ユニファ開発者ブログ

ユニファ株式会社システム開発部メンバーによるブログです。

Actions on Google と AWS Lambda で Google Home から Slack にポストする

f:id:akanuma-hiroaki:20171013013717j:plain:w300:left

 みなさまこんにちは、ユニファCTOの赤沼です。先日やっと日本でも Google Home が発売されましたね。このブログを読んでいる方の中には買われた方もそれなりに多いのではないでしょうか。ユニファでも Google Home でどのぐらいのことができるのか検証してみるために、オフィス近くのビックカメラで購入してきました。普通に使っているだけでも天気やニュースを教えてくれたりと便利ではありますが、やはりエンジニアとしてはアプリを開発したり他のものと繋げてみたくなるものです。そこで今回は Google Home から使えるオリジナルのアプリを作ってみたいと思います。公式のドキュメントで紹介されているチュートリアルでは、バックエンドとして Firebase を使っていますが、それをそのままやっても面白くないので、今回は AWS Lambda でバックエンドの処理を実装してみたいと思います。

Google Home で使うアプリの構成

 Google Home の中で実際に音声アシスタントとして動いているのは Google Assistant で、Apple の Siri や Amazon の Alexa に当たるものです。なので Google Home で使うアプリを作るということは、 Google Assistant 用のアプリを作るということになります。ということは Google Assistant が動いていれば、 Google Home だけでなく、 Android 端末や iOS 端末でも使うことができるということになります。

 Google Assistant のアプリは Actions on Google というプラットフォーム上で開発します。主に下記のような要素から構成されています。

  • Actions on Google developer project
     アプリのプロジェクトを管理するベースとなるもので、アプリの分析や、テストのためのシミュレータ等の機能を持っています。

  • Action package
     Google Assistant がアプリをどのように起動するかや、どのように Fulfillment を呼び出すかなどのメタデータを定義しています。

  • Fulfillment
     HTTP Web サービスとしてホストされる、アプリの実機能を提供するファンクションです。JSONベースの Actions Protocol で Google Assistant からのリクエストを受け付け、処理結果を返します。

アプリ開発方法の選択肢

 Actions on Google でアプリを開発する際の開発方法の選択肢としては、下記の3つがあります。

  • Templates
     あらかじめ用意されているテンプレートを使う方法で、クイズやフラッシュカードなどのアプリのテンプレートが用意されています。コードを書く必要がなく、 Google Spreadsheet でデータの用意だけすれば使えるので、アプリの種類がマッチするならこの方法が一番お手軽です。

  • Dialogflow
     以前は API.AI という名前だった、自然言語で会話できる bot を作るためのAPIを提供しているサービスで、2016年9月に Google に買収されました。そして最近 Dialogflow という名前に変わりました。(Introducing Dialogflow, the new name for API.AI)Dialogflow は Actions SDK を Web IDE でラップしたもので、Action package を簡単に作成、デプロイできるようになっています。また、NLUエンジンを含んでいるので、自前で自然言語解析をする必要がなくなります。

  • Actions SDK
     限られたユーザとシンプルなやりとりを行うだけの場合に選択される方法で、既に自前のNLUエンジンを持っていてそれを使いたい場合などは Actions SDK を用いて開発する必要があります。また、 Actions SDK はIDEを提供しないので、テキストエディタなどで Action package を作成し、CLIから Google Developer project へデプロイする必要があります。

 今回は上記の3つの中から、Dialogflowを使う方法で実装します。

Actions on Google と Dialogflow での設定

 それではアプリを作成していきます。 Actions on Google と Dialogflow での設定は、基本的にはチュートリアルで紹介されている内容を踏襲していきます。

Overview  |  Actions on Google  |  Google Developers

 まず Actions on Google のコンソールにアクセスすると、プロジェクトの作成画面になりますので、+マークと Add/Import project と書かれているところをクリックします。

