0から始めるAlexa入門

まだ日本語を全くサポートしてないAlexaですが、最近AWSからLexやPollyも登場してきており、おそらく今後どんどん使われていきそうなので、まとめてみました。

# 目次

- Amazon echo持ってないけど？
- 作るもの
- おおまかな流れ
- 最後に

# Amazon echo持ってないけど？

大丈夫です。Amazon USAのアカウントが必要ですが、

Amazon echoのシミュレータ：https://echosim.io/
Alexaの管理ツール: http://alexa.amazon.com/spa/index.html

で自分の作成したSkillを試すことが出来ます。また、Raspberry Piを持っていれば、そこにAlexaをインストールすることが出来ます(ただ僕はやり方を知らないので今回は省略します。)

# まずは公式リファレンス(めっちゃまとまってる)
https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/getting-started-guide

Alexaから呼び出すことのできるSkill(いわゆるアプリケーション)の作り方のリファレンスです。正直これ読めば知りたいことだいたいわかるのですが、全部読もうとすると結構なボリュームがあるので、とりあえず最低限動くSkillを作ることを目的として解説を進めていきます。

# 作るもの
### Alexa Skill (認識する文章の定義)

https://developer.amazon.com/home.html にて作成することが出来ます(要Amazon USAアカウント)。

後に詳細は説明しますが、ここで作成するものをざっくり言うと「ユーザーからの呼びかけに対してどの関数を呼び出すかの定義」です。

### Lambda function (実際に行う処理の定義)

AWS Lambdaで実際の処理を行います。リージョンは「バージニア北部」に変更をしておいてください。

後に詳細は説明しますが、ここで作成するものをざっくり言うと「Alexa Skillから送信されたリクエストに対して処理を行いレスポンスを返す関数」です。

# おおまかな流れ

Amazon echoを例にして説明します。

