事務所にある 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

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.