DialogflowとLINEの統合

Dialogflowの公式ドキュメントに従って作成したホテル予約エージェントをLINEと統合した。ここで、「統合」とは、公式LINEアカウントアプリ(いわゆるLINEボット)に入力したメッセージをDialogflowのエージェントにWebhook経由で送信し、Dialogflowが返してくるレスポンスをLINEに通知することである。この「統合」を行うには、DialogflowコンソールのメニューからIntegrationsを選択する。

Integrations

図は Dialogflowコンソールからホテル予約エージェントのIntegrationsを選択したところのスクリーンショットである。

図1.Integrations

この画面で統合するサービスを選択する。LINEを選択すると次の画面が表示される。

図2.LINE統合設定画面

この画面に示すように、統合画面ではLINEのチャネルID、チャネルシークレット、チャネルアクセストークンを入力するようになっている。これらはLINE Developersコンソール(下記)のチャネル基本設定、Messaging API設定で取得できる。

図3.LINE Developers コンソール画面

また、図2のLINE統合設定画面の最下行にあるWebhook URLを図4のLINE DevelopersコンソールのMessaging APIタブにあるWebhook URLに設定してWebhookの利用を有効にする。

図4.Webhook URLの設定

LINEでテスト

設定が完了したらLINEでテストを行う。LINEの友達追加でLINE DevelopersコンソールのQRコードを読み取り友達追加して、「明日の福岡を予約」とメッセージを入力した。

図5.予約メッセージを入力

その結果、「福岡タウンホテルを2月22日に予約しました。」とDialogflowエージェントで処理したレスポンスメッセージ(図6)が返ってきた。

図6.Dialogflowで「明日の福岡を予約」

 なお、デフォルト設定のままだと図5に示すように「メッセージありがとうございます!申し訳ありませんが・・・」と応答メッセージが通知されるので、LINE Developersコンソールから応答メッセージを編集して「オフ」にしておくとよい(Webhookのみ「オン」)。

次に、「こんにちは」と入力すると「こんにちは。」、「今日の天気は?」と入力すると「今のは少しわかりにくかったです。」と返ってきた(図7)。

図7.インテントにないメッセージを入力

これらは、Dialogflowのインテントに設定していない入力を行うと、何が返ってくるか(言い換えれば誰が応答メッセージを返してくるか)を調べるために行った実験である。これを確認するためにDialogflowコンソールのTry it nowに「こんにちは」と入力すると「こんにちは」とレスポンスが(図8)、しかし、「今日の天気は?」と入力すると「今のは少しわかりにくかったです。」が返ってきた(図9)。

図8.Dialogflowで「こんにちは」

 
図9.Dialogflowで「今日のお天気は?」

図8を見ると、レスポンスを返してきたINTENTは「Default welcome intent」になっており、図9を見ると「Default fallback intent」になっている。図6では作成した「booking-hotel」がINTENTになっていたところを見ると、Dialogflowエージェントは入力メッセージにマッチするINTENTを探してきてそれに対応するレスポンスを返しているようだ。

図10は日付を指定せす「東京を予約」と入力した際に、Dialogflowが必須Entityの入力を促進しているところである。

図10.日付を省略して「東京を予約」と入力

このように、Dialogflowで設定したように不足する情報を自動でリカバリしてくれる機能はとても役に立つ。

感想

LINEをDialogflowに統合すると自然言語処理の部分はDialogflowがやってくれるし、必須Entityを補完する機能があるので便利である。よって、これから開発するLINE公式アカウントアプリはDialogflowと統合することにする。そうなると、すべてのメッセージはWebhook URLに送信してもらわないといけないので、INTENTを作り込まないといけない。

また、Googleアシスタントもレガシー統合すればLINEとGoogle Homeの両方が同じプログラムで処理できるので便利である。この方向で やっていきたい(→と、当初は考えたが、どうもLINEとの統合とGoogle Assistantとの統合は勝手が違うようだ。Google Assistantとの統合はセッションという考え方がベースにあるが、LINEとの統合にはない。)。

Intentを追加する

