7
15

More than 5 years have passed since last update.

GoogleHome 開発をやってみた 〜Dialogflow編〜

Last updated at Posted at 2018-03-15

事務所にある 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 で テスト用プロジェクトを作成します。
screenshot001.png

次に、Add action to your app の ADD ACTIONS を押して、使用するアクションを選択します。

screenshot002.png
screenshot003.png
#最初は3つしか見えてませんが、すぐ下に more とあるのでそれを押すと全部見えるようになります。
各項目右下の BUILD を押すと作成されます。

Dialogflow

まずは、Dialogflow を使ってみます。
Dialogflow は簡単な音声アプリを簡単に作成するときに使用します。
キーとなる音声(文字列)を登録し、その言葉が見つかったら処理(返事)をする、というルールを一つずつ登録していくスタイルです。
何らかの処理が Dialogflow だけで完了しない場合、例えばキーワードに関する情報を加工したりする場合には、backend の web-service へ処理を投げる(webhookする)ことができます。

screenshot004.png

DEFAULT LANGUAGE を ja にして、右上の CREATE ボタンで作成します。

Intents の作成

処理のきっかけとなる文章とその処理を定義します。
標準で作成されているのは Default Welcome Intent です。これは GoogleHome が、今回作成するアプリケーションに制御を渡すきっかけとなるものです。

screenshot005.png

クリックして中を見てみましょう。

screenshot006.png

大きい項目には
 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 にして保存します。

screenshot007.png

screenshot008.png

これで、「OK Google」→「アプリに繋いで」→ (応答)→「さようなら」→ (応答)で 自作アプリに処理を渡して終了する部分が完成しました。
#実際には「アプリに繋いで」では繋がらず、「テスト用アプリに繋いで」と言わなければいけませんでした。なにか設定が足りないようです。。。

テストしてみる

Actions on Google のページに戻り、左上の 三 からメニューを開いて、Actions を選択します。

screenshot009.png

screenshot010.png

Actions が開いたら右側の TEST ボタンでテストします。
シミュレーターが起動するので、テキストを入力するか音声でテストをします。

screenshot011.png

GoogleHome が繋がっていれば、音声でテストできます。
「OK Google」「テスト用アプリにつないで」と喋ると、上で登録した、「こんにちは!」が返ってきます。
さらに「さようなら」と喋ると、「ありがとー」と返ってアプリを終了します。

テキスト入力でのテストもできるので、同様に入力してみます。
リクエストや返事の実データが右側でみれるようになっています。

Fulfillment を使ってみる

簡単な応答アプリの場合は前項までで作ることができますが、ちょっと複雑な処理とかしようと思ったときにこの Fulfillment を設定します。

screenshot012.png

左メニューから 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 になります。

screenshot013.png

これで、登録した 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

7
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
15