Dialogflowを使った自然言語処理(1)ES版

Dialogflowは会話型ユーザインターフェイスを実装するためのプラットフォームです。現時点でDialogflow CX(Advanced)と Dialogflow ES(Standard)の 2 つのエディションが存在しています。まずはESを使ってどのような処理をしているのか確認します。

事前準備

最初に、エージェントを作成します。エージェントは仮想的な対話相手であり、特定のタスク(予約や問い合わせなど)を実行するためのモジュールで、一連の会話を制御することができます。

ここでは、エージェントの名前(nlp-demo)と言語(ja)、Time Zone(Asia /Tokyo)を選択しておきます。CREATEを実行すると、エージェントが作成されGoogle Cloudにプロジェクトが生成されます。

Intent

Intentは日本語では「意図」を意味しています。Dialogflowは、IntentとそのIntentに対する応答とを定義することで、ユーザの意図に沿った応答をします。また複数のIntentを定義した場合、一番マッチするIntentの応答を返します。もし、どのIntentにもマッチしなかった場合、デフォルトで定義されている"Default Fallback Intent" の反応を返します。従って、作成したばかりのエージェントに対して「明日の天気は?」と聞いても「すいません。良くわかりませんでした」と"Default Fallback Intent" に定義されているResponsesのうちの一つを返します。

ここで新しいIntent "tenki"を作成します。Training phrasesに天気を聞く例をいくつか入力してトレーニングさせるのですが、ここでは敢えて「明日の天気を教えてください」の一つだけを入力します。

次にこのtenki intentにマッチしたことを知るために、Text Responsesに「晴れると良いですね」とだけ入力しておきます。IntentをSAVEすると、トレーニングが実行されます。では試してみた結果です。


トレーニング文 「明日の天気を教えてください」

  • マッチした文 「明日の天気は」「天気を教えて」「天気は」「天気」「昨日の天気は」「週末の天気は」
  • マッチしなかった文「明日は晴れるの」「明日は雨だよね」「明日はお天気」

こうして並べてみると、出現している単語だけでマッチングしているのではなく、文型なども含めてマッチングをしているようです。

通常の使い方ではトレーニング文はできるだけ沢山のパターンで入力します。例えば「明日は晴れるの」も天気を聞いていると考えられるのであれば、トレーニング文に追加します。

Diagnostic infoをみると、どのくらいintentにマッチングしたかを知ることができます。intentDetectionConfidence の値は、0〜1の値をとり、完全一致の場合に1となります。今回の事例では「明日の天気は」(0.54796785,)、「天気を教えて」(0.6630541)、「週末の天気を教えてください」(1)となリました。(公式ドキュメント

一つのエージェントの中で多くのintentを登録すると、思い通りにマッチしなくなることがあります。その場合、1)優先度を設定する 2)Contextsを使う などの対策が必要になります。

優先度はIntent名の横についている丸印で設定します。標準は青色(normal)ですが、LowからHighestまで4段階で設定できます。また、Contextsを設定すると、特定の状態の時のみマッチするIntentが作れます。例えば、ユーザから情報を受け取ったのち、「OK」「NG」の2択を得たい場合などに使います。(Contextsに関する公式ドキュメントはこちら。)

Entity

System Entity

Entityは文章の中に含まれるパラメータを取得するためのものと理解できます。先ほどの例で言うと、「明日の天気を教えてください」をトレーニングした際に、「明日」の部分が自動的にハイライトされて、Action and parametersに定義されています。

ここでENTITY列が@sys.date-timeとありますが、「明日」を日時を表す単語として理解していることを示しています。

従って、「明日」の部分が「明後日」に変わっても「週末」に変わっても、同じく日付を表す単語なのでマッチングすると言うことになります。

そして、文中に@sys.date-timeに属する単語が出てくると、それを共通の書式(例えば「2022-09-27T12:00:00+09:00」)に変換してパラメータにセットします。こうすることで、天気予報を問い合わせる場合に「いつの」という情報をパラメータとしてバックエンドのサーバに送ることができます。

他にも、「大阪の天気を教えて」をTraining phrasesに入力すると、「大阪の」がハイライトされて@sys.locationとして認識されパラメータlocationが定義されます。

System Entityに関する公式ドキュメントはこちらです。日本語には対応していないEntityもあります。

@sys.date-timeの値は、入力によって日付("2018-04-05T12:00:00-06:00")や期間({"endDate":"2018-08-31T12:00:00-06:00","startDate":"2018-08-01T12:00:00-06:00"})をとり得ます。日付だけを取得したい場合には、@sys.dateを使います。同様に、@sys.location内のcityだけを使いたい場合には、@sys.geo-cityとします。

Custom Entity

独自のEntityを使う場合には、Custom Entityで定義します。例えば、何かのサイズを「大」「中」「小」の三段階で取得したいとします。

まず、CREATE ENTITY で新しいEntityを作成します。Entity名はsizeとしておきます。サイズは人によっていろんな言い方がありますので、”Define synonyms”にチェックを入れて、それらを全て登録しておきます。

新たにIntent "size"を作成し、Training phrasesに「大きいのにしてください」「Mサイズでお願いします」と入力します。”大きい”、”M"がハイライトされ、パラメータにsizeが追加されます。

SAVE後にテスト入力(Try it now)に「スモールで」と入力すると、sizeインテントとマッチし、パラメータ sizeは「小」の値となります。

ちなみに、 Entityの定義画面で、”Allow automated expansion”にチェックを入れて「ちっこいのが良いです」とすると、sizeの値が「ちっこいの」になります。sizeの取り得る値が自動で拡張されるようです。

また、”Fuzzy matching”にチェックを入れると、「でっかい」ではなく「でかい」としてもマッチします。

Fulfillment

固定の会話であれば、IntentsとそのResponcesとを設定すれば、ある程度の会話は実現できます。また、Entityでユーザの発話をパラメータとして取り込み、それをResponcesで使えば、より会話らしく聞こえます

例えば、先ほどのsize intent のresponcesに「『$size』ですね。承知しました。」としておくと、

ユーザ :「Lサイズでお願いします」

エージェント:「『大』ですね。承知しました」

と言った会話が生成されます。

しかし、実際のシステムではバックエンドのデータベースなどとの連携が必須になるでしょう。外部のシステムと連携させる場合には、Fulfillmentのwebhookを使います。Intentの設定で"Enable webhook call for this intent"をオンにすると、そのIntentとマッチした場合には、Fulfillmentの設定画面で指定したURLに、リクエストをPOSTします。

Intentの設定

DialogflowとHuggingface API(Text 2 Textモデル)とを繋ぐ APIの例を以下の記事にあげています。

Chalice使ってflask APIをLambdaにデプロイする

前回、Netlifyの記事を書きましたが、今回は、Chaliceです。 接続としては、以下の通りです。 <LINE> ー <Dialogflow> ー <heroku> ー <V […]

このAPIのURLを以下の様にFulfillment画面で設定します。

Dialogflow ESで定義可能なwebhookは一つだけです。Intentごとに様々な処理を行うためには、Intent内で action nameを設定し、actionごとに処理を記述します。Dialogflow CXでは、複数のwebhookを定義できるので拡張はしやすそうです。