ホテル予約エージェントに2つ目のIntentを追加する。ユーザが入力したリクエストメッセージをDialogflowがIntentに紐づけ、Webhook側ではそのIntent(queryResult.intent.displayName)に基づいて処理を行い、レスポンスを返す。

追加するIntentは血圧測定にする。

Entityの追加

収縮期血圧(systolic-pressure)、拡張期血圧(disatolic-pressure)、脈(pulse-rate)を追加する(下図)。

図11.Entity 収縮期血圧の追加

図12.Entity 拡張期血圧の追加

図13.Entity 脈拍の追加

Intentの作成

次にIntentを作成する。Intent nameは「measuring-blood-pressure」とし、Training phraseに「収縮期は134、拡張期は68で脈拍は82です。」と入力し、「収縮期」、「拡張期」、「脈拍」にそれぞれEntity「@systolic-pressure」、「@diastolic pressure」、「@pulse-rate」を割り当て、各々の数値「134」、「68」、「82」にはシステム組み込みEntityである「@sys.number」を割り当て、各々の変数を「systolic」、「diastolic」、「pulse」と定義した(下図)。
図14.Intent measuring-blood-pressureの作成
次いで、FulfillmentをEnableに設定した。
図15.Fulfillmentの有効化

GASプログラムの修正

Webhookプログラムに血圧測定のIntentハンドラを追加する。

/**
 * POSTメソッド
 */
function doPost(e) {
  const data = e.postData.getDataAsString();
  const req = JSON.parse(data);
  debug(JSON.stringify(req, null, ' '));
  const res = handleWebhook(req);
  return ContentService.createTextOutput(JSON.stringify(res));
}

/**
 * Webhookリクエストハンドラ
 * Dialogflowから送信されてきた HTTPS POST Webhook リクエストを処理する関数
 * https://cloud.google.com/dialogflow/es/docs/fulfillment-webhook?hl=ja
 */
function handleWebhook(req) {
  const intent = req.queryResult.intent.displayName;
  debug('intent=' + intent);
  switch(intent) {
    case 'booking-hotel':
      return intent_booking_hotel(req);
    case 'measuring-blood-pressure':
      return intent_measuring_blood_pressure(req);
    default:
      return tell('intent=' + intent + 'がフックされていません。');
  }
}


/**
 * Intent=measuring-blood-pressure
 */
function intent_measuring_blood_pressure(req) {
  const parameters = req.queryResult.parameters;
  const systolic = parameters['systolic'];
  const diastolic = parameters['diastolic'];
  const pulse = parameters['pulse'];
  const text = '了解しました。血圧は上が ' + systolic + ' 、下が ' + diastolic + 'で、脈拍は ' + pulse + 'ですね。記録しておきます。';
  const res = new Response();
  res.pushLineText(text);
  res.pushLineSticker("52002740","11537");
  return res.getMessage();
}

/**
 * Intent=booking-hotel
 */
function intent_booking_hotel(req) {
  const parameters = req.queryResult.parameters;
  const text = parameters['building'] + 'を' + GST2JST(parameters['date-time'], 'M月d日') + 'に' + parameters['request'] + 'しました!';
  const res = new Response();
  res.pushLineText(text);
  res.pushLineSticker("52002740","11537");
  return res.getMessage();
}

/**
 * tell テキストメッセージ作成
 */
function tell(text) {
  const res = new Response();
  res.pushLineText(text);
  return res.getMessage();
}

/**
 * グリニッジ標準時(GST)を日本標準時(JST)に編集する
 * str_gst_date: '2021-02-20T12:00:00+09:00'
 * format: 'MM月dd日'
 */
function GST2JST(str_gst_date, format = 'yyyy/MM/dd HH:hh:mm') {
  const date = new Date(str_gst_date);
  return Utilities.formatDate(date, 'JST', format);
}

なお、ここでカスタムペイロードレスポンスクラスを利用した。

LINEによるデバッグ

作成したGASプログラムをデプロイしてLINEでテストを行った結果を下図に示す。

図16.LINEで血圧測定Intentを実行
入力された血圧や脈拍をスプレッドシートに書き込めば完成である。


0 件のコメント:

コメントを投稿