Amazon EchoとIBM Watsonを連携させてみた - パート1 -

# **はじめに**
* [Ishiiさんの投稿](https://qiita.com/e21084/items/38e2407e3b6fff0e40f3)に触発されて、Amazon EchoとIBMのWatson（Conversation）との連携をやってみた。
* 最初は試行錯誤でIntentを両方に持たせてしまったりエラく複雑になったけれど、[IBM公式](https://developer.ibm.com/code/patterns/create-an-alexa-skill-with-serverless-and-a-conversation/)をみつけて修正を加えたら、最終的にとてもシンプルになった。
* 今回やってみたのは、Alexaにハローワールドと呼びかけてWatsonからランダムに回答を返すだけの仕掛けだが、対話のフローをうまく作ってあげると面白いことができそうだ。
* やってみるとAlexaとWatsonの使い方の違いや共通点もわかってくるので、興味のある人は試して見てほしい。
* なお、いずれもクラウドのサービスであり画面や機能は日進月歩で変わっていくので、今後必ずしもこの通りの手順でできない場合があることは、ご容赦願いたい。


# **前提**
* 必要なもの:
* IBM Cloudのフリー・アカウント([ここ](https://console.bluemix.net/#/upgradeAccount/orgGuid=9c5af262-d2fe-4c62-b6c2-9bbceb8abd2a&showExpirationPane=true)) -> IBMのWatsonとNode-RED(APIやデバイスの間を簡単に繋ぐツール)を利用する。今回はクレジットカード登録なし(機能制限あり)で利用した。
* Amazon Developerアカウント([ここ](https://developer.amazon.com/home.html)) -> Alexa Skills Kitを使うために必要。AWSをすでに使っていればそのアカウントと共通で使える(ショッピングのAmazonアカウントではない)。こちらはクレジットカード登録が要るけども、今回作るものでは課金はされない。
* Amazon Echo -> なくても作成したSkillのテストまではできる。今のところ購入は招待制なので、Amazonから招待メールがこない限り、ほしいときに手に入らないのが難点。
* RESTテストツール -> AlexaからWatsonを呼び出すときにいちいちAlexaのテストツールを起動するのは煩雑な時がある。その様な場合はRESTのテストツール(各ブラウザのプラグインやPostmanなど)を使うと便利である。この記事にある手順で作業をする分にはなくても良い。

# **作業の流れ**
* 全体をイメージであらわすとこの様になる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/7432d18e-9a2f-c5ae-e7ca-7bf8299ac61c.png)



# **1. IBM Cloudとつなぐ**
* AmazonのDeveloper ConsoleからAlexa Skills Kit(ASK)のメニューに入って、Add a New Skillで開始する。

* 今回は対話を作るので、Skill TypeにCustom Interaction Modelを指定。Languageは日本語、NameはAlexaアプリに表示される名前を指定する。Invocation Nameには、AlexaからこのSkillを呼び出すときの呼び名を設定する。あとはデフォルトで良い。ほかにも例えばFlash Briefing Skill APIを使うと、好きなRSSフィードや音声ニュースを順番に読み上げさせるSkillを簡単に作れる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/7031cc34-34b6-e3af-06af-279002406200.png)

* Next -> Save -> Nextと進み、Interaction ModelでSkill Builderを起動すると、この様なダッシュボードが開く。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/0468291c-dde7-fbe4-b24e-bb1615f058fd.png)

* デフォルトで、Built-ins Intentsが3つ定義されている。Intentsとは、対話で"何をさせたいのか？"の"何"にあたるコトをさす。例えばCancelIntentとStopIntentにはスキルを止めるための設定がプリセットされていて、"Alexa,止めて"などと呼びかけると、いずれかのIntentに引っかかって決められたAction＝スキルの終了、が実行される。なおBuilt-ins IntentsはAWSが提供するものでありユーザーが中身を変えることはできないが、これらのIntentsを継承して、カスタムIntentsを作ることはできる。とにかく、ここはそのままで良い。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/7dbcd570-2d65-c755-0d96-80aee571e762.png)

* 次にWatsonとつなぐ際に使うIntentを作成する。Add an Intentより以下の様に作成する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/614118e9-0b9d-a8de-e1bc-0fd6addb152e.png)

* Sample Utterancesに以下の様に登録する。通常は"止めて","止める"などこのIntentに引っかけるための発話例を登録するが、今回は全ての発話をこの1つのIntentに引っかけてそのままWatsonに渡したいので、{}で囲って変数にする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/d35f1217-0213-3079-1b60-02bc5b5caf83.png)

