じゅころぐAR

ARのブログ

Actions on GoogleのIntentsを理解する

少し間が空きましたが、Actions on Googleで対話型アシスタントを自作する作業の続きです。

Google Homeと連携するサービスを自作するには - じゅころぐAR
Actions on GoogleとAmazon API Gatewayを連携させる - じゅころぐAR

今回はアシスタント作成の基本となるIntentsの設定をしていきます。
Intents  |  Dialogflow ES  |  Google Cloud

Intentsを作成するまでの流れ

Actions on GoogleにGoogleアカウントでログインしてプロジェクトを作成すると、以下のような画面になります。

f:id:jyuko49:20180105170817p:plain

Build a custom appの"Dialogflow"をクリックすると、ポップアップが開き、Dialogflowでactionsを作成するよう促されます。

f:id:jyuko49:20171222074632p:plain

ボタンをクリックしてDialogFlowのコンソールに遷移すると、現在登録されているIntentsの一覧が表示されます。

f:id:jyuko49:20171222075443p:plain

既存のIntentを編集する場合は一覧からクリック、追加の場合は、画面左メニューの"+"ボタンもしくは画面上部の"CREATE INTENT"でIntentを追加できます。

Intentを作成する

固定のResponseを返す

最もシンプルな定義は、ある入力 = "User Says"に対して決められた出力 = "Response"を返す設定です。

"User Says"にユーザから入力してもらう文言を入れます。

f:id:jyuko49:20180104231922p:plain

句読点の有無やカナ・漢字などの表記ゆらぎは吸収してくれるので、あまり気にしなくても大丈夫です。

文章は複数定義することができ、いずれかに該当すれば合一のIntentとしてResponseを返します。同じ意味の文章を言い回しを変えて定義しておくと、どれでも反応してくれるようになります。

f:id:jyuko49:20180104233335p:plain

続いて、"Response"を定義します。定型文を返す形であれば、返したいメッセージをそのまま入力すればOKです。

f:id:jyuko49:20180104231935p:plain

Responseも複数の文章が定義でき、定義されたものから一つをランダムで返します。

f:id:jyuko49:20180104234803p:plain

"Use Says"と"Response"を定義したら、画面上部メニューでIntentに適当な名前を付けて"Save"をクリックします。

f:id:jyuko49:20180104235825p:plain

名称の横にある青い点をクリックすると、Intentの優先度を設定することができます。Intentが複数ある場合、スコア(後述)が高いものが使われるため、優先度を上げることでそのIntentが使われやすくなります。

f:id:jyuko49:20180104235853p:plain

Intentを"Save"したら、画面の右側にある"Try it now"で動作確認してみましょう。

テキストボックスに直接入力するか、マイクアイコンをクリックして音声入力ができます。マイクが使えるなら音声入力の方がGoogle Homeでの動作に近い形のテストになります。

テスト実行した例です。

f:id:jyuko49:20180105001700p:plain

入力したテキストは"User Says"に定義した文章のどれとも完全には一致しませんが、スコア(関連性)が高いIntentとして先程定義したものが使用されています。

Intent選択時のスコアは"SHOW JSON"で確認できます。

f:id:jyuko49:20180105124653p:plain

関連性が高いIntentほどスコアが大きくなり、入力が"User Says"と完全一致するとスコアは1になります。
思い通りにIntentが選択されない場合、"User Says"に定義する文章やIntentの優先度で調整します。

Fallback Intentを編集する

Fallback Intentは特殊なIntentで、他のIntentで入力に該当するものがなかった場合の入力エラーとして使われるIntentです。

Dialogflowに最初から定義されている"Default Fallback Intent"を編集します。

f:id:jyuko49:20180105012633p:plain

Fallback Intentには、"Usr Says"の入力欄がありません。優先度の設定も存在せず、Fallback IntentのON/OFFを行うUIになっています。

Responseは入力エラーに相当するメッセージを定義しておきます。

Eventsをトリガにする

"User Says"に反応する定義の他に、Eventsに対してResponseを返す設定ができます。
Fallback Intentと初期設定されている"Default Welcome Intent"Eventsを使った例になっています。

f:id:jyuko49:20180105010119p:plain

この例では"User Says"は定義されておらず、Eventsに"WELCOME"が設定されています。
Google Homeではアシスタントアプリに接続した直後に、"WELCOME"イベントが発生し、定義したメッセージが発話されます。

Parametersを使う

少し高度な設定として、"User Says"からパラメータを抽出して応答に使います。
Actions and parameters  |  Dialogflow ES  |  Google Cloud

"User Says"からParameterを抽出

"User Says"に例文を入力した後、パラメータとして抽出したい単語を選択するとエンティティ(後述)の一覧が表示されます。

f:id:jyuko49:20180105113456p:plain

@sys.anyを選択して、PARAMETER NAMEをanyから任意の名称に変更します。(anyのままでもOK)

f:id:jyuko49:20180105113824p:plain

@sysシステムエンティティと呼ばれるDialogflowで予め定義されたデータ入力型です。
例えば、@sys.dateは日付にマッチする入力をISO-8601にフォーマットして返してくれます。

例:「"1月1日"の天気は?」
 → "2018-01-01"をパラメータにセット

@sys.anyは空でない任意の入力にマッチし、マッチした文字列そのものを返します。
Dialogflow Documentation  |  Google Cloud

ActionでParameterの設定を行う

抽出したパラメータの設定はActionで行えます。Action名の設定は任意です。
f:id:jyuko49:20180105120505p:plain

