Dialogflow Essentials コードを使ったeventの制御

こんにちは、AIチームの友松です。

この記事は以下の記事の続編となります。先にそちらをご覧いただいてから読むことをおすすめします。

今回は、DialogflowのEventという機能を紹介します。

1. Eventとは

これまでの記事ではContextとTraining Phraseによる対話の制御について説明してきました。

Dialogflowの動作としてはユーザの発話を受け取ってContextとTraining Phraseによって遷移先の決定を行い、ボットの発話を返却するというのが1回のリクエストの中で行われる内容です。

Eventを使うと、ユーザの発話を待たずしてeventを待ち受けているIntentへと遷移し、その遷移先のIntentの中身の発話を返すことができます。

つまり、1度のリクエストで2つのIntentを処理することができます。

Eventを発火するIntentではbotの発話を返さず、eventのみを返し、botの発話はeventによる遷移先のIntentで返すことになります。

まずは簡単なeventによる制御を作ってみます。

2. eventのメリット

Fulfillmentにおいてeventを使うメリットは3点挙げられます。

  1. Contextによる複雑な遷移を書かなくて良くなる
  2. コード側にbotのレスポンス文を記載する必要がない
  3. end_conversationを分岐先によって分けることができる。

まず1点目のポイントは、Output ContextとTraining Phraseによって複雑に遷移を制御していた部分が、eventによって簡潔に記述できるため、全体の設定や実装がシンプルになります。

2点目のポイントはコード側にbotのレスポンス文を記載する必要がないため、運用していく中で文言変更が必要になった際にコード側を変更することなくDialogflow側の変更のみで完結します。これはDialogflowの設計者とコードの実装者が異なる場合に非常に大きなメリットとなります。

3点目はend_conversationのフラグについてです。各Intentでは Set this intent as end of conversationという設定項目があります。これは対話の終端地点を示すフラグになっているのですが、Fulfillmentで遷移によってend of conversationをtrueにすべき場合とfalseにすべき場合が分岐する場合にContext+Training Phraseベースでやろうとした場合、各Intentで一つの値しかend of conversationの値を設定できないため、eventで遷移した先でそれぞれend of conversationを設定することでこちらを回避することができます。

3. eventを使った制御

前回の記事で紹介したWebhook Call+Contextによる営業時間の制御(図1)をEventに変えたパターン(図2)に変更したものを作成してみます。

図1: Webhook Call + Contextによる営業時間判定
図2: Webhook Call + eventによる営業時間判定

3.1 Entityの設定(Dialogflow)

ユーザーが発話した時間を捉えるエンティティとしてhourエンティティを正規表現のカスタムエンティティとして作成します。こちらは前記事と全く同じ設定となっています。

※今回は簡単化のために、0-23時以外の時間が発話されるケースは考慮しないものとします。

※また、システムエンティティで日時を扱えるものもありますがこちらも簡単化のために使用しません。

3.2 Intentの設定(Dialogflow)

Welcome Intent

Welcome Intentは前回の記事と全く同じ設定です。

  • Input Context: 無し
  • Output Context: Confirmation(lifespan=1)
  • Training Phrase: こんにちは
  • Response: お問い合わせありがとうございます。予約希望の時間をおこたえください。

Request Reservation Hour Intent

Request Reservation Hour Intentも前回の記事と全く同じ設定です。

  • Input Context: Confirmation
  • Output Context: 無し
  • Training Phrase: 10時(hourエンティティ)
  • Response: エラーが起きました(Webhook Intentなので、エラー時のみこの発話が起こる。)
  • Enable webhook call this intent: True

このIntentに来るとWebhook宛にリクエストをし、コードによる制御を行います。コード部分は後ほど解説します。

After Business Hour Intent

  • Input Context: 無し
  • Output Context: 無し
  • Training Phrase: 無し
  • Event: after_business_hours
  • Response: $hour_int時ですね。こちらは営業時間外なので受付できません。

こちらのIntentはeventを受け取って遷移するIntentです。そのため、Input ContextおよびTraining Phraseは無しになっています。Output Contextは後続の処理に応じて適切に付与してください。今回は簡単化のために無しとしています。

eventの設定には、eventという項目に文字列でキャッチするeventを指定するだけです。

eventにはparameterを含ませることができて、受け取ったparameterを$で指定することによってレスポンスに含めることができます。

During Business Hour Intent

  • Input Context: 無し
  • Output Context: 無し
  • Training Phrase: 無し
  • Event: during_business_hours
  • Response: $hour_int時ですね。こちらは営業時間内です。予約の空き状況を確認致します。

こちらのIntentは一つ前のIntentのEventとResponseのみを変更したものになっています。

3.3 Webhookサーバーの実装(Cloud Function)

Webhookサーバーの実装も前回の記事をベースに変更を行っています。

import json
import re

def main(request) -> str:
  body = request.get_json() # Request Body
  intent_name =  body["queryResult"]["intent"]["displayName"]

  if intent_name == "Request Reservation Hour Intent": # Enable webhook call for this intent.を指定したintent名
    return fulfillment_request_reservation_hour(body)
  else:
    raise Exception

def fulfillment_request_reservation_hour(body):
  session = body["session"] # sessionId
  hour = body["queryResult"]["parameters"]["hour"] # ユーザー発話から抽出したhourパラメータ
  hour_int = int(re.search(r'\d+', hour).group()) # ◯時の表現から数字部分を抜き出す

  if hour_int >= 24:
    raise Exception
  elif 10 <= hour_int <= 19:
    event_name = "during_business_hours"
  else:
    event_name = "after_business_hours"
  
  res = {
    "followupEventInput": {
      "name": event_name
      "parameters": {
        "hour_int": hour_int
      }
    }
  }
  return json.dumps(res)

変更点は21行目以降となり、コードはシンプルになっています。基本的な実装の解説は前記事に譲るとして変更点の差分のみ示します。

  • Contextの付与やbotのレスポンスをコード内に書かなくなっています。
  • 代わりにfolloupEventInputを返却しており、発火させるeventと任意でparametersを追加することができます。返却したparametersは受け取り先でresponseに含めることができます。

3.4 動きの確認

①営業時間内の時間を発話したケース

②営業時間外の時間を発話したケース

想定したとおりの分岐とレスポンスの挙動を確認することができました。

4. まとめ

今回はDialogflow Essentialsにおけるコードを使ったeventの制御について解説しました。過去3回で紹介した内容によってDialogflow Essentialsの大枠の制御は可能になります。次回はclientからDialogflowを参照してチャットボットの実装を行う方法について解説します。

最後までご覧いただきありがとうございました。

PICK UP

TAG