カタカタブログ

SIerで働くITエンジニアがカタカタした記録を残す技術ブログ。Java, Oracle Database, Linuxが中心です。たまに数学やデータ分析なども。

Google HomeとFlask(Python)サーバでスマートスピーカーアプリを作成してみた

先日Google Homeを買ってみたので、Google Homeと簡単な会話をするためのアプリケーションを作ってみた。
Google Assistantのアプリケーションとして開発するため構成は以下の通り。
まず、Google Homeに話しかけたメッセージを入力として、応答を返すWebサービスを作成する。
次に、GoogleのサービスであるDialogflow(旧API.AI)を利用してフロントの会話の部分を定義する。このときに、WebhookとしてそのWebサービスを指定することで、応答として得られた内容をGoogle Homeが喋ってくれる。
そのため、開発者はWebサービスの部分の開発と、Dialogflowの設定のみを行えばよい。

今回作成するアプリケーションは簡単な例として、Google Homeでしゃべった内容をそのまま2回オウム返しして喋るアプリとする。つまり「ハロー」と話しかけると、Google Homeは「ハローハロー」と返すようなものである。

Google Home連携用Webサービスの準備

Web側はPython+Flaskで実装し、Herokuにデプロイする。DialogflowからWebhookするときはインターネット上に公開されているWebサービスである必要があるため、Heorkuのようなクラウドプラットフォームを使うと便利。

まずメインとなるアプリケーションプログラムは以下。
app.py

from flask import Flask, request, jsonify
app = Flask(__name__)

@app.route('/echo', methods=['POST'])
def echo():
    message = request.json.get("result").get("parameters").get("message")
    response = {
        "speech": message + message
    }
    return jsonify(response)

/echoというパスにPOST形式で受け取るWebサービスのエンドポイントを作成する。
後でDialogflowでパラメータを設定するが、その際にmessageという変数名を使うことにする。そのため、DialogflowからWebhookされるリクエストのJSON構造から、result > parameters > message とたどれば、話しかけたメッセージを取得することができる。
これをレスポンスJSONのspeech要素の値としてmessageを2回つなげたものを返す仕様とする。

なお、Google AssistantのWebhook Requestのフォーマットは以下を参考にした。
https://developers.google.com/actions/reference/v1/dialogflow-webhook

あとはHerokuにデプロイするため、Flaskアプリケーションを起動させるために必要となるファイルを用意する。
Procfile

web: gunicorn app:app --log-file=-

runtime.txt

python-3.6.0

requirements.txt

Flask==0.12.2
Flask-Cors==3.0.2
Flask-SQLAlchemy==2.3.2
gunicorn==19.7.1

続いて、上記FlaskアプリケーションをHerokuにデプロイする。
今回Macから作業しているが、もしHeroku CLIがインストールされていない場合は以下のコマンドでインストールする。

$ brew install heroku/brew/heroku

Herokuにログインする。

$ heroku login

Herokuアプリを作成。名前を適当に付ける。

$ heroku create <app name>

Pythonビルドであることを明示。

$ heroku buildpacks:set heroku/python

Git pushしてデプロイ。

$ git push heroku master

アプリを起動する。

$ heroku ps:scale web=1

これでOK。curlで試しに以下のようなリクエストを投げて動作確認しておく。

$ curl -XPOST -H 'Content-Type:application/json' -d '{"result": {"parameters": {"message": "hello"}}}' https://<app name>.herokuapp.com/echo
{
  "speech": "hellohello"
}

正しく2回繰り返してメッセージが返されていればOK。
Google Homeから連携するためのWebサービスの準備はこれで完了。

Google Assistantアプリケーション作成

Google Assistantアプリケーションを作成する。まず、以下のURLからプロジェクトを作成する。
https://console.actions.google.com/

Add projectを選択する。
Project Nameは今回は「EchoApp」とした。また「Country/region」で「Japan」を指定して、プロジェクトを作成する。
f:id:osn_th:20180206161918p:plain
Dialogflowを選択する。
f:id:osn_th:20180206161926p:plain
Dialogflowの画面になると「EchoApp」作成画面になるので、DEFAULT LANGUAGEを「Japanese - ja」として「CREATE」する。
なお、API VERSIONという設定項目があり、Dialogflow V2 APIがあるようだが現時点はbeta版となっており有効化はしないため、V1のAPIとして利用する。
f:id:osn_th:20180206161930p:plain
まず、連携用のWebサービスを登録する。
Fulfillmentを開き、WebhookをENABLEDに変更する。URLに上でデプロイしたHerokuアプリのechoエンドポイントを指定する。
f:id:osn_th:20180206161936p:plain
次にインテントを登録する。
Intentsを開く。今回は任意のメッセージをそのままmessage変数として受け取りたいため、「AnyIntent」という名前で、Entityを「@sys.any」に、パラメータ名を「message」とする。
f:id:osn_th:20180206161945p:plain
Fulfillmentの「Use webhook」にチェックを入れておく。こうすることで、このインテントに対応する会話はHerokuアプリの方に連携される。
f:id:osn_th:20180206161955p:plain
以上で必要なスマートスピーカーアプリケーションの設定は完了である。

Google Homeで動かす前に、右上の「Try it now」にメッセージを入れてテストしておく。
USER SAYSで入力した内容がDEFAULT RESPONSEに2回繰り返されて返ってくることが確認できる。
もしエラーが出ている場合は「SHOW JSON」を開くと404とか503とかHTTPのステータスコードが確認できるので、それとWebサーバログを見て原因調査する。
f:id:osn_th:20180206162002p:plain

Google Homeで動作確認

いよいよGoogle Homeで動かしてみる。
IntegrationsからGoogle Assistantを選択する。
f:id:osn_th:20180206162006p:plain
 Testを選択する。
f:id:osn_th:20180206162011p:plain
CONTINUEする。
f:id:osn_th:20180206162018p:plain
するとシミュレータが起動するので、ここで「テスト用アプリにつないで」とメッセージを送ると、上で作ったアプリケーションが起動する。ここで「ハロー」とメッセージを送ると「ハローハロー」と2回繰り返して応答していることが確認できる。
ちなみに止めるときは「とめて」と言うと停止する。
f:id:osn_th:20180206162024p:plain

この時点で自宅のGoogle Homeにシミュレータの会話と同じように、「テスト用アプリにつないで」からアプリを起動し、
話しかけるとシミュレータの結果と同様に、こちらの発話を全て2回オウム返ししてくれる。

まとめ

Google Homeで外部Webサーバと連携し、こちらのメッセージに対して応答するアプリケーションを作成した。また実際にテスト用アプリとして、自宅のGoogle Homeに対して動作することも確認した。今回はテスト用アプリとしての動作確認までだったが、実際にアプリケーションとして公開する場合はここからGoogleに申請して登録してもらう流れになると思う。

これでスマートスピーカーアプリの入力と出力の方法が確認できたので、後はDB連携したりセッションを活用したり、外部APIを読んだりすれば、複雑なアプリケーション開発にも繋げられそう。

以上!