* そうするとIntents Slotに定義した変数が現れる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/5a74139c-721e-2bc4-1d6d-b6a5a2d3f2f9.png)

* 次にSlot Typesのところで、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/e8ae0f5d-8e19-81bd-d1ff-7807bc04691c.png)

* BAG_OF_WORDSというスロットタイプを定義する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/359bed49-6805-c497-3b7d-74e3e617534b.png)

* ここでEveryThingSlotに戻ってスロットタイプに今作成したBAG_OF_WORDSを指定する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/393ecb81-b783-a8bd-9b51-e08e040fda71.png)

* ここでも、いくつかAMAZON.*という名前のプリセットされたスロットタイプがあることがわかる。あらかじめAWSが用意している変数、例えば、都市名とか日付とか、をつかいたい場合は、ここで指定すれば良い。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/d5b23fe9-8ab5-4751-c854-c972e5d576fd.png)

* 先ほどは飛ばしたが、自分で作った変数(スロットタイプ)に対して、値を入れることもできる。例えば、ANIMAL_SLOTを作った場合は、犬、猫、兎などの値を入れることで、"犬","猫","兎"と発話した際にこのスロットに引っかかり、このスロットを登録したIntentsが呼び出されることになる。今回は全ての値を拾わせるので本当は登録は必要ないが、何か1つは登録が必要なので、ハローワールドと登録しておく。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/372c23e2-07a5-13a2-1193-81ab2376136a.png)

* 最初、このスロットの使い方がわからずハローワールド専用のIntentを作っていたため、同じIntentをWatsonとASKの両方に持たせなければいけないというとんでもないデザインになっていたが、IBM公式で変数を使う方法がわかったので、この様にシンプルに作ることができた。

* 以上でInteraction Modelが完成したので、Built Modelをする。1-2分で完了する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/a8fe811a-05b7-7776-1cb1-221cfd45679c.png)

* ConfigurationをクリックしてSaveして次に進む。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/e47db2af-b759-9008-544c-b42df6ef03f3.png)

* この様な設定画面が出てくる。ここでは作成しているAlexaスキルが呼び出すバックエンドのリソース名を指定する。AWS Lambdaを使う場合はARNを指定するが、今回は外部のリソースを使うので、HTTPSを指定する。Defaultには、呼び出す先のリソース名(URL)を指定する。Provide geographical region endpointsはNoとし、あとはデフォルトで良い。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/8c5e5788-10c8-d1e4-c1aa-dddec56699db.png)

* Nextで次に進むとセキュリティレベルの指定が求められるが、今回は2番目を指定する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/8abefdb0-7ab7-4245-4635-d08572ca946a.png)

* ここまでくるとASKの設定はほぼ終わりだ。Build Modelが完了しているならテストのフラグを有効にしておこう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/672446bc-76d8-098d-7039-26e8b60c5c9f.png)

* 画面をスクロールするとサービスシュミレーターが出てくるのでテストをしてみよう。発話にハローワールドと入力するとJSON形式のサービスリクエストが出ていることがわかる。サービスレスポンスは接続先がまだないのでエラーが返ってくる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/224839/37b2e522-a6a5-a6ce-0af4-b942cf4abbe7.png)

* ASKでの作業はここまでである。

* パート2に続く


# **関連記事**
* [Amazon EchoとIBM Watsonを連携させてみた - パート2 -](https://qiita.com/TMR1000/items/79110dbef585dca45b2f)
* [Amazon EchoとIBM Watsonを連携させてみた - パート3 -](https://qiita.com/TMR1000/items/ca154882e25dbf0bacea)
* [Amazon EchoとIBM Watsonを連携させてみた - パート4 -](https://qiita.com/TMR1000/items/d3d2c1086c9cc72e1897)

以上