f:id:akanuma-hiroaki:20171013015622p:plain:w450

 するとプロジェクトの作成ダイアログが表示されますので、プロジェクト名と国・地域を選択して、 CREATE PROJECT をクリックします。

f:id:akanuma-hiroaki:20171013015913p:plain:w450

 プロジェクトが作成され、プロジェクトのOverviewの画面が表示されます。先ほど紹介した3つの開発方法のパネルが表示されますので、今回は Dialogflow のパネルの BUILD をクリックします。

f:id:akanuma-hiroaki:20171013020107p:plain:w450

 Action を追加するためのダイアログが表示されますので、 CREATE ACTIONS ON DIALOGFLOW をクリックして、Dialogflow のコンソールへ移動します。

f:id:akanuma-hiroaki:20171013020154p:plain:w450

 Dialogflow のコンソールが表示されたら、 Description にActionの内容を入力し、 DEFAULT LANGUAGE を選択して SAVE をクリックして保存します。

f:id:akanuma-hiroaki:20171013020251p:plain:w450

 すると Intents の画面が表示されます。ここでまず Fulfillment を使うためのとりあえずの設定をするため、左メニューから Fulfillment をクリックします。

f:id:akanuma-hiroaki:20171013020318p:plain:w450

 Fulfillment の画面が表示されたら、右上のトグルが DISABLED になっていますのでクリックして ENABLED に変更し、URL にとりあえずのダミーのURLを設定して、画面下部の SAVE をクリックします。

 余談ですが、 Dialogflow に名前が変更になったのと同時にこの画面に Inline Editor が用意されたので、例えばチュートリアルで紹介されていたような、テキストエディタで Function を書いて CLI で Firebase にデプロイするというようなことは、 Inline Editor のみで完結できるようになっているようです。

 保存したら左メニューから Intents をクリックして Intents の画面に移動します。

f:id:akanuma-hiroaki:20171013020503p:plain:w450

 作成済みの Intent の一覧が表示されます。最初から Default Fallback Intent と Default Welcome Intent が用意されています。まずは Default Welcome Intent をクリックします。

f:id:akanuma-hiroaki:20171013020605p:plain:w450

 Default Welcome Intent はユーザが Action を呼び出した際の WELCOME イベントによって最初に起動されます。各項目の設定方法の詳細はチュートリアルで紹介されているので割愛しますが、今回は下記のような内容で設定しています。保存したら再度左メニューから Intents をクリックして Intent の一覧画面に戻ります。

f:id:akanuma-hiroaki:20171013020634p:plain:w450

 次にユーザが Slack にポストしたい内容を受け取るための Intent を作成するため、画面上部の CREATE INTENT をクリックします。

f:id:akanuma-hiroaki:20171013020706p:plain:w450

 新しい Intent の作成画面が表示されたら、下記のような内容で設定します。この Intent ではユーザが話したことをそのまま Slack にポストするため、パラメータとしては @sys.any で全文を使用するようにしています。リクエストを受け取ったら Slack へ投稿するための処理を Fulfillment にリクエストするため、 Fulfillment の設定は Use webhook を選択し、Slack にポストして処理は完結なので、 Google Assistant の設定で End conversation にチェックを入れています。

f:id:akanuma-hiroaki:20171013020751p:plain:w450

 ここまでで一旦 Actions on Google と Dialogflow コンソールでの設定は終了し、 AWS Lambda と API Gateway の設定を行います。

AWS Lambda Function の作成と API Gateway の設定

 今回は AWS Lambda Function と API Gateway、 Slack の Webhook の詳しい作成方法は主題ではないので割愛しますが、まず Lambda の Function は下記のような内容で作成し、postToSlackFromGoogleHome という名前で保存しました。 SLACK_POST_URL には実際の Slack の Webhook のURLを設定してください。

#-*- coding:utf-8 -*-
from urlparse import urljoin
from urllib import urlencode
import urllib2 as urlrequest
import json
import random

SLACK_POST_URL = "https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX"

def build_payload(message):
    payload = {
        "username": "Google Home",
        "text": message
    }
    return payload
    
