IBM Code Patternsのこちらのシナリオをもとにちょっと改変したアプリを作成し、気づいた点や構築にあたって気をつけるべき点などを書いて見たいと思います。
どんなアプリ?
名前は「受付係アレクさん」。いわゆるホテルでの自動受付アプリです。
Alexaを利用して音声を認識させ、スタッフが忙しい時でも受付業務を代行してくれます。スピーカーに話しかけるとチェックインとチェックアウトの処理をしてくれます。
ん?そんなのタブレットで操作させれば良いって?
ああ、なるほど。
ん?最近はチェックアウト不要なホテルも増えてるって?
うんうん、なるほど。
ちょっと何言ってるか分かりません。さあ、解説を進めましょう!
アプリの画面イメージは以下の通りです。
!?
画面無い!画面無いよ!!
んー、あまりにも寂しいので、ブラウンくんに登場してもらいます。
うーん、スマートスピーカーにスマートスピーカーという、もはやEchoじゃなくてClovaで良いんじゃね?案件になってしまいます。
うん、丁度良いやつがいました!エネゴ…いやVSモンキーくんです。おー、何かホントに受付に居そうじゃないですかー
これで行きましょう!
と、言うことでこのアプリについては所謂「画面」はありません。スピーカーへ話しかけ、スピーカーから返事をもらう、それだけのアプリです。でも、必要な処理は行います。そう、サーバーサイドでね。ここでIBM Cloudの出番なわけです。
今回のアプリはデータは保持するものでは無いので、データベース構造などの説明はありません。サーバーサイドで利用するNode-REDはそのフローを永続化するためにCludantを利用します。が、ここは把握する必要はありません。どんどん作っていきましょう。
このアプリケーションのバックエンドは、Node-REDで処理を制御します。会話の実態を成すのはWatson Assistant APIです。会話内での自然言語解析を行い、必要な言葉(今回ですと”チェックイン”とか”チェックアウト”とか、お客様のお名前とか)を拾い上げます。拾い上げた言葉をパラメーターにして、実際の処理(チェックイン・アウト)を行います。ここはFaaS(Serverless)のIBM Cloud Functionsで実装します。実際にホテル内の業務処理部分は実装できないのでスタブとしておきます。非常にシンプルな分かりやすいシナリオではないかと思います。
このアプリを一通り作成すると、以下のことを理解することができます。
- Amazon Alexaを使ったアプリケーションを構築する
- Node-REDでWatson Assistant APIを制御し外部インターフェースと連携させる
- IBM Cloud Functionsの使い方
アプリ構成図
必要な環境
以下の環境を準備しておく必要があります。事前に済ませておきましょう!
- Amazon Echo または Echo Dot ※今回はDotを使ってます
- Amazon Alexaアカウント
実装してみる
1. IBM Cloud Functionsの作成
IBM Cloud FunctionsとはいわゆるServerless、Function as a Service、Event Driven Applicationと呼ばれる種類のものです。Apache OpenWhiskがベースとなっているIBM CloudのFaaSになります。
IBM Cloudのダッシュボード左側のメニューからFunctionsを選択し、Create Actionを選択します。
Actionに適当な名前を付けましょう。ここでは「callReceptionist」としています。
そうしたら、サーバー処理を書いていきます。本来ならここで、既存のチェックイン/アウト処理とつなぐのがBestですが、私はそんなエンタープライズシステムは持っていないので、適当なスタブを作ります。
言語は何でも良いのですが、今回はNode.jsで行きましょう。
/**
*
* main() will be run when you invoke this action
*
* @param Cloud Functions actions accept a single parameter, which must be a JSON object.
*
* @return The output of this action, which must be a JSON object.
*
*/
function main(param) {
var resultJson = {};
if (param.purpose == "checkin") {
// チェックイン成功
resultJson = { message: 'チェックイン処理が完了しました' };
} else if (param.purpose == "checkout") {
// チェックアウト成功
resultJson = { message: 'チェックアウト処理が完了しました' };
} else {
// 該当処理無し
}
return resultJson;
}
実装はこれでOKです。まあただの定数返すだけのスタブなので簡単ですよね。本来は、ここが既存システムをAPI化したGatewayになるイメージです。
次に、このアクションをWEB呼び出しできるようにしてあげます。と、言っても設定でチェックを入れるだけです。画面左上の「Web Action」ボタンをクリックして「Enable as Web Action」「Raw HTTP handling (Optional)」にチェックを入れます。
そうしたら、コマンドラインからチェックしてみましょう。
curl -H 'Content-Type:application/json' -d '{"purpose":"checkin"}' -u <自分のAPIキーを指定して下さい> -X POST https://openwhisk.ng.bluemix.net/api/v1/namespaces/<自分のAPIエンドポイントURLに合わせて下さい>/actions/callReceptionist?blocking=true
以下のようなレスポンスが帰ってくれば成功です。
{"activationId":"c6edfb3fbe5d4d33adfb3fbe5d5d33c6","annotations":[{"key":"path","value":"Developer Advocacy_Cloud Developer Advocacy/callReceptionist"},{"key":"waitTime","value":448},{"key":"kind","value":"swift:4.1"},{"key":"limits","value":{"logs":10,"memory":256,"timeout":60000}},{"key":"initTime","value":2153}],"duration":2171,"end":1543216533393,"logs":[],"name":"callReceptionist","namespace":"Developer Advocacy_Cloud Developer Advocacy","publish":false,"response":{"result":{"msg":"チェックイン処理が完了しました"},"status":"success","success":true},"start":1543216531222,"subject":"taijih@jp.ibm.com","version":"0.0.1"}
なお、Functionsでは、GUIでActionの動作確認を簡単に行うことが可能です。
Codeペインの上部「Change Input」をクリックして、InputパラメータをJSON形式で指定できます。そのまま「Invoke」をクリックすると、Actionが実行され、右側にActivationペインが出現し結果が表示されます。
2. Node-REDの作成
Node-REDでは、Echoからの音声をトリガーにして、先ほど作成したActionを呼び出して、結果を返す部分を実装します。実際の対話部分はWatsonのAssistant APIを使います。
IBM Cloudのカタログから、スターターキットカテゴリを選択し、Node-RED Starterを選択します。
Node-REDはWebアプリケーションです。アプリ名はそのままパブリッククラウド上にWebアプリとして公開されるNode-REDフローエディタのURL(サブドメイン部分)になります。他人と重複しなさそうな名前を指定してください。料金プランはLiteが選択されていることを確認し、作成ボタンをクリックします。
アプリのステータスが実行中(running)と変わったら作成成功です。だいたい5分くらいで起動しますが、もう少しかかることもあります。まれに、未実行とか停止中となって止まってしまう(GUI上、止まっているように見える)ことがあるので、その場合は慌てずに再度開始/再起動して見てください。
3. Watson Assistant APIの作成
今回のアプリはいわゆるボットアプリです。ユーザーインターフェースはスマートスピーカーですが、裏ではチャットボットの会話を処理する必要がありますね。ここにWatson Assistantを使っていきたいと思います。
IBM Cloudのカタログから、AIカテゴリを選択し、Watson Assistantを選択します。
料金プランがLiteになっていることを確認して作成ボタンをクリックします。
4. Node-REDとWatson Assistantの接続
先ほど作成したNode-REDアプリのCloud Foundryの管理画面で接続タブ(Connections)にて、Watson Assistantを接続します。これにより、Node-RED上でWatson Assistantを資格情報無しで利用することが可能になります。
新しい接続の作成(Create Connection)ボタンをクリックすると、接続可能なサービスが一覧で表示されます。その中から先ほど作成したAssistantのサービスを選択します。マウスオーバーすると接続ボタンが表示されます。
デフォルトの設定のまま接続(Connect)ボタンをクリックします。そのままNode-REDの再ステージングが実行されます。再びアプリステータスが実行中になれば無事接続完了です!
5. Watson Assistant 会話定義の作成
Watson Assistantは自然言語を解析し、会話文の中からその会話の意図や目的をクラス分けし、そのクラスごとに返す会話を定義していくことができます。 通常であれば、一から作成するのですが今回は簡単に用意したフローの定義をインポートしてしまいましょう!そう、3分クッキングのあれです。「はい、出来上がりはこちらです」
作成したWatson Assistantサービスの管理画面より、ツール起動ボタンをクリックしてツールを起動します。別ウィンドウでツールが開きます。
上に3つ並んでいるメニュータブからSkillsを選択します。Create Newボタンをクリックして下さい。
画面が代わりますので、3つ並んでいるメニュータブから、Import Skillを選択し、Chose JSON Fileをクリックします。ファイル選択ダイアログが表示されるので、こちらのJSONファイル を選択しImportボタンをクリックして下さい。これで会話の作成は完了です。
6. Alexa Skillを設定する
amazonのAlexa Developer Consoleへアクセスします。アカウントをお持ちでない方はアカウントを作成して下さい。
「amazon alexa」を選択します。
「Alexaスキルの開発を始める」を選択します。
「Alexa Skill Kitを使ってみよう」を選択します。
「Alexa Skill Kit」を選択します。
「スキルの作成」を選択します。
スキル名を設定して下さい。ここでは「アレクさん」としてます。言語は「日本語」を設定して下さい。モデルは「カスタム」が選択されていることを確認して下さい。
呼び出し名を設定します。呼び出し名とは、会話のトリガーになるフレーズのことです。ここでは「アレクさんこんにちは」にしています。
次にインテントを設定します。インテントは会話の意図を拾い上げるものですが、今回は実際の会話はWatsonで行うため、すべてを同じ意図に導きます。なのでインテント名を「EveryThingIntent」とし、サンプル発話には「{EveryThingSlot} 」を設定して下さい。
次にスロットタイプを設定します。スロットタイプの追加から「HOTEL_RECEPTION」というスロットタイプを作成します。こちらも同様に会話はWatsonで行うのですが、Alexa側の仕様上、スロットタイプに値を設定する必要があります。[スロット値]の下にある[このスロットタイプの新しい値を入力]のところに、ダミーとして「ハローワールド」を設定して下さい。
先ほど作成したEveryThingIntentの設定に戻り、インテントスロットを追加して下さい。プルダウンの選択肢の中に一つ前の手順で作成した「HOTEL_RECEPTION」が出現するはずですので、こちらを選択します。
ここまで出来ましたら、「モデルのビルド」ボタンをクリックします。ビルドが開始し、間もなくビルドが成功した旨がメッセージで表示されればOKです。
そうしましたら、このスキルへアクセスするためのエンドポイントURLを設定します。今回はLambdaを使わないので「https」を選択して下さい。
設定するURLは以下のルールで設定して下さい。ここを間違うとアプリが連携出来ないのでご注意下さい。
<先ほど作成したNode-REDのURL>/reception
例)https://alec-san-app.mybluemix.net/reception
入力項目を埋めていき、ページを進めて下さい。入力値やプライバシーとコンプライアンスの回答項目は画像を参考にし、ご自身に合わせて入力・回答下さい。
ベータテスト対象ユーザーのメールアドレスを設定し(ご自身のメールアドレスでOKです)、公開を選択して下さい。これですべて完了となります。
7. Node-REDですべてをつなぐ
Node-REDを使って、Alexa → Node-RED → Watson Assostant → Functionsをつなげていきます。今回は完成形のフローを用意してありますので、こちらをインポートしてご利用下さい。
IBM Cloudのダッシュボードから、作成したNode-REDアプリを選択します。アプリURLのリンクをクリックすると別ウィンドウでNode-REDフローエディタの画面が開きます。
右側の「Go to your Node-RED flow editor」ボタンをクリックするとユーザーパスワードを求められますので、先ほど設定したユーザーパスワードでログインします。
フローエディタ画面の右上のメニューから、インポート→クリップボードを選択します。こちらにflow.jsonの中身を貼り付けてインポートして下さい。
以下のようなフローが再現されると思います。
フローの解説をします。
httpリクエストノード:
パスに「/reception」が指定されています。先ほど、Alexa SkillのエンドポイントURLで指定した意味がこちらになります。Node-REDアプリのURL(https://xxx.mybluemix.net
)にここで指定したパスを足した(https://xxx.mybluemix.net/reception
)がAlexa SkillのエンドポイントURLになると言うわけです。
各functionノード: ノードの名前に行っている処理内容を設定しています。基本、その処理を行っているだけです。
Watson Assistantノード: 作成したWatson Assistantを呼び出します。先の手順にて、Node-REDアプリとAssistantサービスを接続済みなので、認証設定は不要で使うことが出来ます。ワークスペースIDを設定する必要があるので、ご自身のIDを設定して下さい。
Switchノード: Assistantから返却された内容により、処理を分岐しています。Assistantの処理でチェックインかチェックアウトに関する会話と判断された場合はそれそれChangeノードへ進みます。それ以外はそのまま返却JSON生成のfunctionノードへ進みます。
Changeノード: チェックインかチェックアウトの会話とみなされた場合に、Functions(OpenWhisk)処理へ渡すためのパラメーターを用意しています。
OpenWhiskノード: 作成したFunctions(OpenWhisk)の処理を呼び出すノードです。作成したActionを呼び出すように設定を変更して下さい。 Service → OpenWhisk Serviceを選択 Namespace → 自分の環境のNamespaceが自動で反映されるのでそれを選択 Action → IBM Cloud上のFunctionsで作成したAction名「callReceptionist」を選択
と、言うことで編集しなくてはならないのはAssistantノードとOpenWhiskノードですね。 これらを上記の内容で変更したら、画面(フローエディタ)右上のデプロイボタンをクリックして下さい。
これで全ての構築が完了しました。 では、動作を確認してみましょう!
動作確認
Alexa Developer Console画面のテストタブから「アレクさんこんにちは」と呼びかけテストしてみて下さい。チェックインに関する会話を投げかけるとチェックイン、チェックアウトに関する会話を投げかけるとチェックアウトの、それぞれ処理が行われた結果を返答してくれると思います。
開発したスキルは、自分のAmazon Developerアカウントに紐付いているデバイスで検証することができます。実機で確認するためには、echoでAlexa Skillを有効にします。詳細の手順はamazonの公式サイトを御覧ください。
https://www.amazon.co.jp/gp/help/customer/display.html/?ie=UTF8&nodeId=201848700&ref_=sv_a2s_6
やったぜ、エネ、いやアレクさん!
最後に
今回の実装で、必要なファイル類は、私のGitHubに置いてありますので、必要に応じご参照下さい。
https://github.com/taijihagino/alec-san
さて、いかがでしたでしょうか?
今回はAlexa、Watson、OpenWhisk(Functions)、Node-REDと、盛りだくさんな内容でお届けしましたが、色々応用が効くことがおわかり頂けたと思います。
ではでは!