Amazon Alexaのサンプルを実装してみる

#この記事は何？
Google AssistantのActionは使った開発はしたことはあったけどAlexaのSkillは未体験だったし、ここ数回AWSさんのConferenceだったり、Meetupに参加させていただき興味が湧いたので作ってみることにしました。

なにはともあれ「実装するならまずはチュートリアルでしょ」と思って進めたのですが、デザイン更新直後だったのか公式の英語のチュートリアルでさえUIが違っていて、すんなりと試せなかったのでここに書き残すことにしました。

この記事を書いたのは、2018年4月28日です。ご覧になっている今、更にUI等が変わっている可能性もありますのでお気をつけください。


#実装の内容
[Node.jsでFunction（って呼び方で正しい？）を実装するサンプル](https://developer.amazon.com/alexa-skills-kit/alexa-skill-quick-start-tutorial-nodejs)を実装します。

このサンプルの動作は、自分の好きな色をAlexaに覚えてもった上で、「私のの好きな色は？」という問にAlexaが答えてくれるというSkillです。


#Alexa Skillの動作概要
AlexaのSkillの基本的な仕組みは大きく2つのブロックに分けられます。

- **Amazon Alexa**： マイクから拾った音声を解析して、コンピュータが理解できる形に翻訳して出力する部分。Google Assistantですと[Action on Google](https://console.actions.google.com/)です。
- **AWS Lambda**： 翻訳後の出力に従って、設計した動作を実行するアルゴリズム、ロジックを記述する部分。Google AssistantだとFulfillment(Dialog Flow内の)にあたります。

という説明で、なんとなく2つの実装をして初めて動くというのが伝わっていたらうれしいです。そうなんです2つのパーツを実装が求められます。

スクリーンに表示するWebだったり、スマホのNativeアプリケーションで説明すると、Amazon Alexaがスクリーンに表示されるボタン、テキストボックス等で、AWS Lambdaがスクリーンのボタンをクリックした後に何が動くか指定している部分です。

それでは実際に実装の説明に進みます。図で表すとこんな↓感じでしょうか。Amazon Alexaが音声で命令を受付、その命令を解釈した上でAWS Lambdaに向けてそれに対応する動作を行う、というイメージです。
（イラストの一部は[ここ](https://developer.amazon.com/ja/blogs/alexa/post/cddf2434-42ee-422f-886d-5be9c36dba14/jp-training-chapter3)のを利用しています）
<img width="500" alt="Screen Shot 2018-04-28 at 12.23.15 AM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/d03c0d29-ec52-697f-59ae-d6b1e6aecc5b.png">



#事前準備
アカウントの準備が必要です。2つのサイトでアカウントを作成する必要があります。
以下の2つが必要ですので事前に作っておきましょう。
- [Amazon Web Service](https://aws.amazon.com/)のアカウント
- [Amazon Alexa](https://developer.amazon.com/)のアカウント

##Amazon Web ServiceのLambdaでFunctionを作成＆ロジックの実装
[コンソール](https://console.aws.amazon.com)を表示して、テキストフィールドに**Lambda**と入力して検索します。
<img width="450" alt="Screen Shot 2018-04-27 at 4.05.42 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/1cdcef34-b6e1-b869-43b1-81bec93d00ed.png">

続いて、次の画面の右上、の部分の(1)が**N.Virginia**になっていることを確認して(2)をクリックします。
<img width="358" alt="Screen Shot 2018-04-27 at 4.08.49 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/037a8b73-78f0-2ee2-ac76-5d543917558a.png">


次にどんなFunctionを作成するかを選択します。
表示された画面の上部で(1)の**Blueprint**を選択して、画面中程のテキストボックスに**alexa-skills-kit-color-expert**と入力して検索して、選択（クリック）して、画面右下の**[Configure]ボタン**をクリックして次の画面に進みます。
<img width="450" alt="Screen Shot 2018-04-27 at 4.15.17 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/aafd290d-48a4-80eb-5c51-235ca3bffb82.png">

ここから、作成するFunctionの詳細を入力していきます。
表示された画面で以下の設定を行います。

- Nameに**myColorSkillNodejs**と入力
- Roleは**Create a custom role**を選択

<img width="450" alt="Screen Shot 2018-04-27 at 4.21.51 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/deb52100-4f81-92cf-399f-cf10637464d7.png">

すると別ウィンドウで「AWS LambdaはIAM roleを使うから・・・」という画面↓が表示されますがビックリしないでください。
<img width="350" alt="Screen Shot 2018-04-27 at 4.22.46 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/046cfb75-7b9c-1e41-257d-39c0f5c2ef08.png">

以下のように選択して、画面右下の**[Allow]ボタン**をクリックして次に進みます。

- IAM Role: lambda_basic_execution
- Policy Name: Create a new Role Policy

**[Allow]ボタン**をクリックする元の画面に戻り、値が入力されていると思います。その状態で次に進みましょう。

<img width="450" alt="Screen Shot 2018-04-27 at 4.28.23 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/c39e1745-4360-27c1-ef2c-8454cb224c5d.png">
こんな画面↑が出てきますが、この中の**alexa-skills-kit**はここではDisableにしておきます。ここにはAlexaのSkillにユニークに与えられるIDを入力するのですが、現在の状況ではまだそのIDは取得できていません。なので、Disableにして次にすすみます。

その他の項目は変更せずに**[Create Function]ボタン**をクリックしてFunctionの実装は完了です。

ここまでで「Amazon Web ServiceのLambdaでFunctionを作る」は一旦終了です。Alexa Skillを作成が完了したら**Skill ID**を登録しに戻ってきますので忘れないようにしましょう。

##Amazon Alexaの実装をする

（画像はほとんど991px以下の場合になります）

###Skillの作る
Amazon Alexaの[Skill一覧画面](https://developer.amazon.com/alexa/console/ask)↓を表示します。
<img width="450" alt="Screen Shot 2018-04-27 at 8.05.08 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/49bcd881-3d30-1e22-108e-c79a59de8385.png">
その画面で**[Create Skill]ボタン**をクリックして、新たにSkillを作成します。

この画面↓でSkillの名前を指定します。Skillを呼ぶ時の名前ではありませんのでチャチャッと決めちゃいましょう。ここではNameのところに**Color Picker**と入力し**[Next]ボタン**で次に進みます。
<img width="450" alt="Screen Shot 2018-04-27 at 8.12.29 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/3ddb5e25-96fa-88ee-3130-51191c03933d.png">

次にSkillのモデルを選択します。今回は(1)の**Custom**を選択（クリック）して、(2)の**[Create skill]ボタン**をクリックします。
<img width="450" alt="Screen Shot 2018-04-27 at 9.38.50 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/55f7d1e1-5844-de9e-b4bf-cf4cf5ed16bf.png">

すると、こんな画面↓が表示されるはずです。
<img width="450" alt="Screen Shot 2018-04-27 at 10.01.14 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/d5c05fee-2262-7a75-3b06-2cdf1925d04c.png">

### Skillの名前を決める
次に、この画面の右側の**Skill builder Checklist**を設定していきます。
まず**「1. Invocation Name」**からです。この名前がSkillを呼び出す時の使う名前になりますので呼びやすく、更に、何の動作がされるSkillかが名前から推測できるようになっていると良いと思います。
(1)にNameを入れて、(2)の**[Save Model]ボタン**をクリックします。ここではSkillの呼び出し名を**color picker**としています。

<img width="450" alt="Screen Shot 2018-04-27 at 10.03.49 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/d1bdbb9a-bd8b-7362-1553-4c78dc29762d.png">


### Slot Typesを追加する
Slot TypeはIntentに紐付けます。Intentとは、音声を解析したときにある動作をさせる為のキッカケ（以後「フック」と書きます）になる文章だったり言葉というイメージです。そのフックの中で更に細かい内容として認識した言葉（このチュートリアルでは「色」）をここで指定していきます。

左メニューの**Slot Types**の横にある**+**をクリックすると、画面右側が下の画像↓のようになります。**Create custom slot type**に**LIST_OF_COLORS**と入力して**[Create custom slot type]ボタン**をクリックして次に進みます。
<img width="450" alt="Screen Shot 2018-04-27 at 10.41.12 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/3fc970a6-d4e2-efd5-5ffe-f8f47165ab78.png">

Slot Valueに値を入力していきます。
red, blue, orange, gold, silver, yellow, black, white
を入れていきます。1つの単語を入力後「Enterキー」またはテキストボックスの右についている**+**をクリックすることで追加されます。 
<img width="450" alt="Screen Shot 2018-04-27 at 10.43.46 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/234ac5c2-e0a0-51ff-7e97-eeb458860860.png">
ちなみに、覚えてもらえる好きな色は、ここで指定した色のみということになります。

ここではまだ**[Save Model]ボタン**はクリックしないでください。もしクリックしてもエラーになります。クリックしてしまってもエラーになりますが気にしなくてOKです。

### Intentを追加します
先程も書きましたが、Intentとは、音声を解析したときにある動作をさせる為のフックになる文章だったり言葉というイメージです。このフックは、その後どんな処理、動作をさせるかの条件分岐に使いますので非常に重要な要素です。

1つ目のIntentは、好きな色をAlexaに覚えてもらう為のフック、という内容になります。

それでは、Intentを入力していきます。
Intentの名前を**MyColorIntent**として、**[Create custom intent]ボタン**をクリックします。
<img width="450" alt="Screen Shot 2018-04-27 at 10.20.13 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/2a48744e-3a84-6a54-b933-cb631e06ab1b.png">

次の画面の**Sample Utterances**に
**my favorite color is {Color}**
と入力して、右側の**[+]ボタン**をクリックして登録します。（入力中に、テキストボックスの下に更にボックスが出てきますが、特に気にしないでください）
<img width="450" alt="Screen Shot 2018-04-27 at 10.23.18 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/64c97600-cb45-9d05-df7c-544f17417083.png">

次に、追加で表示されるIntent SlotsのNameがColorの欄のSLOT TYPEに**LIST_OF_COLORS**を選択します。これで**Sample Utterances**で入力した**{Color}**が**LIST_OF_COLORS**の値を採りえますよ、ということを指定したことになります。
<img width="450" alt="Screen Shot 2018-04-27 at 10.47.46 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/bae3bcdd-0229-c654-1e2d-ebf4e96ac5e3.png">


### もう1つIntentを追加します。

このIntentでは、Alexaに覚えてもらった好きな色を教えてもらう為のフック、という内容になります。

左メニューのIntentsの右側にある**+ Add**をクリックして、**WhatsMyColorIntent**と入力して**[Create custom intent]ボタン**をクリックします。
<img width="450" alt="Screen Shot 2018-04-27 at 11.49.23 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/ab607e87-d736-4309-fc4f-72e62f107590.png">

次の画面でSampleのUtterancesを追加してきます。テキストボックスに入力して、テキストボックスの右端にある「+」をクリックまたは「エンターキー」で追加してきます。
<img width="350" alt="Screen Shot 2018-04-27 at 11.53.35 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/6def9dbf-df6a-7dfa-8fef-bddca1c6bd35.png">

今のリストを追加してください。面倒ならば、上の4つくらいでも充分遊べると思います。ただし、入力した文章でしかAlexaに覚えてもらった色を教えてもらえないので、注意しましょう。
- what's my favorite color
- what is my favorite color
- what's my color
- what is my color
- my color
- my favorite color
- get my color
- get my favorite color
- give me my favorite color
- give me my color
- what my color is
- what my favorite color is
- yes
- yup
- sure
- yes please


ここで**[Save Model]ボタン**をクリックして保存します。
<img width="450" alt="Screen Shot 2018-04-27 at 10.50.57 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/08fb589f-0dbc-860f-ba69-c67210991eca.png">

**[Save Model]ボタン**をクリックして、設定にエラーが無ければ以下のようなNotifivationが画面の右下に出てきますので確認しましょう。
<img width="350" alt="Screen Shot 2018-04-27 at 10.53.37 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/118c0abe-3f69-0723-e897-83b87f91b57e.png">

### Buildする
**Intentを作る**画面にも出てきていたのですが、ここでやっと**[Build Mode]ボタン**をクリックしてビルドします。
<img width="450" alt="Screen Shot 2018-04-27 at 10.57.23 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/8ed3dca1-037b-eab8-3816-749c6fa8fa83.png">

Buildを開始するとこんな↓Notificationが画面右下に表示され、
<img width="350" alt="Screen Shot 2018-04-27 at 11.00.57 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/184318bd-c325-f8cd-b070-843184b5f471.png">

Buildが完了するとこんな↓Notificationが同じく画面右下に表示されます。
<img width="350" alt="Screen Shot 2018-04-27 at 11.02.32 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/ca9a5eb9-ca8a-87f0-761b-69bf9b183ebe.png">

変更を加えた場合は、都度Buildを行い、変更内容を反映させる必要があるので忘れないようにしてください。

### Endpointを指定する
Endpointとは、今回の実装ではズバリ言えば先程実装したLambdaのFunctionです。どのFunctionに繋げるのかを設定します。


###準備：ARNを取得する
先程Lambdaで作成したFunctionはARNという文字列で定義されていますので、その文字列をまずは調べてコピーします。
[Amazon Web ServiceのLambdaでFunctionの画面](https://console.aws.amazon.com/lambda/home)に戻り、リストから実装したFunctionを選択して設定を表示します。
すると、設定がまとめて表示されてる画面が出てきますが、その右上に
**ARN - arn:aws:lambda:hogehoge** 
で始まる文字列が表示されていると思います。これがARNです。
<img width="450" alt="Screen Shot 2018-04-27 at 11.10.29 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/c420b4e3-4805-494a-4071-e885bbab9586.png">
**Skill ID**の設定もありますので、このページは別のタブに表示しておきましょう。

### Amazon Alexa側の設定
続いて、Amazon Alexa側にそれを設定していきます。
画面上にあるメニューの[Build]をクリックします↓。
<img width="350" alt="Screen Shot 2018-04-27 at 11.04.07 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/8a398216-17f4-b4f2-e4a2-3367580d1932.png">

続いて、画面右下にある**「4.Endpoint」**をクリックします。
<img width="450" alt="Screen Shot 2018-04-27 at 11.05.12 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/390f5ec8-14c2-28f3-16d3-4ce49f0b73ca.png">

この画面↓で**AWS Lambda ARN**を選択。
<img width="450" alt="Screen Shot 2018-04-27 at 11.08.19 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/9b873f2d-8666-2222-c021-f525666b9c3c.png">


直下に表示される内容の**Default Region**に先程調べてFunctionのARNを入力します。そして**[Save Endpoints]ボタン**を忘れずにクリックして保存します。
<img width="450" alt="Screen Shot 2018-04-27 at 11.20.42 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/2dbf2793-052d-6126-696a-082523ecee0d.png">

続いて、実装したLambdaのFunctionがこのSkillからのみアクセスを可能にする設定を行います。LambdaのFunctionで**Skill ID**というのが出て来ましたが、やっとここでその**Skill ID**を取得することが可能になりますので、その文字列をコピーします。

タブに用意しておいたLambdaのFunctionの画面のDesignerの右メニューの中の**Alexa Skikll Kit**をクリックして、画面下側に**Configuration Triggers**を表示しておきます。
<img width="450" alt="Screen Shot 2018-04-27 at 11.33.16 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/9faa74fe-747d-497a-5ded-da96d6ad07c7.png">


**Configuration Triggers**のSkill IDにSkillの実装の中のEndpointの画面に表示されていた**Skill ID**をペーストして右下の**[Add]ボタン**をクリックして設定を保存します。
<img width="865" alt="Screen Shot 2018-04-27 at 11.39.34 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/681bc50c-1612-1d84-135a-3bc852f49fde.png">

お疲れ様でした。以上で設定は完了です。

# テストで動作させる
タブメニューの**Test**をクリックします。（下図の(1)）
<img width="450" alt="Screen Shot 2018-04-28 at 12.04.13 AM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/4f2cb407-a0ab-bdc2-0a79-214665172ace.png">
そして、上図の(2)がOffになっている場合は、画像のようにOnにしてください。
## 動かしてみる
**「open color picker」**
で実装したアプリの動作開始です。後は、Alexaと対話しながら答えて遊んでみてください。

# 感想
今後はもう少し掘り下げて遊んでみて、その内容を記事にしようと思います。

#Reference
- [AWS Lambdaとは](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html)
- [Alexa Skills Node.js Tutorial](https://developer.amazon.com/alexa-skills-kit/alexa-skill-quick-start-tutorial-nodejs)