AmazonはAIアシスタントにAlexaという名前を与えて、Alexaを調教するに教える(スキルを追加)ことでAlexaができることを拡張するアプローチを取っていて、ぼくは分かりやすいし親しみやすいと思っていますが、Googleは全然違うアプローチを取っています。
GoogleはAIアシスタントに名前を与えず、機能を拡張をしたい場合はその機能を持っている相手と”チャットする”というアプローチを取っています。
この思想の違いは重要なんです。
Alexaの場合は話し相手はいつもAlexaで、Alexaに部屋の温度やピザの注文をお願いするという、色々と世話を焼いてくれる家族の一員のような役割を与えていて、まさに家庭にAlexaというAIを迎えるという演出をしているんです。今後、家庭に入って来るお掃除ロボットや白物家電、更には家自体(ドアや窓、カーテンのコントロールも)、車もAlexaというAIのコントロール下に置かれて、Alexaと話すことでなんでもできるようになることでしょう。
Amazonの究極の目標はAlexaをAIの代名詞にすること、言い換えると、Alexaを機械やソフトウェアと人間との標準インターフェースにすることなのかも知れません。
っと、SF好きなぼくの妄想はさておいて、今回の趣旨に話を戻しましょう。
構成
前回のAlexaでの記事と比べると、AWS LambdaからBlynkにアクセスする部分以外が違っています。
GoogleにもFirebaseというクラウドアプリ開発環境(Cloud Functionsの仲間)が用意されているので、本来AWS Lamdbaを使う必要が無いのですが、なんとGoogle以外にアクセスするには有料プランの契約が必要になっているのです!
ぼくのアプリではBlynkのクラウドサーバーにアクセスする必要があるため、有料プランに変更しないと駄目だったんです。
これに丸1日ぐらい気付かず、なんでうまく動かないのか散々調べました...。
そんな理由であっさりFirebaseを捨ててAWS Lamdaを使うことにしたんです。
- Actions on Google:Google Assistantアプリの開発者環境。
- Dialogflow:対話モデルの定義とその処理環境。旧Api.ai。
AmazonのAlexa skills kitに用意されているものより高機能な印象。 - Amazon API Gateway:スケーラブルなAPI提供環境。
- AWS Lamda:サーバーレスコード実行環境。
- Blynk:IoT機器をスマホからコントロールするクラウド環境。
- ESP8266:Arduino対応のWiFi付きマイクロコントローラー。
デモビデオ
同じシェアハウスに住んでいる茜ちゃんに協力してもらいました。
Google Assistant、むっちゃ反応いいです!ピポッという音が終わる前に喋ってもキチンと認識しています!この辺りはAlexaより良く出来ているように思います。
アプリを公開せずに自分だけで楽しむのであれば、やることはあまりありません。
最初にプロジェクトを作ってActionを設定し、アプリ名を決めることぐらいです。
プロジェクトの作成
プロジェクト名はとりあえず適当に付けてしまいましょう。
Actionの設定
正直インターフェースというか作りが良くありません。Alexaに対抗するためよっぽど急いだのでしょうか。
プロジェクトを作るとこの画面が表示されますが、これはActionの設定のようです。
Dialogflowの「BUILD」をクリックします。
一度作った後はこのように「①Actions」の所に表示されます。この画面を最初から出して設定するようにした方が、何をやっているのかがわかると思うのですが...。
「BUILD」をクリックするか「Dialogflow actions」をクリックするとこの画面が表示されます。「CREATE ACTIONS ON DIALOGFLOW」をクリックするとDialogflowに飛びます。
Dialogflowは旧Api.aiという会社をGoogleが買収して名前が変わったようです。Dialogflowは機能的に非常に優れていると思いますが、Google Assistantに限らず汎用に出来ているいるために一手間かかる状態となっていて、設定が終わった後に「Integrations」を行わないと設定がGoogle Assistantに反映されません。苦肉の策としてこの画面を挟んでアピールするというなんともスマートじゃない状態となっています。
Dialogflowの設定が終わったら、App infomationの「Assistant app name」と「Pronounciation」を設定すれば、「ブリンクにつないで」とGoogle Assistantに話しかければブリンクアプリにつないでくれます。
アプリの声はGoogle Assistantの比較的ナチュラルな声ではなく、Assistant app voice項目で設定できるたどたどしい声になります。Male 1、Male 2、Female 1、Female 2の4つから選べますが、この声を変更して「SAVE」しただけでは反映されません。DialogflowでIntegrationを行うか、Overviewに戻って「TEST DRAFT」をクリックする必要があるんです!んー、なんだろう、この作り...。
Dialogflow
Dialogflowでは基本「Entities」「Fulfillment」「Intents」の3つの設定を行います。
Entities
会話の変数となるような言葉のバリエーションを定義するっといった感じです。
今回の場合は「部屋の温度を教えてください」や「ベランダの湿度を教えてください」という会話を想定しているので、部屋やベランダ用のLocationと温度や湿度用のMeasurementを登録します。
Fulfillment
外部プログラムとの連携を設定するといった感じです。
Firebaseを使う場合はInline Editorでコードを直接書くことができて、最初はこれでやっていましたが、外部アクセス問題のためにAWS Lambdaに切り替えたためWebhookを使うようにしました。
この段階ではまだAWS Lambdaの設定が終わっていないので、適当なURLを記入しておいて後で変更します。
Intents
初めから次の2つのIntentが登録されています。
Default Welcome Intent:アプリにつないだときに言う言葉
Default Fallback Intent:登録したIntentに合致しなかったとき用の言い訳集
これらのIntentにResponseを追加することもできたのですが、それだと世界観が崩れてしまうので、このように変えました。
Default Welcome Intent:変更後
Default Fallback Intent:変更後
これらの文言は「12分●罰ゲーム用台詞集【男性用】」からお借りしました。七菜 かずはさんに感謝!
Intentの追加
追加するIntentは会話と変数となる言葉を定義するみたいな感じです。
少し独特のインターフェースで、User Saysにまず「locationのmeasurementを教えて」というように入力して、Entityに対応させる部分をマウスでドラッグするなどで選択して(青く反転します)表示されるEntity一覧から選択します。
User saysでEntityの対応付けを行うとActionにも自動で追加されます。
事前にFulfillmentでWebhookを「ENABLE」にしておくと、この画面にもFulfillment項目が表示されるのでUse webhookにチェックを付けます。
AWS Lambda
AWS Lambda関数を作成するには、まず、リージョンを「東京」に変えて、AWSサービスの「最近アクセスしたサービス」か「すべてのサービス」から「Lambda」をクリックします。
ロールは最初「カスタムロールの作成」を選んで、新たに開いた画面で「新しいIAMロールの作成」を選んで「許可」をクリックした後、「既存のロールを選択」に選び直します。
関数コード (Node.js 6.10)
index.jsを以下のものと置き換えます。コードはAlexaの時のreadTemperatureInSession()とほぼ一緒です。違いはDialogflowからのEntityの受け取り方ぐらいです。
Google Assistant
var location = JSON.parse(event.body).result.parameters.Location;
var measurement = JSON.parse(event.body).result.parameters.Measurement;
Alexa
var location = LocationSlot.value;
var measurement = MeasurementSlot.value;
var http = require('http');
exports.handler = (event, context, callback) => {
// TODO implement
var repromptText = '';
var speechOutput = '';
var body = '';
var blynkAuthToken;
var blynkPin;
var location = JSON.parse(event.body).result.parameters.Location;
if (location === '') {
location = 'ベランダ';
}
switch (location) {
case '部屋':
blynkAuthToken = '**********'; // 部屋の温湿度計のtoken
break;
case 'ベランダ':
case '外':
blynkAuthToken = '**********'; // ベランダの温湿度・気圧計のtoken
break;
}
var measurement = JSON.parse(event.body).result.parameters.Measurement;
if (measurement === '') {
measurement = '温度';
}
switch (measurement) {
case '気温':
case '温度':
blynkPin = 'V1';
break;
case '湿度':
blynkPin = 'V2';
break;
case '気圧':
blynkPin = 'V3';
break;
}
var httpPromise = new Promise( function(resolve,reject){
http.get({
host: 'blynk-cloud.com',
path: '/' + blynkAuthToken + '/get/' + blynkPin,
port: '80'
}, function(response) {
// Continuously update stream with data
response.on('data', function(d) {
body += d;
});
response.on('end', function() {
// Data reception is done, do whatever with it!
console.log(body);
resolve('Done Sending');
});
});
});
httpPromise.then(
function(data) {
console.log('Function called succesfully:', data);
var info = parseFloat(JSON.parse(body));
speechOutput = 'よしよし、いい子だね。ご褒美をあげるよ。' + location + 'の' + measurement + 'は';
switch (measurement) {
default:
case '気温':
case '温度':
repromptText = speechOutput + info.toFixed(1) + '℃だ。';
speechOutput = speechOutput + info.toFixed(1) + '度だ。';
break;
case '湿度':
repromptText = speechOutput + info.toFixed(1) + '%だ。';
speechOutput = speechOutput + info.toFixed(1) + 'パーセントだ。';
break;
case '気圧':
repromptText = speechOutput + info.toFixed(0) + 'hPaだ。';
speechOutput = speechOutput + info.toFixed(0) + 'ヘクトパスカルだ。';
break;
}
console.log(speechOutput);
callback(null, {
"statusCode": 200,
"body": JSON.stringify({
speech: speechOutput,
displayText: repromptText,
source: "AWS API Gateway"
})
});
},
function(err) {
console.log('An error occurred:', err);
}
);
};
コードを置き換えたら保存します。
トリガーの部分は、次の「Amazon API Gateway」で設定すると表示されるようになります。
DialogflowのwebhookからAWS Lambdaを利用する場合には、LambdaのトリガーとしてAPI Gatewayを作成します。
API Gatewayを作成するには、まず、リージョンを「東京」に変えて、AWSサービスの「最近アクセスしたサービス」か「すべてのサービス」から「API Gateway」をクリックします。
API名は設定画面でしか使われないので適当に付けてしまいましょう。
メソッドの作成
作成の手順は若干わかり難いです。
まず、リソースのアクションから「メソッドの作成」を選びます。
プルダウンリストから「POST」選びます。
チェックマークをクリックします。
するとセットアップ画面になります。
LambdaリージョンはLambda関数を作成したときのリージョンを選択します。「ap-northeast-1」が「東京」です。実際に存在しているLambda関数を指定しないとエラーになるので、先にLambda関数を作成しておきましょう。
APIのデプロイ
次に、リソースのアクションから「APIのデプロイ」を選びます。
ステージはテスト用や本番用、バージョン毎などで作成(デプロイ)することができます。最初は「新しいステージ」を選んでステージ名に「test」などと付けておきましょう。
ステージが作成されると「URLの呼び出し」が表示されます。このURLをDialogflowのFulfillmentのWebhookのURLに設定します。
テスト
DialogflowでIntegrationsメニューを選び、Google Assistantクリックするとこの画面が表示されます。
「TEST」をクリックするとActions on Googleが開いてアップデートが行われテストができる(アプリが使える)ようになります。
おわり