Dialogflowを使った自然言語処理(2) CX版
Dialogflowには、小規模でシンプルなエージェントに適した”ES"と、大規模で複雑なエージェントに適した”CX"と、2つのエディションがあります。運用コストにも違いがありますので、どちらを選択すべきか悩むこともありますが、会話の規模よりも、会話の複雑さで選択すべきなんじゃないかなと考えています。
CXには、ESにない概念、「Flow」と「Page」とがあります。また、それらを可視化するための画面コンソールも備わっています。特に、Page中心の会話構造は、複雑な状態遷移をする会話を実現するのに適しているかと思います。一方、ユーザの意図(Intent)が多くても、ツリー構造のように一方向のシンプルな会話、もしくはフラットな会話であれば、ESの方が簡単で安価かもしれません。例えば、よくある電話アンケートのようなものです。
もう一つ、自然言語処理という観点で言うと、ESとCXでは使われる機械学習のモデルに違いがあるようです。CXの方は最新のBERTベースのNLUモデルが使われていると記載されています。違いがわかるかどうかは疑問ですが、こちらも試してみたいと思っています。(ESとCXの機能比較はこちら)
Flow と Page
Pageは会話における一つの状態を表しています。ユーザの入力意図やイベントによって、Pageが遷移します。一連のPage遷移がFlowとなります。
定番の例としては、「ピザの注文」Flowがあります。(公式ドキュメント)
全体が一つのFlowで、青い四角がPageです。Pageには、次のPageに遷移する条件、その時のエージェントの反応(Fufillment)などが定義されています。
会話のサンプル
会話のサンプルとして、友達を映画に誘ってみます。全体のFlowは、以下の通りです。

挨拶をしてstartに遷移します。start page内では、ユーザの入力には適当な相槌を打っています。ユーザが「暇だ」という意図の発言をすれば、inviteに遷移します。
invite状態に入ると、いきなり映画に誘います。Noなら、このFlowを終了します。Yesなら、place_dateに遷移します。
place_dateでは、約束の日と、待ち合わせ場所を決めます。両方が決まりましたら、確認メッセージを出力して、Flowを終了します。
結果の会話はこんな感じです。

会話が終了した時のステータスは以下の通り。

断る時のパターンはこんな感じ。

各Page毎の定義
start page

start pageには2つのRouteがあります。Default Welcome intentは、一般的な挨拶にマッチします。 no_plan (暇)intentがマッチした時に、invite pageに遷移します。また、どちらのRouteにもマッチしなかった時には適当に相槌を返すように、sys.no-match-defaultイベントハンドラのFulfillmentに幾つかの相槌ワードを設定しています。
invite page

invite pageはの Entry fulfillmentに「映画に誘うセリフ」を設定しています。ユーザの返事がYesの場合にはplace_dateに遷移し、Noの場合には、End Flowに遷移して会話を終了させています。
place_date
place_dateでは、約束の日付と場所とをパラメータとして定義します。2つのパラメータともRequiredにチェックを入れておきます。

この状態でも、「やっぱりやめる」ということもありますので、No_I_don't IntentをRouteに設定しておきます。
2つのパラメータが設定されたら遷移する条件は、以下の様に設定します。公式ドキュメントはこちらです。

Intentとentityについては、従来のDialogflow ESとほぼ同じなので説明は割愛しますが、以上の知識だけで、基本的な会話の実装が可能かと思います。
実際に会話を作ってみて、どのようなFlowにするのか、少し悩みました。これだけの簡単な例でも、ベストプラクティスではないかもしれません。
次はwebhookを試してみたいと思います。