OBotMLでダイアログ・フローを記述する方法
OBotMLでは、単純な構文を使用して、変数を設定し、状態を定義します。これはYAMLのバリアントであるため、ダイアログ・フローを定義するときは、YAMLの空白設定規則に注意してください。最初から始める必要はありません。かわりに、デフォルトのダイアログ・フロー定義を基本テンプレートとして使用できます。
contextノードおよびstatesノードがすでに含まれているため、既存のボイラープレートを削除して独自のコンテンツを追加できます。構文的に正しい状態定義を構築するには、+コンポーネント・メニューのコンポーネント・テンプレートを使用します。変数の設定および状態の定義に関するヒントは、ダイアログ・フローの構文を参照してください。
ダイアログ・フローの構文
| 操作手順 | これを使用 |
|---|---|
| ダイアログ・フロー全体でコンテキストを保持する変数を設定します。 |
contextノード内で、次の構文を使用します: variablename: "variableType" 例:
変数をエンティティ( |
| スキルのエラー・ハンドラを定義します。 |
エラーを処理する状態を指す
defaultTransitionsノードを定義します。通常、この状態はダイアログ・フロー定義の終わりに追加します。例:予期しないアクションのダイアログ・フローの構成を参照してください。 |
| 解決されたインテントの値を保持する変数を定義します。 |
contextノード内で、nlpresultエンティティを指定する変数を定義します。その名前が示すように(nlpは自然言語処理を表します)、このエンティティはインテント・エンジンによって解決されたインテントを抽出します。ほぼすべての参照ボットは、nlpresult変数を宣言します。例: |
| ユーザー入力に基づいてダイアログ・フローを制御します。 |
通常(常にではありませんが)、インテント・エンジンの結果を返す YAMLモードでのダイアログ・フローの構造で説明されているように、フローの |
| 未解決インテントを処理するスキルを作成します。 |
次に例を示します:
|
| コンポーネントが変数値にアクセスできるようにします。 |
式で
.valueプロパティを使用します(${crust.value})。デフォルト値を置き換えるには、${variable.value!\"default value\"}を使用します。たとえば、thickは${crust.value!\"thick\"}のデフォルト値です。例:変数に対してnull値が返される可能性がある場合は、Apache FreeMarkerのデフォルト演算子( |
| 再訪に備えてユーザー値を保存します。 |
状態定義内に、
user.という接頭辞を付けた変数定義を追加します。ユーザー値を設定するための組込みYAMLコンポーネントを参照してください。例:ユーザー変数の詳細は、PizzaBotWithMemory参照ボットのダイアログ・フローを参照してください。 |
| ダイアログ・フローを終了し、ユーザー・セッションを終了します。 |
次に例を示します:
|
フロー・ナビゲーションおよび遷移
ダイアログ・フロー内の特定のパスでダイアログ・エンジンを設定するには、状態の遷移プロパティを設定します。遷移は、変数値が設定されている場合または設定されていない場合に、ダイアログがどのように分岐するかを記述します。これにより、会話の典型的なルート(ハッピー・フロー)をプロットしたり、値の欠落や予期しないユーザーの動作に対応する代替ルートを設定できます。
| 手順は次のとおりです... | ...この遷移を使用 |
|---|---|
| 実行する次の状態を指定します。 | next遷移(next: "statename")を設定して、nextキーで指定された状態にジャンプするようにダイアログ・エンジンに指示します。次の遷移に示すように、return遷移を含む状態を除き、任意の状態にnext遷移を追加できます。
|
| 会話をリセットします。 | return遷移を使用してコンテキスト変数に設定された値をクリアし、ダイアログ・フローをリセットします。この遷移に任意の文字列値を指定できます。return: "done"遷移を定義すると、ユーザー・セッションが終了し、ダイアログ・エンジンがフローの最初に配置されます。
|
| 条件付きアクションをトリガーします。 | 特定の状態へのナビゲーションをトリガーするactionsキーを定義します。コンポーネントがその処理を完了すると、ダイアログ・エンジンに次に移行する場所を指示するアクション文字列が返されます。アクション・キーを定義しない場合、ダイアログ・エンジンはデフォルトの遷移またはnext遷移(存在する場合)を使用します。アクションは必要な数だけ定義できます。一部の組込みコンポーネントには特定のアクションが用意されています。たとえば、Apache FreeMarker式を評価するSystem.MatchEntityなどのコンポーネントは、matchアクションおよびnomatchアクションを使用します。System.OAuthAccountLinkにはtextReceivedアクション、passアクションおよびfailアクションがあります。ユーザー・インタフェース・コンポーネントは独自のアクションを使用します(「共通レスポンス・コンポーネントの遷移」を参照)。コンポーネント・テンプレートをガイドとして使用します。actions遷移は、return遷移を含む状態を除き、任意の状態で定義できます。
|
| エラーを処理します。 | コンポーネントがエラーをスローすることがあります。これは、システム関連の問題や障害(無効なパスワード、無効なホスト名または通信エラー)が原因で発生することがあります。エラー処理状態を指定するerror遷移を設定すると、スキルが問題を正常に処理できるようになります:error遷移を設定しない場合、スキルは予期しないエラー・プロンプトを出力し(Oops! I’m encountering a spot of trouble)、セッションを終了します。error遷移は、return遷移を含む状態を除き、任意の状態内で定義できます。
一部のコンポーネントには、アクションとして定義されたエラーがあります。これらの組込みエラーの遷移は、コンポーネント固有のエラーを処理します:
|
next遷移に従います:state_name:
component: "component name"
properties:
component_property: "value"
component_proprety: "value"
transitions:
next: "go_to_state"
error: "go_to_error_handler"
actions:
action_string1: "go_to_state1"
action_string2: "go_to_state2"複数の遷移を定義できますが、
return遷移は例外です。return遷移をerror遷移、next遷移またはactions遷移と組み合せることはできません。
次の遷移
next遷移を使用して、デフォルトの次の状態を指定します。状態がerror遷移、actions遷移およびnext遷移を組み合せた場合、next遷移は、コンポーネントがerror遷移またはactions遷移を満たす文字列を返すことができない場合にのみトリガーされます。
next遷移がトリガーされるようにするには、defaultTransitionノード内にnextアクションを定義します。
context:
variables:
name: "string"
defaultTransitions:
next: "nextRules"
states:
getName:
component: "System.Text"
properties:
prompt: "What's your name please?"
variable: "name"
transitions:
next: "printName"
printName:
component: "System.Output"
properties:
text: "Hello ${name.value}."
transitions:
return: "done"
nextRules:
component: "System.Output"
properties:
text: "Hello ${name.value}. I told you! Next transitions rule the game!"
transitions:
return: "done"予期しないアクションのダイアログ・フローの構成
| シナリオ | 解決方法 |
|---|---|
| ユーザーが、ボタンをタップするのではなくテキストを入力するという適切でない方法で応答します。 | ボットがこれを正常に処理できるようにするには、次のCrcPizzaBotのスニペットのtextReceived: Intentのように、System.Intentコンポーネントがテキスト入力を解決できる状態にルーティングします:
|
| ユーザーが、現在のレスポンスのボタンをタップすることが想定されているにもかかわらず、以前のメッセージまでスクロール・バックしてそのオプションをタップします。 |
デフォルトでは、デジタル・アシスタントは順不同のメッセージを処理しますが、「順不同のアクションの検出方法」の説明に従って、この動作をオーバーライドまたはカスタマイズできます。
たとえば、デフォルトの
system.outofOrderMessage遷移を追加すると、順不同のすべてのメッセージを処理する単一の状態(前述のOBotMLのスニペットのHandleUnexpectedAction状態など)に遷移するようにダイアログ・エンジンに指示します。この状態を作成するには、様々な方法を使用できます:
|
YAMLダイアログ・フローからの別のスキルからのスキルのコール
同じデジタル・アシスタント内の第2スキルでなんらかの作業を実行するために、エンゲージしているスキルを一時的に離れる明示的オプションをユーザーに提供する場合があります。たとえば、ショッピング・スキル内でいくつかの選択を行った後、銀行取引スキルにジャンプして(購入に十分な金額があることを確認するため)、その後ショッピング・スキルに戻ってオーダーを完了できるようにするボタンを表示できます。
YAMLダイアログ・フローでこれに対処するために、同じデジタル・アシスタント内の別のスキルとの対話を開始して、その後元のフローに戻るようにスキルのアクションを構成できます。
この仕組みは次のとおりです:
-
System.CommonResponseコンポーネントを使用して、別のスキルでなんらかの作業を実行するためのボタンをユーザーに表示します。このボタンはポストバック・アクション(ターゲット・スキルに誘導する発話を提供するようにペイロードを構成する)に基づきます。そのターゲット・スキルにルーティングされる可能性を最大化するために、発話にそのスキルの起動名を含める(つまり、明示的な起動)ことが理想的です。基本的に、これを行うことによって、目的のインテントをトリガーする発話をハードコードします。
そのコードのフォーマットは次のとおりです:
component: "System.CommonResponse" properties: metadata: ... responseItems: - type: "cards" ... actions: ... - label: "Press me to switch to different skill" type: "postback" payload: action: "system.textReceived" variables: system.text: "utterance with invocation name that you want passed to the digital assistant" ...system.textReceivedアクションを使用してsystem.text変数にテキストを指定することで、ポストバックが、デジタル・アシスタントによって正しくルーティングできるユーザー・メッセージとして処理されます。ノート
このようにsystem.textReceivedを使用する場合、system.textがポストバック・ペイロードで定義できる唯一の変数です。ペイロード内のその他の変数はすべて無視されます。 textReceived遷移を、System.Intentコンポーネントを含む状態に設定します。transitions: actions: .... textReceived: "Name of the state for the System.Intent component"これは、デジタル・アシスタントにターゲット・スキルが含まれていない場合に、デジタル・アシスタントによって適切なフォールバック・レスポンスが提供されるようにするために必要です。
これが機能するには、スキルの
System.IntentコンポーネントでdaInterceptプロパティが"always"(デフォルト)に設定されている必要があります。
ターゲット・スキルがデジタル・アシスタント内にある場合、デジタル・アシスタントは明示的な起動を認識し、リクエスト(通常はコンポーネントによって処理される)を制御して、このリクエストをターゲット・スキルのSystem.Intentコンポーネントにルーティングします。ターゲット・スキルのフローが終了すると、ユーザーはコール・スキルに戻ります。
ターゲット・スキルがデジタル・アシスタント内にない場合(またはコール・スキルがデジタル・アシスタントなしで公開されている場合)、コール・スキルのSystem.Intentコンポーネントが起動され、インテントはunresolvedIntentに解決されます。
ヒント:
ターゲット・スキルの起動名がデジタル・アシスタントに追加される際に変更されるケースを処理するには、カスタム・パラメータを使用して、system.text変数でスキルの起動名を渡します。
たとえば、ピザ・スキルでda.CrcPizzaCashBankInvocationNameというパラメータを作成し、これにデフォルト値CashBankを指定します。次のようにパラメータを参照できます:
system.text: "ask ${system.config.daCrcPizzaFinSkillInvocationName}, what is my balance"スキルの起動名が変更された場合は、単に、新しい起動名に一致するように、カスタム・パラメータの値を変更します。
カスタム・パラメータを参照してください。
system.text変数で明示的な起動を使用すると、そのボタンを含むメッセージが2回表示される場合があります:
- 他のスキルに移動するためのボタンが表示されるとき。
- 他のスキルでフローを完了したとき。
system.text変数で、明示的な起動ではなく暗黙的な起動を使用します。暗黙的な起動とは、スキルの起動名(または文字の間隔や大文字の使い方が異なる起動名のバリエーション)を使用せずに、特定のスキルと適切に一致する発話です。
例: 別のスキルからのスキルのコール
たとえば、ここでは、ユーザーがオーダーを完了する前に銀行口座残高を確認するオプションを提供する、ピザのオーダー(OrderPizza)インテントを示します。口座残高は、別のスキル(CashBank)によって提供されます。ユーザーがCheck Balanceオプションを選択すると、「ask CashBank, what is my balance」というテキストがデジタル・アシスタントにポストされ、ユーザーはCashBankスキル内の該当するインテントにルーティングされます。
OrderPizza:
component: "System.CommonResponse"
properties:
metadata:
...
responseItems:
- type: "cards"
headerText: "Our pizzas:"
cardLayout: "vertical"
name: "PizzaCards"
actions:
- label: "More Pizzas"
...
- label: "Check bank account balance"
type: "postback"
payload:
action: "system.textReceived"
variables:
system.text: "ask CashBank, do I have enough money?"
...
processUserMessage: true
transitions:
actions:
order: "AskPizzaSize"
more: "OrderPizza"
textReceived: "Intent" # where the value of textReceived is the name CashBank's System.Intent state
...ピザ・スキルがCash Bankスキルと同じデジタル・アシスタント内にあると仮定すると、デジタル・アシスタントをテスターで開き、ピザ・スキルにアクセスしてから「Check bank account balance」をクリックした場合のように表示されます。

図skillment-skill.pngの説明
テスターの「ルーティング」タブで、明示的な起動が認識され、明示的な起動が優先されていることを確認できます:
さらに、Cash BankスキルのCheck Balanceインテントが一致していることを確認できます:
YAMLダイアログ・フローのユーザー・スコープ変数
会話が終了すると、ユーザー入力から設定された変数値は破棄されます。これらの値が破棄されると、スキル・ユーザーは、スキルに戻るたびに同じステップを再びたどる必要があります。ダイアログ・フローでユーザー・スコープ変数を定義すると、こうしたユーザーの手間を省くことができます。スキルでこのような変数を使用して、前のセッションからのユーザー入力を格納することで、ユーザーは迅速に会話を進めることができます。
contextノードではなく個々の状態内で定義するユーザー・スコープ変数には、user.という接頭辞が付きます。PizzaBotWithMemoryダイアログ・フローからの次の抜粋のchecklastorder状態には、前のユーザー・セッションからのピザ・サイズを保持するuser.lastsize変数が含まれます。user.変数はユーザーIDを保持します。そのIDはチャネルに固有であるため、会話に戻ったり、同じチャネルで実行するスキルで前のエントリを使用してオーダーをスキップできますが、異なるチャネルでこれを行うことはできません。
main: true
name: "PizzaBot"
parameters:
age: 18
context:
variables:
size: "PizzaSize"
type: "PizzaType"
crust: "PizzaCrust"
iResult: "nlpresult"
sameAsLast: "YesNo"
states:
intent:
component: "System.Intent"
properties:
variable: "iResult"
transitions:
actions:
OrderPizza: "checklastorder"
CancelPizza: "cancelorder"
unresolvedIntent: "unresolved"
checklastorder:
component: "System.ConditionExists"
properties:
variable: "user.lastsize"
transitions:
actions:
exists: "lastorderprompt"
notexists: "resolvesize"
lastorderprompt:
component: "System.List"
properties:
options: "Yes,No"
prompt: "Same pizza as last time?"
variable: "sameAsLast"
transitions:
next: "rememberchoice"
rememberchoice:
component: "System.ConditionEquals"
properties:
variable: "sameAsLast"
value: "No"
transitions:
actions:
equal: "resolvesize"
notequal: "load"
...
load:
component: "System.CopyVariables"
properties:
from: "user.lastsize,user.lasttype,user.lastcrust"
to: "size,type,crust"
transitions:
...ユーザー値を設定するための組込みYAMLコンポーネント
"${user.age.value}"などの式を使用して、格納されているユーザー値を設定する、次のコンポーネントのvalueプロパティを定義します。
| コンポーネント | 用途 |
|---|---|
| System.SetVariable | 格納されているユーザー値を設定します。 |
| System.ResetVariables | 格納されているユーザー値をリセットします。 |
| System.CopyVariables | 格納されているユーザー値をコピーします。 |
| System.Output | 格納されているユーザー値をテキストとして出力します。 |
| System.ConditionExists | ユーザー・スコープ変数がすでにコンテキストに存在するかどうかをチェックします。 |
| System.ConditionEquals | ユーザー・スコープ変数をチェックします。 |
| System.Switch | 格納されている値を使用して、ある状態から別の状態に切り替えます。 |
YAMLダイアログ・フローでのテキストのみのチャネルの自動番号付け
自動採番フレームワークでは、ボタンに接頭辞が付けられ、オプションが番号付きでリストされるため、テキストのみのチャネルでスキル・ボットを実行できます。ユーザーがタップ・ジェスチャを使用できない場合でも、番号を入力することでボタンのポストバック・アクションをトリガーできます。たとえば、CrcPizzaBotがボタンをサポートするチャネルで実行されている場合は、PizzasおよびPastasが表示されます。
ただし、これがテキストのみのチャネルで実行されている場合は、PizzaオプションおよびPastaオプションがテキストとしてレンダリングされ、これらの先頭に連番が付けられます(1. Pizza 2. Pasta(パスタ)。 
自動採番はテキストのみのチャネルに限定されていないため、ボタンがサポートされている場合でも、ユーザーが選択を入力する別の方法を追加できます。たとえば、ユーザーはPizzaをタップするか、1と入力できます。 
YAMLダイアログ・フローの自動採番の設定
YAMLダイアログ・フローの場合、自動採番機能は、グローバル・スケール(ダイアログ・フロー定義で指定したすべてのコンポーネントに影響を及ぼす)またはポストバック・アクションをトリガーするコンポーネントのコンポーネント・レベル(System.List、 System.CommonResponse、System.ResolveEntities、System.QnA、System.Webview、System.OAuthAccountLinkComponentおよびSystem.OAuth2AccountLinkComponentコンポーネント)で設定できます。
-
contextノードに
autoNumberPostbackActions: "boolean"を追加します。これ(textOnlyやautoTranslateなど)は、すべてのボットで使用できる共通の変数です。context: variables: pizzaSize: "PizzaSize" pizzaType: "PizzaType" pizzaCrust: "PizzaCrust" pizzaCheese: "CheeseType" autoNumberPostbackActions: "boolean" iResult: "nlpresult" -
autoNumberPostbackActionsプロパティをtrueに設定します:type: component: "System.List" properties: prompt: "What Type of Pizza do you want?" options: "${pizzaType.type.enumValues}" variable: "pizzType" autoNumberPostbackActions: "true" footerText: "Enter a number or tap your selection." transitions: ...特定のコンポーネント(システム・コンポーネントまたはカスタム・コンポーネントのいずれか)の自動採番をオーバーライドする必要がある場合は、autoNumberPostbackActionsプロパティをfalseに設定します。System.CommonResponseで特定のポストバック・アクションの自動採番をオーバーライドするには、skipAutoNumberプロパティを追加して、そのアクションを指定します。ノート
自動採番はサーバー側の処理によって適用されるため、クライアント側のURLアクションではなく、ポストバック・アクションでのみ機能します。そのため、2つのボタン・アクション(1つはURLアクション、もう1つはポストバック・アクション)をレンダリングするコンポーネントでは、様々なUI要素の採番が一貫していないため、ユーザー・エクスペリエンスが最適ではなくなります。ログインURLアクションと取消ポストバック・アクションの両方をレンダリングするOAuthコンポーネントの場合、取消アクションの先頭にのみ番号が付けられます。このような場合に一貫性を維持するには、autoNumberPostbackActionsプロパティをfalseに設定します。 -
自動採番を条件付きで有効にするには、
autoNumberPostbackActions変数に現在のチャネルを設定します。例:setAutoNumbering: component: "System.SetVariable" properties: variable: "autoNumberPostbackActions" value: "${(system.channelType=='facebook')?then('true','false')}"autoNumberPostbackActions変数の設定後、これを参照してpromptテキストを変更できます:
同様に、フッター・テキストに条件を設定できます:prompt: "Hello ${profile.firstName}, this is our menu today<#if autoNumberPostbackActions.value>. Make your choice by entering the menu option number</#if>:"footerText: <#if autoNumberPostbackActions.value>"Make your choice by entering the menu option number."</#if>
YAMLダイアログ・フローでのテキストのみのチャネルのコンテンツのレンダリング
textOnly変数を参照する場合は、チャネル固有のメッセージを表示または非表示にできます。テキストのみのメッセージに基づいてフローを分岐する前に、textOnlyをコンテキスト変数として宣言し、その値を設定する必要があります。基本的なステップは次のとおりです:
-
contextノードにtextOnly: "boolean"変数を追加します。context: variables: autoNumberingPostbackActions: "boolean" textOnly: "boolean" -
System.SetVariableやSystem.Switchなどの変数設定コンポーネントで
textOnlyを参照します。 -
system.messageプロパティを使用して、ユーザー・メッセージ全体を表示します。次のスニペットは、system.channelType式内に、テキストのみのチャネル(この場合はTwilio)が使用されているかどうかを示すブールを設定する方法を示しています。setTextOnly: component: "System.SetVariable" properties: variable: "textOnly" value: "${(system.channelType=='twilio')?then('true','false')}"自動採番を条件付きで有効にするには、ユーザー・メッセージ・チャネルを参照します。例:setAutoNumbering: component: "System.SetVariable" properties variable: autoNumeringPostbackActions value: "${(system.channelType=='twilio')?then('true','false')}"