![Group.png](https://qiita-image-store.s3.amazonaws.com/0/41446/4ee513c4-d49f-08f8-e9d9-bd097c1a7830.png)

1. Amazon echoに話しかける
2. 内容をテキストに変換してAlexa Skillに送る
3. 文章の内容から呼び出す関数を見つけ出す
4. Lambdaに関数の実行を依頼するリクエストを送る
5. Lambdaから返ってきたレスポンスをAmazon echoに送る

# Alexa Skillの作成

### Amazon Developer Consoleへアクセスし、サインインする

https://developer.amazon.com/home.html へアクセスし、右上の「SIGN IN」からサインインします。そして、「ALEXA」タブをクリック→「ALEXA SKILL KIT」にある「Get Started」をクリックします。

### Alexa Skillを新規作成する

右上にある「Add a New Skill」をクリックします。左にある「Skill Information」「Interaction Model」「Configration」「Test」まで作業を進めればSkillを試せるようになるので、ここまで進めていきます。

### アプリの基本情報を設定する

「Skill Information」の設定を行います。

- Skill Type ここではCustom Interaction Modelを選択します。
- Language ここではEnglish(U.S.)を選択します。
- name スキルの表示名です。
- Invocation Name Alexaに呼びかける際のSkill名です。

### ユーザーからの呼びかけに対して呼び出す関数を定義する

「Interaction Model」の設定を行います。ここが一番大事なポイントです。

まず最初に全体像を把握するために1つ例を書くと

`AddIntent Add {a} to {b}`

これは、`Add {a} to {b}`と話しかけられた時に、`AddIntent`という関数に`x`と`y`という引数を渡して実行されることを意味します。例えば、`Add four to three`と話しかけた場合、`x`には`4`、`y`には`3`が代入されます。

ここでは

`AddIntent` はIntent、いわゆる関数名
`x`および`y`はSlot、いわゆる変数名
`AddIntent Add {a} to {b}`はSample Utterancesで定義され、呼びかけられる内容とIntent、Slotを結びつけます。

- Intent Schemaの定義

JSON形式で書いていきます。
例

```
{
  "intents":  [
    { "intent": "AMAZON.HelpIntent", "slots": [] },
    { "intent": "AMAZON.StopIntent", "slots": [] },
    { "intent": "AMAZON.RepeatIntent", "slots": [] },
    { "intent": "AMAZON.CancelIntent", "slots": [] },
    { "intent": "AMAZON.YesIntent", "slots": [] },
    { "intent": "AMAZON.NoIntent", "slots": [] },
    { "intent": "searchIntent", "slots":
                    [{ "name": "date", "type": "AMAZON.DATE" }] },
    { "intent": "eventIntent", "slots":
                    [{ "name": "number", "type": "AMAZON.NUMBER" }]}
  ]
}
```

`AMAZON`の名前空間があるものはbuilt-inで、いくつかありますが、自作のIntentを定義することもできます。

- Custom Slot Typesの定義

Slotはいわゆる変数のようなものです。`Custom Slot Types`には、変数の型と、その型の値を定義していきます。こうすることで、ある型の変数は、その型に定義されている値に対して重み付けをした認識(要するに優先順位を高く認識)してくれます。しかしながら、ここに定義した値以外のものも認識するため、Lambda関数側で引数を扱う場合は、エラーハンドリングをする必要があります。

ここでは、公式のチュートリアルにある星座の変数の定義を例にします。

例

```
name: sign
type: LIST_OF_SIGNS 

Aries
Taurus
Gemini
Cancer
Leo
Pisces
Virgo
Libra
Scorpio
Sagittarius
Capricorn
Aquarius
```

- Sample Utterancesの定義

ユーザーからの呼びかけに対してどの関数を呼び出すかを定義します。

フォーマット #{ intent_name }  #{ phrase }

例

```
AMAZON.HelpIntent tell me standard calendar
searchIntent get me stuff happening {date}
searchIntent get me events for {date}
searchIntent whats on {date}
searchIntent whats happening {date}
searchIntent tell me whats happening {date}
searchIntent what is happening {date}
searchIntent what is happening on {date}
searchIntent what events are happening {date}
searchIntent what events are happening on {date}

eventIntent tell me about event {number}
eventIntent whats event {number}
eventIntent number {number}
```

設定をしたら「Next」ボタンをクリックします。

### lambdaのARNを設定する

「Configration」の設定を行います。
ここではリクエストのエンドポイントを設定します。今回はAWS Lambdaを選択し、「North America」にチェックをします。テキストボックスが現れるので、呼び出したいLambdaのARNを設定します。ここではまだ作成していないので、Lambda functionを作成してから設定します。

# Lambda functionの作成

Lambda functionでは、Alexa Skillから送られてきたリクエストを元に適切な関数を実行し、結果をレスポンスとして返します。
https://github.com/anjishnu/ask-alexa-pykit のチュートリアルに沿って実装していくのが楽です。

この手順に沿ってやっていけばAlexa Skillから呼び出せるようになります。
(Ref: https://github.com/anjishnu/ask-alexa-pykit#step-1-download-code)

1. Lambda function用のディレクトリを作成
2. ask-alexa-pykitをディレクトリ内にインストール
3. lambda_function.pyファイルを作成し、その中にリクエストに対する処理を書く。
4. ディレクトリ内のものを全てzipにまとめる
5. Lambdaにzipをアップロード
6. Handler名をlambda_function.lambda_handlerに設定({ #呼び出したいファイル名 }.#{ 呼び出したい関数名 })
7. roleをlambda_basic_exectionに設定

### Intentに対する処理の定義

lambda_function.pyでは、各Intentに対応する関数を定義していきます。

関数の例

```
@alexa.intent('AddIntent')
def add_intent_intent_handler(request):
    x = request.slots["x"]
    y = request.slots["y"]
    answer = x + y
    return alexa.create_response(str(answer))
```

送信されたリクエストに対して、レスポンスを返します。最低限`alexa.create_response()`に文字列を渡して返せば動くので、まずはこれを試してみるのが簡単だと思います。

加えて、高度なことをしたい場合は`create_response()`に渡すオプションをいくつかいじるといいと思います。

- `end_session` Falseを渡すことで、会話を継続することができます。また、request.sessionに値を渡して保持させることができます。
- `card_obj` Alexaの管理ツール(http://alexa.amazon.com/spa/index.html) の「Home」に表示するカードを渡すことが出来ます。文字といくつかの形式の画像を表示をすることが出来ます。
![Screenshot from 2016-12-19 02-13-24.png](https://qiita-image-store.s3.amazonaws.com/0/41446/43a04701-66c8-e13b-cd50-8e02061a2bb8.png)
- `reprompt_message` Alexaからの呼びかけに対して、ユーザーからの返答が一定時間以上なかった場合のメッセージを定義できます。要するに催促する際のメッセージです。

# 最後に

簡単な割に意外と遊べるので、ぜひ試してみてください。