"User Says"で抽出した"PARAMETER NAME"、"ENTITY"を"VALUE"にセットする定義になります。
"REQUIRED"はパラメータを必須入力とするかどうかの設定、"IS LIST"はマッチする値が複数あった場合に配列で返す設定です。

ResponseでParameterを使う

Actionで設定したパラメータの"VALUE"をResponseに埋め込むことができます。
$ではじめる"VALUE"をそのまま記述すればOKです。

f:id:jyuko49:20180105121521p:plain

ここまでの設定を"Save"してテストしてみます。

f:id:jyuko49:20180105123314p:plain

入力した文章からパラメータが抽出され、Responseで使われていることがわかります。
同様にJSONにもアクション名とパラメータの値が追加されています。

f:id:jyuko49:20180105124718p:plain

FulfillmentでWebhookを用いた場合、このJSONに相当する内容がPOSTされるため、Webhook先でもパラメータが使えます。

Entityを定義する

先程は@sys.anyで任意の文字列を抽出しましたが、入力をそのまま返すという特性上、不便な点がいくつかあります。

  • "IS LIST"が使えない
    「"AとB"について」や「"A、B"について」と入力された場合、"A","B"の2つの要素を配列で取得したいところですが、@sys.anyだと区切り文字を判別しないため、"AとB"、"A、B"を返します。

  • 入力のゆらぎに対応しにくい
    「"お肉"食べたい」「"肉"食べたい」は同じ"肉"への欲望を表現していますが、@sys.anyだと"お肉"、"肉"と異なる結果を返します。

これらを解決するため、Entity(エンティティ)を定義します。
画面左のメニューからEntitiesを選択し、"CREATE ENTITY"をクリックで設定画面が表示されます。

f:id:jyuko49:20180105131515p:plain

まず、画面上部のテキストフィールドにエンティティ名を入力します。

次に、"Define synonyms"でシノニムを利用するかのチェックを入れます。
シノニムは同意語の意味で、同じ意味で表現が異なる単語を同じ値として扱います。
リストに追加した行の右側に同意語として扱う単語をカンマ区切りで列挙し、左側にVALUEにセットする文字列を記述します。

最後に、"Allow automated expansion"で自動拡張を許可するかを設定します。
チェックを外すと、リストに定義されている単語のみマッチします。例えば、天気のエンティティ(@weather)を定義して、"晴れ"、"曇り"、"雨"、"雪"のみを扱いたい場合、チェックを外しておくと余計な入力を受け付けません。
チェックを入れると、リストにない入力も受け付けるようになります。こちらは@sys.anyに近い挙動ですが、シノニムと"IS LIST"は有効になります。

設定が完了したら、"Save"をクリックでEntityが作成されます。
今回は、"Define synonyms""Allow automated expansion"をどちらも有効にしました。

定義したEntityをIntentで使う

Intentの編集画面に移動し、"User Says"とActionの@sys.any先程定義したEntity(@friends)に変更します。
また、動作確認のため、"IS LIST"も有効にしました。

f:id:jyuko49:20180105141802p:plain

この設定で再度テストしてみます。

まずはシノニムの確認。元の文字列は"ちゃん"付けになっていますが、"VALUE"はシノニムで定義した値になっています。

f:id:jyuko49:20180105142909p:plain

次に"IS LIST"の確認です。"AとB"、"A、B"のような入力をすると、VALUEはAとBの配列で取得できています。

f:id:jyuko49:20180105143344p:plain

Google Homeでテストする

ここまでの設定で入力から抽出したパラメータを使ったメッセージを返せるようになったので、実機で試してみます。

Actions on Googleの画面に戻り、2のApp informationで"EDIT"をクリックします。

f:id:jyuko49:20180105152828p:plain

いくつか設定項目があるうちのAssistant app name[アシスタントアプリ名]を入力します。このアプリ名はアシスタントに接続する際に使います。

f:id:jyuko49:20180105152834p:plain

入力したら画面下の"SAVE"ボタンで保存します。未入力の項目でエラーが出ますが、アプリをパブリックに公開するための設定が含まれるため、テスト時は無視して問題ありません。

"TEST DRAFT"ボタンをクリックします。

f:id:jyuko49:20180105145602p:plain

ブラウザ上ではSimulatorの画面に遷移しますが、この画面では特に何もしなくても実機でテストできる状態です。

Google Homeに向かって、
「OK、Google! [アシスタントアプリ名]につないで」
と発話してみましょう。

前提として、Actions on Googleで使っているGoogleアカウントと同じアカウントをGoogle Homeと連携させておく必要があります。
上手くいけば、"Default Welcome Intent"で定義したWELCOMEイベント発生時のメッセージが発話されるはずです。

接続ができた後は入力を待ち受ける状態になるので、Intentsのテストを行います。

設定したIntentが動作していることが確認できました。

まとめ

Intentsの基本的な設定を一気に書いたので、かなり長くなりました。
機能が多く、最初のうちはわかりにくさがありますが、ドキュメントを読み進めつつ設定していけば、何が行えるのかを徐々に理解できるかと思います。

まだ使っていない中で重要そうなところではContexts(コンテキスト)という機能があります。
アシスタントと自然な対話を行うために、直前の入力を一時的に保存しておき、その後のIntentsで使う仕組みです。

この辺りまで押さえておけば、対話形式の入力を自由に扱えるようになるので、あとはバックエンドでどんなサービスと組み合わせるかを考えれば、様々なアシスタントを作成・提供することができます。
まあ、サービスとして提供するデータやWeb APIを用意するのが一番大変なんですけどね。