def post(payload):
    payload_json = json.dumps(payload)
    data = urlencode({"payload": payload_json})
    req = urlrequest.Request(SLACK_POST_URL)
    response = urlrequest.build_opener(urlrequest.HTTPHandler()).open(req, data.encode('utf-8')).read()
    return response.decode('utf-8')

def post_to_slack(message):
    payload = build_payload(message)
    return post(payload)

def lambda_handler(event, context):
    return post_to_slack(event['result']['parameters']['any'])

 チュートリアルで紹介されているように node.js で Fulfillment を実装する場合には Actions on Google の SDK が利用できるので、SDKが提供するメソッドでリクエスト内容を取り出したりできますが、今回は Lambda で Python による実装なので、送信されてくる JSON から目的のパラメータを取り出しています。送信されてくる JSON で使用するパラメータに関する部分を抜粋すると下記のような内容になります。 Intent の設定でパラメータとして @sys.any を指定したので、 parameters の中で any として目的の内容が送信されてきています。今回はとりあえずユーザが話した内容だけ取れれば良いので、他の部分についてはあまり調べていません。

{
  "id": "7a27e8ff-4e18-4e80-89a0-141dbb3965a5",
  "timestamp": "2017-10-12T17:17:21.169Z",
  "lang": "ja",
  "result": {
    "source": "agent",
    "resolvedQuery": "投稿テスト",
    "action": "",
    "actionIncomplete": false,
    "parameters": {
      "any": "投稿テスト"
    }
  }
}

 作成した Lambda Function を API Gateway と紐づけ、API をデプロイしたら、そのURLを Dialogflow のコンソールの Fulfillment の画面で URL の項目に設定して保存します。

f:id:akanuma-hiroaki:20171013083215p:plain:w450

アップデートとテスト

 ここまでで一通りの設定は終了なので、テストをしてみます。まずは Dialogflow コンソールの左メニューから Integrations をクリックします。 Integration の一覧画面に移動したら、 Google Assistant のパネルをクリックします。

f:id:akanuma-hiroaki:20171013021018p:plain:w450

 初回は下記のようなダイアログが表示されるかと思いますので、そのまま DONE をクリックします。

f:id:akanuma-hiroaki:20171013021143p:plain:w450

 Google Assistant の Integration の設定ダイアログが表示されたら、下部の TEST をクリックすると、下記の画面のように Test now active と表示され、シミュレータでのテストができるようになりますので、 VIEW をクリックして Actions on Google のシミュレータに移動します。

f:id:akanuma-hiroaki:20171013021202p:plain:w450

 シミュレータに移動すると、 Input フォームにはあらかじめ「スラックポストにつないで」というテキストが入っているかと思いますので、Input フォームを選択して Enter します。

f:id:akanuma-hiroaki:20171013085449p:plain:w450

 すると Action が起動し、右側にはリクエストの JSON の内容が表示されます。続けてユーザが話した想定の文言を Input フォームから入力して Enter します。

f:id:akanuma-hiroaki:20171013085507p:plain:w450

 追加で作成した Intent の設定内容に従って処理が行われ、レスポンスが表示されます。

f:id:akanuma-hiroaki:20171013085524p:plain:w450

 実際に Slack の Webhook へのリクエストも行われ、下記のように Slack にメッセージが表示されます。

f:id:akanuma-hiroaki:20171013085544p:plain:w450

 これでとりあえず Google Home に話した内容を Slack にポストするアプリを作ることができました。

まとめ

 今回はお試しということで、ごくシンプルな内容でテスト段階までということでしたが、 Lambda 等と連携できればそこから先は自由度高く色々なことができると思います。また、一般的に使ってもらえるようなアプリを作って公開すれば、多くのユーザに使ってもらうこともできます。会話で処理を進めるというUIは画面を使うアプリと比べて用途が絞られると思いますが、もうすぐ Google Home mini も発売されますし、色々試して新しい使い方を模索してみたいと思います。