GoogleHomeをDialogflow(旧:API.ai)でスプラトゥーンアシスタントにする


はじめに

Google Homeを買ったはいいものの、テレビ無し、外出ない、家電使わない自分には少々物足りないので
生活の大半を占めるスプラトゥーンのアシスタントをGoogle Homeには勤めてもらいます。

目標

  • スプラトゥーン用お供AI

機能

実装する機能は2つです。

  • ブキ毎の勝敗の登録
  • ブキ毎の勝率の呼び出し

使用ツール・環境

webhookの置き場にheroku使用しました。

1.勝敗の登録

まず、お手軽にIFTTTを使ってGoogleスプレッドシートへ勝敗を入力します。

GoogleAssistant → spreadsheetのAppletを作ります。

IFTTTの設定は先人の方参考に
同様に負けた時用のApletも作ります。

これで
勝利 スプラシューター」「負けた キャンピングシェルター」等と話せば自動的にGoogleDriveのスプレッドシートに勝敗が記入されるようになりました。


スプレッドシートに登録されると「イカ登録完了」とGoogle Homeが喋ります。

2.勝率の呼び出し

次に、Googleスプレッドシートで計算した武器毎の勝率を呼び出してもらいます。

目標とする実装↓

僕「勝率 〇〇(武器名)

GoogleHome「〇〇の勝率は××パーセントです

この機能はGoogleAssistant+IFTTTでは賄えないので、
スプラトゥーンアシスタントAIをDialogflow(旧:API.ai)で作ります。

これを使って入力を解析(と言ってもブキ名を取得するだけ)し、webhookで外部へ流します。
そこでスプレッドシートの内容を取得し、JSONレスポンスでAI(Bot)へ戻せばBotが受け取った情報を元に喋ってくれるという仕組みです。
こんな流れです。

Dialogflowのセッティング

初期設定はこちら参照

Intents

Intentsで入力の受け取りや失敗した際の返答を登録します。
今回はユーザーの発言が「勝率」「成績」だった場合にBotが反応し、
勝率の後に続く部分をweapon_nameとして入力で受け取ります。

Entities

入力として受け取る単語はEntitiesから登録します。
都市名や日時はデフォルトでシステム側が用意してくれていますが、
残念ながらスプラトゥーンのブキデータベースは無いそうです。

Fulfillment

Fulfillmentでwebhookの送信先を設定します。
今回はherokuを利用しているのでそのURLを入力。

IntentsUse webhookに忘れずチェックを入れておきましょう。
ついでにDefaultの返答には検索が失敗した際の文章を入れておきます。

Webhookを作る

いよいよAIから受け取ったweapon_nameを元に勝率を返すwebhookを作れば終了です。

こちらの中で使われているwebhookを参考に、

以下がgspreadを使ってスプレッドシートの情報を取得しJSONで返すサーバーです。

webhook-dialogflow.py
from __future__ import print_function
from future.standard_library import install_aliases
install_aliases()

from urllib.parse import urlparse, urlencode
from urllib.request import urlopen, Request
from urllib.error import HTTPError

import json
import os

from flask import Flask
from flask import request
from flask import make_response, jsonify
import gspread
from oauth2client.service_account import ServiceAccountCredentials


# Flask app should start in global layout
app = Flask(__name__)


@app.route('/webhook', methods=['POST'])
def webhook():
    req = request.get_json(silent=True, force=True)
    result = req.get("result")
    parameters = result.get("parameters")
    weapon_name = parameters.get("weapon_name")

    scope = ['https://spreadsheets.google.com/feeds']

    #ダウンロードしたjsonファイルを同じフォルダに格納して指定する
    credentials = ServiceAccountCredentials.from_json_keyfile_name('xxxxxxxxxx.json', scope)
    gc = gspread.authorize(credentials)

    # # 共有設定したスプレッドシートの名前を指定する
    worksheet = gc.open("Google Assistant Commands").get_worksheet(1)

    cell = worksheet.find(weapon_name)

    text = str(cell.value) + str(worksheet.cell(cell.row,cell.col+1).value) + "パーセント"
    r = make_response(jsonify({'speech':text,'displayText':text}))
    r.headers['Content-Type'] = 'application/json'
    return r

if __name__ == '__main__':
    port = int(os.getenv('PORT', 5000))

    print("Starting app on port %d" % port)

    app.run(debug=False, port=port, host='0.0.0.0')

gspreadの使い方はこちらから

テストする

Dialogdlowのコンソール右側に入力すればテキストでテストが可能です。

「勝率 スプラシューター」と入力すると…

「スプラシューター50パーセント」と勝率が返って来ます。

ちなみにJSONはこんな感じになります。

完成

動作はこちらの通りです。
IMAGE ALT TEXT HERE
とりあえず自分がほしい機能は実装できました!

おわりに

現在、GoogleAssistantからDialogflowで作ったアプリを呼び出さなければいけないので、登録と呼び出しが別動作(Google Homeからテスト用アプリを起動している形)なのですが、
次はこれをDialogflowで一括にまとめようかなと思ってます。
後はステージ情報の取得とかでしょうか。しばらくはGoogle Homeで楽しめそうです。

そして良きスプラトゥーンライフを!

参考