#やったこと
Google Assistant経由で、Watson Assistantと対話するサンプルはすでにIBM Developerサイトに掲載されており、gitでコードも公開されています
ただし、Google Assistantの"Actions On Google"は、もともとは「Dialogflow」というものが利用されていたものの、2020/6に「Conversational Actions」がリリースされ、こちらが標準になったようです。公開されているサンプルはDialogflow前提のようなので、この記事ではConversational ActionsでWatson Assistant対話させてみました。
ただし、対応はまだ中途半端で、以下の制約があります。
・Google Assistantの固定のシーン(Watsonで言うダイアログ)で会話させるようにしているが、検証で確認している限り、同じシーンに3回戻すと強制的に会話が終了されてしまう
・Watson Assitantの会話終了を拾って、Google Assistant側の対話を終了するハンドリングが未実装
参考.Watson Assistant を利用して Google アクションを作成する
https://developer.ibm.com/jp/technologies/artificial-intelligence/patterns/create-an-agent-for-rental-car-reservations/
参考.watson-google-assistant
https://github.com/IBM/watson-google-assistant
#概要
Conversational ActionsからIBM Cloud Functions経由でWatson Assistantにリクエスト、レスポンスを受け取ります。IBM Cloud Functionsで、Conversational ActionsとWatson Assistantとでやり取りさせるために、jsonパラメーター上のデータの入れ替えを行っています。
#解説
##Conversational Actionsの設定
Main InvocationとNo_matchインテントから、webhooksを呼び出す設定にしておく。そして「askwatson」というSceneを作成しています。こうすることでWebhooks経由でWatson Assistantにリクエストが飛び、google Assistant上では「askwatson」というscene上で処理が進みます。
詳細は手順参照。
##Conversational Actionsのリクエストのパース
Conversational Actionsからリクエストを受け取り、パースしている部分のコードを以下に記載しています。
sessionIdとsceneの名前を取得し、グローバル変数に格納しています。
Watson Assistantのcontextは、Google Assistantのセッションストレージというパラメーターに格納されている想定で取得しています。
参考.Session storage
https://developers.google.com/assistant/conversational/storage-session
if (!args.__ow_body) {
return reject(errorResponse('body is required'));
}
console.log("__ow_body:")
console.log(args.__ow_body);
const rawBody = Buffer.from(args.__ow_body, 'base64').toString('ascii');
console.log("rawBody:");
console.log(rawBody);
const body = JSON.parse(rawBody);
console.log("body:");
console.log(body);
// google assistant attributes hold our context
const googleAssistantSessionStorage = body.session.params;
console.log('googleAssistantSessionStorage attributes:');
console.log(googleAssistantSessionStorage);
if (typeof googleAssistantSessionStorage.hasOwnProperty(googleAssistantSessionStorage, 'watsonContext')) {
console.log("set watsonContext from googleAssistantSessionStorage.")
context = googleAssistantSessionStorage.watsonContext;
} else {
context = {};
}
//global googleSesionId
googleSesionId = body.session.id
googleScene = body.scene.name
const query = body.intent.query;
console.log('input:' + body.intent.query);
console.log('context:'+context)
##Watson AssistantのレスポンスをConversational Actionsに返す
sessionIdとsceneをセットし、Watson Assistantのcontextは、Google Assistantのセッションストレージに格納して返しています。
参考.conversational actionsのwebhookのパラメータ
https://developers.google.com/assistant/conversational/webhooks
function sendResponse(response, resolve,reject) {
try{
console.log('Begin sendResponse');
// console.log(response);
// Combine the output messages into one message.
const output = response.result.output.text.join(' ');
console.log('Output text: ' + output);
resolve({
body:formatResponseForGoogleConv(output)
});
}catch(err){
reject({body:formatResponseForGoogleConv(err)});
}
}
function formatResponseForGoogleConv(outputText){
console.log("outputText");
console.log(outputText);
console.log("googleSesionId");
console.log(googleSesionId);
console.log("context");
console.log(context);
console.log("googleScene");
console.log(googleScene);
return {
"session": {
"id": googleSesionId,
"params": {
"watsonContext":context
}
},
"prompt": {
"override": false,
"firstSimple": {
"speech": outputText,
"text": ""
}
},
"scene": {
"name": googleScene,
"slots": {},
"next": {
"name": "askwatson"
}
}
}
}
#手順
リポジトリはこちら。利用手順はReadmeに記載しています。
https://github.com/GodaiAoki/watson-google-assistant/blob/master/README.md