会話フローの実装
ここでは、デジタル・アシスタントで会話フローを実装するためのベスト・プラクティスをいくつか示します。
適切に設計されたモデルを使用すると、通常のインテントの会話フローの構築を開始できます。会話は、Oracle Digital Assistantスキルの一連のダイアログ・フロー・ステップによって定義されます。
ビジュアル・モードの使用
スキルを作成すると、「ビジュアル」またはレガシーYAML設計モードを使用するように設定できます。常に「ビジュアル」モードを使用する必要があります。これは、デフォルト・オプションでもあります。ビジュアル・モードには、レガシーYAMLモードよりも次のような多くの利点があります。
- フロー状態がキャンバス、コンポーネント・プロパティ・エディタおよび設計時検証で視覚的に表されるビジュアル設計エクスペリエンス。
- ダイアログ・フロー全体を複数のフローに分割する機能。
- 複数のフローで使用される処理を処理するために他のフローからコールできる再使用可能フローを作成する機能。
- 非常に読みやすく、メンテナンス性も簡単です。
ダイアログ主導の会話
ダイアログドリブンの会話では、一連のダイアログ・フロー状態を介してユーザーをナビゲートすることにより、タスクを完了するために必要なユーザー情報を収集します。各状態は、ボット・レスポンスおよびユーザー・プロンプトをレンダリングしたり、条件、ロジックおよびその他の機能を処理するためにコンポーネントにリンクされます。
このアプローチでは、プロジェクトの計画フェーズで設計したユース・ケースから導出するフィルム・スクリプトのようなダイアログ・フローを開発します。会話内の個々のステップはダイアログ・フローによって制御されるため、ダイアログ・フローはすぐに大きくなる可能性があります。サイズが管理できないダイアログ・フローを回避するには、ユースケースを異なるスキルに分割する必要があります。
ダイアログ・フローの状態名に対するネーミング規則の使用
ドキュメントの一部として、ダイアログ・フローの状態の名前を検討してください。ダイアログ・フロー状態の名前がコンテキストを提供している場合、コード・レビュー担当者は、ダイアログ・フローの状態が何をしているか、およびどの会話フローに属しているかを簡単に理解できます。例:
promptForOrderNumber
findOrder
cancelOrder
また、スキルがYAMLモードの場合は、関連するダイアログ・フローの状態をBotML内で緊密にまとめておくことを検討してください。これにより、コードを確認するときに会話のアクションの流れに従うことが容易になります。
変数を使用するためのベスト・プラクティス
変数には、スキルがユーザーから収集する情報が含まれます。可能な場合は常に、収集する情報にエンティティ・タイプの変数を使用します。これは、次の理由で行います。
-
ユーザー入力が検証され、無効なデータ入力の後にユーザーがプロンプト再表示されます。
-
デジタル・アシスタントは、順序付けされていないナビゲーションを処理します。つまり、ユーザーは、コーディングを必要とせずに、既存の会話中に新しい会話を開始できます。
-
コンポジット・バッグ・エンティティおよびカスタム・エンティティにラップされた組込みエンティティの場合、プロンプト、検証エラー・メッセージおよび明確化解除プロンプト(共通レスポンス・コンポーネントおよびエンティティの解決コンポーネントによって自動的に表示される)を定義できます。
-
エンティティをインテントに関連付けると、エンティティ・タイプの変数を初期ユーザー・メッセージからスロットできます。ビジュアル・ダイアログ・モードで開発されたスキルの場合、このスロッティングは「共通レスポンス」および「エンティティの解決」コンポーネントで自動的に行われます。YAMLダイアログ・モードで開発されたスキルの場合は、入力コンポーネントの
nlpResultVariable
プロパティを使用してこの機能を取得します。
アクション・アイテムでのキーワードの使用
共通レスポンス・コンポーネントおよびカスタム・コンポーネントを使用すると、アクション・アイテムのキーワードを定義できます。キーワードを使用すると、ユーザーは数値や略語などのショートカットを送信してアクションを起動できます。つまり、テキストのみのチャネルまたは音声を使用したり、表示されたアクション・アイテム・ラベルの全文を入力したりできなかったアクション・アイテムを押す必要はありません。
共通レスポンスまたはカスタム・コンポーネント(エンティティ・イベント・ハンドラを含む)を使用してキーワードを定義する場合は、次の点を考慮してください。
-
キーワードは、ラベルに同じテキストを表示する必要はありません。
-
キーワードは、大/小文字を区別しません。大/小文字が区別されるすべてのバリアントでキーワードを定義する必要はありません。
-
複数言語のボットを作成する場合は、キーワードを英語のみで定義することはできません。多言語キーワードをサポートするために、共通レスポンス・コンポーネント(
${rb('resource_key_name')}
)のkeyword
プロパティからリソース・バンドル文字列を参照できます。次に、リソースバンドル文字列には、キーワードのコンマ区切りリストが含まれます。 -
ラベルの前にインデックス番号を追加するなど、キーワードを使用できることを示す視覚的な手がかりを提供します。
たとえば、オーダーを発行または取り消すアクション・メニューは、「1」というラベルで定義できます。送信、 "2Cancel"また、キーワードは「1,1.、send」および「2,2.、cancel」として定義できます。そのため、注文を取り消すには、「cancel」、「2」、または「2」と入力します。
ノート
この場合、ラベルは1であるため、sendおよびcancelもキーワードとして定義する必要があります。「送る」と「2」「取消」ではなく、「取消」のみ送信します。 -
キーワードは、文で使用しても機能しません。たとえば、ユーザーが「I'd prefer to cancel my order」と記述した場合、「cancel」はキーワードとして検出されません。ユーザーがオプションから選択するキーワードのかわりに会話を使用する場合、次の項で説明するように、NLUベースのアクション・メニューを検討します。
動的に作成されるアクション・アイテムの索引ベースのキーワードの作成方法については、次の選択肢があります。
-
スキルの「タスク・フローのポストバック・アクションでの自動採番の有効化」構成設定を使用して、スキルの自動採番を有効にします。これにより、キーワードをキーワードのリストに追加し、索引をラベルに追加するようにコンポーネントが構成されます。
-
Apache FreeMarker式を使用して、索引番号を追加したり、名前にアクション・アイテム値を含むリソース・バンドル文字列を参照したりします。
NLUベースのアクション・メニューの検討
通常、アクション・メニューでは、ユーザーが押すことができるアクション・アイテムを使用して、特定の会話へのナビゲーションを実行したり、操作を送信、確認または取り消すことができます。アクション・アイテムが押されると、変数を更新するためのオプションのペイロードおよび遷移先のダイアログ・フロー状態を決定するアクション文字列を含むメッセージがスキルに送信されます。
ユーザーが、アクション・アイテム・ラベルまたはアクション・アイテムに定義されたキーワードと一致しないメッセージを入力した場合、次の遷移が行われます。たとえば、「経費精算書の送信」および「経費精算書の取消」をラベルとして使用するアクション・アイテムのペアを想像します。ユーザーが「はい、送信してください」と入力した場合、経費精算書の送信でマークされたアクション・アイテムではなく、次の遷移がトリガーされます。このようになる理由は、ユーザーがボタンまたはアクション・アイテムを押す必要がある実装が会話型ではないためです。
堅牢で真に会話型のアクション・メニューを作成するには、値リスト・エンティティに基づいて作成する必要があります。リスト値は、実行するアクションを示し、シノニムによって、ユーザーがアクションを起動するメッセージで使用するキーワードが定義されます。
これを行うには、最初に値リスト・エンティティを作成し、次にダイアログ・フローで変数を定義します。次に、共通レスポンスまたはエンティティの解決コンポーネントを使用して、オプションのリストを表示できます。作成する変数は、コンポーネントの変数プロパティの値として構成する必要があります。このようにして、ユーザーが「はい、送信してください」と入力して、変数に格納されている値をチェックするダイアログ・フロー状態に移動すると、次の遷移がトリガーされます。
変数に格納される値は、value-listエンティティに定義されている値の1つです。Switchコンポーネントを使用すると、会話を続行する次のダイアログ・フロー状態を定義できます。
ユーザーが値リスト・エンティティにないメッセージまたはそのシノニムの1つとしてメッセージを入力すると、アクション・メニューが再度起動されます。値リスト・エニティを使用したため、エンティティに定義されたエラー・メッセージを使用すると、ユーザーが期待される内容を理解するのに役立ちます。また、値リスト・エンティティに対して複数のプロンプトを構成できるため、代替プロンプトや、アクション・メニューの表示を取り消す方法に関する情報など、追加情報を徐々に明らかにするメッセージも表示できます。
値リスト・エンティティの値にリソース・バンドル文字列名を作成する場合は、次のいずれかの式を使用して、アクション・アイテムに表示されるラベルを翻訳できることを確認できます。
${rb(enumValue)}
${rb(enumValue.value.primaryLanguageValue)}
(共通レスポンス・コンポーネントのfullEntityMatches
プロパティがtrue
に設定されている場合)
アクション・アイテムの値を動的に設定するには、共通レスポンス・コンポーネントを使用する方が簡単です。エンティティ・イベント・ハンドラをプログラミングする場合は、「エンティティの解決」も使用できます。
NLUベースのアクション・メニューを使用すると、ユーザーはアクション・アイテムを押すか、アクション・ラベルまたはキーワードと完全に一致する必要のないメッセージを入力できます。
新規会話の現在の会話の中断
よくある質問は、ユーザーが入力を求められた場合に新規または別の会話を開始できるように会話を構成する方法です。しかし、この質問は、技術的なノウハウよりも、あなたが行う必要がある設計上の決定です。次に、設計に関する考慮事項を示します。
-
あなたのスキルはデジタル・アシスタントを通じて公開されていますか?その場合、スキルはデジタル・アシスタントの非連続ルーティングに参加します。これにより、現在のダイアログ・フロー状態についてユーザー・メッセージを正常に検証できなかった場合に、メッセージが別のスキルまたは同じスキルの別のインテントにルーティングされます。この連続しないナビゲーションを実現するには、ユーザー入力がエンティティベースの変数に対して検証されることを確認します。
-
スキルはスタンドアロン・スキルとして公開されていますか。その場合、非連続ナビゲーションが組み込まれていないため、設計する必要があります。これを行うには、ユーザーが新しい会話に分岐できるようにするダイアログ・フローの状態にエンティティ・ベースの変数を使用します。次に、ユーザー入力コンポーネントの
maxPrompts
プロパティを1に設定し、cancel
アクション遷移を構成して新しい会話を開始します。無限ループを引き起こす可能性が最も高いため、取消遷移をインテント状態に直接示すのは間違いです。そのため、インテント状態に戻る前に、変数のリセット・コンポーネントで構成されたダイアログ・フロー状態を使用して、会話に必要なnlpresult
型変数およびその他の変数をリセットしてください。
チャネルで直接公開するスタンドアロン・スキルを作成することはオプションですが、お薦めしません。主な理由は、デジタル・アシスタントの使用によって得られる会話と開発のすべてのメリットを逃すことです。あなたが見逃すいくつかの利点は次のとおりです。
-
非連続ナビゲーション。デジタル・アシスタントが現在の会話を一時停止し、トピックを別の会話に一時的に変更する機能です。
-
開発作業を複数のスキルにパーティション化できるモジュラ開発により、ボットに対する増分開発および改善が可能になります。
-
ヘルプ・リクエストの自動処理。
-
よくある質問、スモール・トーク、エージェント統合など、一般的に必要なスキルの再利用。
モデル主導型の会話
モデル駆動型の会話は、ダイアログ駆動型の会話の拡張です。モデル主導型の会話により、記述するダイアログ・フロー・コードの量を減らし、ボット・ユーザー・インタラクションの成熟したドメイン・オブジェクト中心のナビゲーションを提供します。
モデル駆動型の会話と呼ばれる概念は、「エンティティの解決」または「共通レスポンス」コンポーネントを使用してコンポジット・バッグ・エンティティを解決することで会話を処理することです。コンポジット・バッグ・エンティティは、一連のエンティティをグループ化して、オーダー、予約、顧客などを表す実際のオブジェクトを形成するという点で、ドメイン・オブジェクトに似ています。
コンポジット・バッグ内の各エンティティは、「エンティティの解決」または「共通レスポンス」コンポーネントによって自動的に解決されます。つまり、すべてのボット・レスポンスおよびプロンプトは、それぞれにダイアログ・フロー状態を作成せずに生成されます。モデル駆動型の会話では、少ないダイアログ・フロー・コードを記述し、より多くの機能を取得します。
推薦アプローチ
モデル駆動型の会話を作成するためのベスト・プラクティスは、コンポジット・バッグ・エンティティ、エンティティ・イベント・ハンドラおよびエンティティの解決コンポーネントを使用することです。
ResolveEntitiesのかわりに共通レスポンス・コンポーネントを使用することに問題はありませんが、エンティティ・イベント・ハンドラのおかげで、エンティティの解決はほとんどの実装で十分です。
-
コンポジット・バッグ・エンティティは、ユーザーから収集する情報ごとにバッグ・アイテムを持つドメイン・オブジェクトです。各バッグ・アイテムには、必要に応じて表示されるプロンプト、エラー・メッセージおよび明確化プロンプトが定義されています。値リスト・エンティティに基づくコンポジット・バッグ・アイテムの場合、複数選択リストを表示することもできます。コンポジット・バッグ・エンティティの利点は、1つのユーザー・メッセージから多くのバッグ・アイテムのユーザー入力を収集できることです。この機能は順不同抽出と呼ばれ、デフォルトで有効になっています。
-
「エンティティの解決」コンポーネントは、エンティティに定義されているプロンプトの表示、ユーザー入力の検証、エンティティに定義されている検証エラー・メッセージの表示、およびユーザーがメッセージで予想以上に多くの情報を提供した場合の曖昧さ回避ダイアログの表示によって、エンティティを解決します。コンポジット・バッグ・エンティティの場合、エンティティの解決コンポーネントは、コンポジット・バッグ・エンティティ内のすべてのバッグ・アイテムのユーザー・インタフェースを、定義されている順序でレンダリングします。
-
エンティティ・イベント・ハンドラは、コンポジット・バッグ・エンティティに登録され、コンポジット・バッグ・エンティティの解決時にエンティティの解決コンポーネントによってコールされる関数を含むJavaScriptコンポーネントです。このイベントドリブンのアプローチでは、ユーザーがコンポジット・バッグ・エンティティで作業している間に、カスタム・コード・ロジックを実行し、リモートRESTサービスを呼び出すこともできます。エンティティ・イベント・ハンドラについては、このガイドの後半で詳しく説明します。
モデル駆動型の会話の設計方法
モデル駆動型の会話に最適な設計は、コンポジット・バッグ・エンティティに必要なバッグ・アイテムの数を最小限に抑えることです。コンポジット・バッグ・エンティティを、会話に連鎖する個々の会話モジュールとして想像してください。
解決する各コンポジット・バッグ・エンティティの後にユーザーに確認して、会話を続行または中止する機会を提供します。
もちろん、これは「続けるべき」のようなプロンプトと、「はい」ボタンと「いいえ」ボタンのペアで実装しないでください。会話設計者は、2つの会話モジュールを結び付ける、より侵入しにくい移行を作成できます。
メッセージおよびプロンプトのリソース・バンドル
すべてのメッセージおよびプロンプトと同様に、コンポジット・エンティティ・バッグ・アイテムで定義されたプロンプトおよびメッセージにはリソース・バンドル文字列を使用することを強くお薦めします。コンポジット・バッグ・エンティティの例を次に示します。
-
cbe.
<entity_name>.
bag_item_name.errorMessage
-
cbe.
<entity_name>.
bag_item_name.disambiguationMessage
-
cbe.
<entity_name>.
bag_item_name.prompt1
-
cbe.
<entity_name>.
bag_item_name.prompt2
Apache FreeMarkerのベスト・プラクティス
Apache FreeMarkerは、ダイアログ・フローおよびエンティティおよびスキル構成で使用できる強力な式言語です。ただし、Apache FreeMarker式が複雑すぎると問題が発生し、デバッグ・オプションがないためにエラーが発生しやすく、使用が困難になります。
複雑な複数行のApache FreeMarker式を回避し、かわりに次のいずれかのオプションを検討することをお薦めします。
-
複雑なFreeMarker式を分割するには、値を短い名前で変数に保存してから式で使用します。
-
<#/if ...>
ディレクティブを使用して、FreeMarker式の読みやすさを向上させます。 -
エンティティ・イベント・ハンドラをコンポジット・バッグ・エンティティとともに使用して、複雑な検証コードを処理するか、変数に割り当てる値を計算します。
-
?has_content
組込み式を使用して、参照する変数のnull値を確認します。式がfalseに解決される場合は、適切なデフォルト値を指定します(例:?has_content?then(...,<SENSIBLE_DEFAULT_VALUE>)
)。
会話を実装するためのチェックリスト
- ☑フローおよびフロー状態のわかりやすい説明的な名前を選択します。
- ☑ エンティティ・タイプ変数を使用します。
- ☑ エンティティ・タイプ変数のユーザー入力プロンプトは、エンティティからプロンプトを読み取る必要があります。
- ☑モデル主導の会話を構築します。
- ☑値リスト・エンティティからアクション・メニューを作成します。
- ☑ 複雑なApache FreeMarker式は避けてください。
- ☑ リソース・バンドルを使用します。テキスト・メッセージまたはプロンプトは、ダイアログ・フローに直接追加しないでください。
- ☑異なるフローに共通する会話の一部に対して再利用可能なフローを作成します。
さらに学ぶ
- Oracle Digital Assistant Design Campの動画: Oracle Digital Assistantのナビゲーション技術
- Oracle TechExchangeサンプル: モデル主導の会話 –Pasta注文スキル
- Oracle TechExchangeサンプル: モデル主導の会話- 経費精算書スキル
- チュートリアル: ダイアログ・フローの開発
- チュートリアル: コンポジット・バッグ・エンティティの構築
- チュートリアル: 会話マーカーを使用したインサイト・レポートの最適化