事務所にある GoogleHome で何かできないか、ということで、すこし調べたのでメモしておきます。
概要
GoogleHomeで音声を使ったアプリケーションを開発するときの、データの流れは以下の通りです。
[GoogleHome] ---- [Actions on Google] ---- [ <action> ] ---- [backend web-service]
左から3番目の <action> は開発する規模?種類?によって次の4つから選べます。
1) Dialogflow
2) Smart home
3) Actions SDK
4) Converse.AI
今回は 1 の Dialogflow と 3 の ActionSDK の場合をやってみました。
Actions on Google
とりあえず、Actions on Google (https://developers.google.com/actions/) のページから、右上の ACTIONS CONSOLE に入ります。
Add/Import project で テスト用プロジェクトを作成します。
次に、Add action to your app の ADD ACTIONS を押して、使用するアクションを選択します。
#最初は3つしか見えてませんが、すぐ下に more とあるのでそれを押すと全部見えるようになります。
各項目右下の BUILD を押すと作成されます。
Dialogflow
まずは、Dialogflow を使ってみます。
Dialogflow は簡単な音声アプリを簡単に作成するときに使用します。
キーとなる音声(文字列)を登録し、その言葉が見つかったら処理(返事)をする、というルールを一つずつ登録していくスタイルです。
何らかの処理が Dialogflow だけで完了しない場合、例えばキーワードに関する情報を加工したりする場合には、backend の web-service へ処理を投げる(webhookする)ことができます。
DEFAULT LANGUAGE を ja にして、右上の CREATE ボタンで作成します。
Intents の作成
処理のきっかけとなる文章とその処理を定義します。
標準で作成されているのは Default Welcome Intent です。これは GoogleHome が、今回作成するアプリケーションに制御を渡すきっかけとなるものです。
クリックして中を見てみましょう。
大きい項目には
Contexts
Events
Training phrases
Action and parameters
Responses
Fulfillment
があり、Events に 「Welcome」が設定されています。これが制御を移すイベントになります。
下段の Training phrases には、そのきっかけの文章を定義します。
Training とあるように、ここに書かれた文章は学習され、汎用的に丸められます。
「アプリに繋いで」とか「アプリと話す」的な言葉を登録します。
次に、Response に、その結果、応答する言葉を設定します。
「ようこそアプリへ!」とか「こんにちは、アプリです。」的な言葉を登録します。
Googleさんのガイドには、そのアプリが次の動作へスムーズに移行できるようなフレーズを登録すると良いと書かれていますので、そういうふうにした方が親切かと思います :p
Exit Intent を作る
そしてこのままだとアプリへ制御が移動したまま終われないので、終わりのきっかけを作ります。
CREATE INTENT で Intent name を Exit Intent として、Events に Exit を追加、Training phrases に「さようなら」とか「バイバイ」とか登録して、Response に 「ありがとー」を追加して、その下の Set this intent as end of conversation のチェックを ON にして保存します。
これで、「OK Google」→「アプリに繋いで」→ (応答)→「さようなら」→ (応答)で 自作アプリに処理を渡して終了する部分が完成しました。
#実際には「アプリに繋いで」では繋がらず、「テスト用アプリに繋いで」と言わなければいけませんでした。なにか設定が足りないようです。。。
テストしてみる
Actions on Google のページに戻り、左上の 三 からメニューを開いて、Actions を選択します。
Actions が開いたら右側の TEST ボタンでテストします。
シミュレーターが起動するので、テキストを入力するか音声でテストをします。
GoogleHome が繋がっていれば、音声でテストできます。
「OK Google」「テスト用アプリにつないで」と喋ると、上で登録した、「こんにちは!」が返ってきます。
さらに「さようなら」と喋ると、「ありがとー」と返ってアプリを終了します。
テキスト入力でのテストもできるので、同様に入力してみます。
リクエストや返事の実データが右側でみれるようになっています。
Fulfillment を使ってみる
簡単な応答アプリの場合は前項までで作ることができますが、ちょっと複雑な処理とかしようと思ったときにこの Fulfillment を設定します。
左メニューから Fulfillment を選択して Webhook を有効にします。
URL に backend の web-service の url を登録します。https でないといけないので注意します。
認証とかなければ他は空白で大丈夫です。
下段の Inline Editor は Firebase という グーグルさん関連のクラウドサービス上で処理をするよ、その時のコードだよ、というものです。今回は使用しません。#Node.js を使っているみたい。。。
保存したら Intent を追加します。ポイントは一番下の Fulfillment の Enable webhook call for this intent を有効にするところです。#その下は無効で。
Response は追加しません。web-service からの返事が Response になります。
これで、登録した Intent のフレーズを認識したら URL の web-service へデータが飛んで行くようになりました。
データは HTTPS の POST で、body 部分が JSON形式の文字列になっています。
受け側をつくるよ
というわけで、受け側を作ります。今回は sinatra で作りました。
post “/hogeactiontest” do
content_type :json
response = { :speech => “こんにちは、世界!”,
:displayText => “Hello, world!” }
response.to_json
end
JSON形式なのでJSONで返します。
:speech と :displayText は必須のようです。
とりあえずこれで返事を返すようになりましたので、同じようにテストしてみましょう。
Dialogflow 経由でやってくる JSON は以下な感じです。
あとは、色々できそうですね :p
あ、ちなみに body をハッシュにするのは
params = JSON.parse(request.body.read)
です。あとはよしなに。
{
"originalRequest": {
"source": "google",
"version": "2",
"data": {
"isInSandbox": true,
"surface": {
"capabilities": [
{ "name": "actions.capability.WEB_BROWSER" },
{ "name": "actions.capability.MEDIA_RESPONSE_AUDIO" },
{ "name": "actions.capability.SCREEN_OUTPUT" },
{ "name": "actions.capability.AUDIO_OUTPUT" }
]
},
"inputs": [
{
"rawInputs": [ { "query": "ハロー",
"inputType": "VOICE" } ],
"arguments": [ { "rawText": "ハロー",
"textValue": "ハロー",
"name": "text" } ],
"intent": "actions.intent.TEXT"
}
],
"user": {
"lastSeen": "2018-03-14T13:14:09Z",
"locale": "ja-JP",
"userId":"ABwpp....ru-3Q....RUI"
},
"conversation": {
"conversationId": "1521033330197",
"type": "ACTIVE",
"conversationToken": "[]"
},
"availableSurfaces":[
{
"capabilities":[
{ "name": "actions.capability.SCREEN_OUTPUT" },
{ "name": "actions.capability.AUDIO_OUTPUT" }
]
}
]
}
},
"id": "6a34b33e-8d99-479b-aac8-9b0d3c392719",
"timestamp": "2018-03-14T13:15:37.745Z",
"lang": "ja",
"result": {
"source": "agent",
"resolvedQuery": "ハロー",
"speech": "",
"action": "",
"actionIncomplete": false,
"parameters": {},
"contexts": [
{ "name": "actions_capability_screen_output",
"parameters": {},
"lifespan": 0 },
{ "name": "google_assistant_input_type_voice",
"parameters": {},
"lifespan": 0 },
{ "name": "actions_capability_audio_output",
"parameters": {},
"lifespan": 0 },
{ "name": "actions_capability_media_response_audio",
"parameters": {},
"lifespan": 0 },
{ "name": "actions_capability_web_browser",
"parameters": {},
"lifespan": 0 }
],
"metadata": {
"intentName": "Hello Intent",
"isResponseToSlotfilling": false,
"intentId": "6e68c027-4c00-4ec7-a379-04a8229162f7",
"webhookUsed": "true",
"webhookForSlotFillingUsed": "false",
"nluResponseTime": 3
},
"fulfillment": {
"speech": "",
"messages": [
{ "type": 0,
"speech": "" }
]
},
"score":1.0
},
"status":{
"code":200,
"errorType":"success",
"webhookTimedOut":false
},
"sessionId":"1521033330197"
}
Intents を作成するときに Action にタグのようなものが付けれます。
そこで登録した名称は [result"]["action"] の中に入ってくるので、これをみて処理を変えることもできたりします。もちろん ["result"]["metadata"]["intentName"] で処理を分けても大丈夫です。
まとめ
Dialogflow を使うと簡単に音声アプリが作れるのはすごいですね。
GoogleHome のような音声認識を使ったものはインパクトありますし、これからますます多くなってくると思うので、簡単にできるのはいいことです。
次は Actions SDK 編 予定。。。
→ https://qiita.com/ysomei/items/9c38dc76cd698e59026a