Alexaスキル作成からスキル申請までの方法

# 1. はじめに
先日（2018/02/24）、[Smart Hacks](https://smarthacks.jp/db/) 様主催の [スマートスピーカー勉強会](https://www.facebook.com/groups/914975592004491/permalink/917776731724377/?pnref=story.unseen-section) に参加させて頂き、Alexaスキル開発エンジニアとして私もスマートスピーカ普及に尽力せねばと感銘を受けました。

そこで今回は、まだ多くの方々がご存知ではない、Amazon Echo Alexaスキルの作成から、スキル申請までの流れを、惜しみなく大公開したいと思います。

## 1-1. この記事を読んでできること
- **Amazon Developer Portal を用いた、Alexaスキルが作成できるようになる。**
- **AWS Lambda を用いた、音声ロジックプログラムの作成ができるようになる。**
- **Alexaテストシミュレータが使えるようになる。**
- **Echoデバイス実機がなくともAlexaスキルが開発できるようになる。**
- **Alexaスキル申請ができるようになる。**

# 2. 事前準備
ここでは、事前準備としてAWSアカウントとAmazon Developer Portalアカウントの用意をおこないます。

## 2-1. AWSアカウントの作成

もしかしたらこの事前準備が一番めんどくさいかもしれません。
一般的なAlexaスキルの開発環境としては、[Amazon Web Services（アマゾン ウェブ サービス、AWS）](https://aws.amazon.com/)の開発アカウントを用意する必要があります。

今回の記事内容には、AWSアカウント作成の手順は割愛させて頂きますが、幸運にもアマゾンジャパン合同会社さまが、AWSアカウントの作成方法をとても丁寧に説明してくださっている参考サイトがありますので、ご紹介いたします。

[参考：AWSアカウント作成の流れ](https://aws.amazon.com/jp/register-flow/)

ただし、上記の参考サイトだけでは、一番の難関 IAMロール権限設定 がクリアできないかと思います。どなたか、参考サイトをご存知の方がいらっしゃいましたら、コメント投稿をお願いいたします。

書籍でよいのでもっと詳しく知りたいぜーって方には、[AWS Lambda実践ガイド 大澤 文孝  (著)](https://www.amazon.co.jp/AWS-Lambda%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%E5%A4%A7%E6%BE%A4-%E6%96%87%E5%AD%9D-ebook/dp/B0764C5MT5/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=1519532854&sr=1-1)を推薦させて頂きます。

AWSアカウント作成で一番のネックは、IAMロール（権限設定）が分かりづらい点ですが、大澤先生の書籍では、とても丁寧に説明されており、おすすめです。
（この書籍でのLambda開発言語はPythonとなります、私は音声スキルの開発言語をNode.jsを用いて開発するのですが、この部分だけ残念でした。。。Node.js版の書籍が出たら必ず買いますので、今後に期待したいと思います。）

AWSアカウントの作成が出来た方は、Lambda（Node.jsプログラム作成部）、CloudWatch（ログ出力）へのIAMロール（権限設定）を済ませてください。

合わせて、DynamoDB（NoSQL）、S3（ファイルサーバ）へのIAMロール（権限設定）を済ませておくと、おおむねAlexaスキル開発に必要なAWS開発環境の準備は整ったことになります。

## 2-2. Amazon Developer Portalアカウントの用意
Amazon Developer Portalでは、Alexaスキルの設定（スキル名、アイコン、概要説明、Intent設定、Slot設定、サンプル発話設定）などに利用します。
ここにも大変な罠が仕掛けられております。

日本語環境向けのAlexaスキルを開発される方は、[Amazon（JP）Amazon.co.jp](https://www.amazon.co.jp/)のアカウントを必ず先に作成してください。

ここで誤ってAmazon（US）のアカウントを利用し、Amazon Developer Portalアカウントを作成すると、アメリカ環境向けのAlexaスキルを開発する環境が構築されることとなり、いろいろと面倒です。

ぜひとも、[Amazon（JP）Amazon.co.jp](https://www.amazon.co.jp/)のアカウントを作成してから、[Amazon Developer Portal](https://developer.amazon.com/ja/)のアカウントを作成してください。
　　
またもや、幸運にもアマゾンジャパン合同会社さまが、Amazon開発者アカウントの作成方法と、おちいりやすい罠について、とても丁寧に説明してくださっている参考サイトがありますので、ご紹介いたします。（密林の女神さまやー！）

[参考：Alexa 開発者アカウント作成時のハマりどころ](https://developer.amazon.com/ja/blogs/alexa/post/9f852a38-3a44-48bd-b78f-22050269d7c7/hamaridokoro)

[参考：失敗しないAlexa開発者アカウントの作り方](https://dev.classmethod.jp/voice-assistant/how-to-safety-create-alexa-developers-account/)

[参考：Amazon.comアカウントが優先してAlexaアプリに入れない問題の解決法](https://dev.classmethod.jp/voice-assistant/solution-of-a-problem-amazon-com-account-conflict/)

## 2-3.（補足）Alexaサインインの存在
通常、Amazon Echoのスキルを有効にする際は、スマホアプリのAlexaアプリを利用します。
ただ、Alexaスキルを開発されるみなさまが、開発の都度、スマホアプリを起動するのは面倒かと思います。

Alexaスキルの 有効／無効 を切り替える際は、PCブラウザから直接[Amazon.co.jp alexaサインイン](https://alexa.amazon.co.jp/)にログインすると、少しだけ楽できておすすめです。
また、ユーザ発話をAlexaがどのような言葉として認識したのかも、Alexaアプリ→設定→履歴から、ご確認いただけます。
おそらく、公式なアクセス方法ではないと思われるので、ご利用される方はブックマークしておくことをおすすめいたします。

一つ前のAmazon Developer Portalアカウント作成の罠に引っかかった方は、[Amazon.com alexa sign in](https://alexa.amazon.com/)のUSアカウントに紐づいていると思います。

JPアカウントとUSアカウントの区別をしっかり認識することで、以後、スムーズなスキル開発をおこなうことができます。

# 3. 音声スキル設計
ここでは、どのような音声スキルを作成するのか？音声スキルの設計をおこないます。

## 3-1. 音声スキルのアイデアを考える
みなさんの中には、
「Amazon Developer PortalアカウントとAWSアカウントが準備できたんだから、作り方ハヨ！！」と、お気持ちが急がれている方が大変多くいらっしゃるかと思います。
ただ、私はプロのエンジニアなので、いきなりコーディングに着手することはいたしません。

- みなさんは、これからどんな音声スキルを作りたいですが？
- アイコン画像は、どのようにしたいですか？
- それは、どのような起動方法（スキル名：呼び出し名と言います。）を必要としますか？
- 音声スキルが起動したら、Alexaとユーザは、どのようなトークを続けますか？
- ユーザからのリクエスト（Intent：インテント、ユーザの意図。）を叶えますか？
- Alexaは、ユーザ発話からどのようなキーワード（Slot：スロットと言います。Slotには、Date、Time、Number、カスタムスロットなどが利用できます。）を必要としますか？

などなど、要求事項を整理し、要件を定義する必要があります。

今回は、そこまで難しく準備する必要はありませんが、しっかりとスキルを設計することが、スキル申請まで終えるには必要です。

**最低でも、次の3つは必ずスキルを作る前に考えておきましょう。**

- <font color="Red">**スキルのアイデア（実現したいこと）**</font>
- <font color="Red">**スキル起動フレーズ（スキル呼び出し名）**</font>
- <font color="Red">**トークシナリオ（スキル起動から終了まで）**</font>


## 3-2. 今回開発するAlexaスキル
今回開発するAlexaスキルは、既に私が、開発＆スキル申請＆スキル公開まですませた [とっさの英語](https://smarthacks.jp/db/5788/) を参考に、Alexaスキル作成の手順を説明していきたいと思います。

<font color="Red">**今回開発するAlexaスキルのトークシナリオ（サンプル）は、以下のとおりです。**</font>

```plaintext:トークシナリオ（サンプル）
ユーザー：「アレクサ、とっさの英語を開いて。」
アレクサ：「とっさの英語をご利用いただき、ありがとうございます。とっさの英語は、
　　　　　　英語学習用のスキルです。私の発音を真似て、リピートアフターミーして
　　　　　　ください。船に対するの呼び掛け、おーい。（1秒の間）アホーイ。」

ユーザー：「アホーイ。」
アレクサ：「はくしょん、くしゃみ。（1秒の間）アチュー。」

ユーザー：「アチュー。」
アレクサ：「わかった、なるほど。（1秒の間）アハ。」

ユーザー：「止めて。」
アレクサ：「スキルの終了を受け付けました。 」
```

基本的には、ユーザーの発話（Request）に対し、Alexaが応答（Response）するかたちでトークが進みます。

このRequestとResponseの仕組みが理解できれば、自由に音声会話をデザインできるようになります。このような考え方を **VUI（ボイス ユーザ インターフェース）設計**と呼びます。なんだかかっこいいいですよね？


# 4. Alexaスキルの作成手順
ここでは、Amazon Developer Portal を用いて、音声スキルの骨格を作成します。実際の音声ロジック部分（Lambda Function プログラム）の部分は、後ほどAWSを使って作成します。Amazon Developer Portalでのエンドポイント設定およびテスト実施については、AWS Lambda Functionを作成してからでないと機能しないので、その点はおさえておきましょう。

## 4-1. 新しいスキルの作成
- Amazon Developer Portal を開き、「Developer Console」 をクリックし、ログインする。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/240522/3214c8e5-006f-6dfe-5260-30dc84ee411d.png)
　 
- 「Alexa」 をクリックし、Alexa Skills Kit 側の 「始める」 をクリックする。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/240522/17050d09-d123-c4c3-90f4-11d05d5e7dee.png)

　

- 「新しいスキルを開始する」 をクリックする。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/240522/8ac04210-abd0-ebd1-7e3b-57b6baf1701b.png)
　

## 4-2. スキル情報の登録
- 「スキル情報」を選択し、スキルの種類「Custom」、言語「Japanese」、スキル名、呼び出し名を設定し、画面下部の「保存」をクリックする。ここでの注意点は、スキル名および呼び出し名に、簡単な人名や、商標権を侵害する名前は用いることができません、スキル申請時にNG（リジェクト）をくらいます。2つ以上の言葉の組み合わせを、おすすめいたします。あと、保存後に、「アプリケーションID」が発行されますので、メモ帳などにメモしておきましょう。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/240522/ba0274fb-19e0-b47a-a903-a8fd8d99b958.png)
　

## 4-3. 対話モデルの登録（重要なところです！！）
- 「対話モデル」を選択し、インテントスキーマを登録する。
![5.png](https://qiita-image-store.s3.amazonaws.com/0/240522/24c19cf7-10ce-fbae-3e9c-03b415afc517.png)
Intent（インテント：意図）ですが、AMAZON.CancelIntent、AMAZON.StopIntentおよびAMAZON.HelpIntentは、必須インテントとなりますので、必ず登録しましょう。SlotPhraseIntentには、Custom Slot（カスタムスロット）として、LIST_OF_PHRASE の利用を定義しています。LIST_OF_PHRASE については、この次で登場します。

```json:IntentSchema.json
{
  "intents": [
    {
      "slots": [
        {
          "name": "PhraseWords",
          "type": "LIST_OF_PHRASE"
        }
      ],
      "intent": "SlotPhraseIntent"
    },
    {
      "intent": "AMAZON.CancelIntent"
    },
    {
      "intent": "AMAZON.StopIntent"
    },
    {
      "intent": "AMAZON.HelpIntent"
    }
  ]
}
```
  
  
- カスタムスロットで「タイプを入力」に、先ほど登録したインテントスキーマでのSlot名である「LIST_OF_PHRASE」を入力し、英語の発話練習をしたい言葉「アブラカタブラ、アチュー、アハ、エヘン、アホーイ、、、」などを登録します。
　
ここでの注意点は、2018年2月現在、アルファベットを用いた登録ができない仕様となっています。少し残念です、今後の改善に期待しましょう。

![6.png](https://qiita-image-store.s3.amazonaws.com/0/240522/691be696-105f-af54-5604-4a11d0c0ecfe.png)



```plaintext:LIST_OF_PHRASE.txt
アブラカタブラ
アチュー
アハ
エヘン
アホーイ
```  
  
  
- サンプル発話を登録し、どのようなユーザ発話の際に、どのインテントを呼び出すか、定義します。中括弧 {PhraseWords} になっているところは、インテントスキーマで設定したスロット名を設定します。
![7.png](https://qiita-image-store.s3.amazonaws.com/0/240522/ef5965b0-9678-d4d1-f085-d11e989989c4.png)

```plaintext:Utterances.txt
AMAZON.HelpIntent 使い方を教えて
AMAZON.HelpIntent 使い方教えて
AMAZON.HelpIntent 使い方
SlotPhraseIntent {PhraseWords}
SlotPhraseIntent {PhraseWords} かな
SlotPhraseIntent {PhraseWords} あってるかな
SlotPhraseIntent {PhraseWords} で合ってるかな
SlotPhraseIntent {PhraseWords} いいかな
SlotPhraseIntent {PhraseWords} でいいかな
```

ここまでが、Amazon Developer Portal で設定する、Alexaスキルの重要な設定部分です。
みなさんの中には、
「あれ？ AMAZON.CancelIntent と AMAZON.StopIntent のサンプル発話、設定してないじゃん。これじゃあ、キャンセルインテントと、ストップインテントが呼び出せないじゃんけー！！」
とぷち切れているかと思います。
安心してください、ビルトインインテントですから。。。

Alexaスキルの中で、Amazon.XXXX となっている箇所が出てきますが、これは、Amazon様が予めちゃんと動くようにしてくれている標準機能（Built-in）となります。ビルトインインテント以外にも、ビルトインスロットも用意されており、日付、時間、数字などは、スロット登録の必要なく、音声学習済みのスロットとして用いることができます。

詳しくは、以下の参考サイトをご参照ください。

参考：[一般的標準インテント](https://developer.amazon.com/ja/docs/custom-skills/standard-built-in-intents.html)
参考：[スロットタイプリファレンス](https://developer.amazon.com/ja/docs/custom-skills/slot-type-reference.html)

## 4-4. 公開情報の登録
ここでは、スキル公開時に表示されるカテゴリーや説明文などの設定をおこないます。

- 「公開情報」を選択し、「カテゴリー」を登録する。選択したカテゴリーにより、サブカテゴリーを選択する場合もあります。

```plaintext:カテゴリー
Education & Reference
```

- 「テストの手順」を登録する。ここでは、アマゾンテスターさん向けのお願い事項があればその内容を明記します。

```plaintext:テストの手順
英語学習用のスキルです。
ご審査おねがいもうしあげます。

2018年01月25スキル申請分
・新規作成
・その他バグ修正
```

- 「国と地域」を登録する。日本環境向けのAlexaスキルの場合は、「国と地域を選択する」を選択し、「Japan」のみにチェックを入れるようにしましょう。他国にチェックを入れると、その国で動くように開発しないと、スキル申請でNG（リジェクト）されるはずです。

```plaintext:国と地域を選択する
Japan
```

- 「スキルの簡単な説明」を登録する。ここでは160文字以内の簡単なAlexaスキルの説明文を登録します。

```plaintext:スキルの簡単な説明
とっさの英語は、英語学習用のスキルです。
発音を真似ることで、正しい発音を学習いただけます。
```

- 「スキルの詳細な説明」を登録する。ここではより詳しくAlexaスキルの説明文を登録します。

```plaintext:スキルの詳細な説明
とっさの英語は、英語学習用のスキルです。
発音を真似ることで、正しい発音を学習いただけます。

ご利用にあたり、アカウントリンク等による個人情報のご登録は必要ございません。
```

- 「サンプルフレーズ」を登録する。ここで登録したサンプルフレーズが機能しない場合、これもスキル申請でNG（リジェクト）されますので、かならずテストし動作することを確認しましょう。

```javascript:サンプルフレーズ
1. アレクサ、とっさの英語を開いて
```

- 「キーワード」を登録する。ここで登録した言葉が、Alexaアプリ内でのスキル検索キーワードとして利用されます。

```plaintext:キーワード
英語,英会話,えいご,えいかいわ,入門,日本語,日本,にほんご,スピーキング,リーディング,ヒアリング,イングリッシュ,English,ENGLISH,english,バイリンガール英会話,バイリン,ガール,バイリンガール,バイリンガル,とっさ,とっさの,とっさの英語
```

- 小アイコンを登録する。108x108ピクセルの正方形アイコンを用意しましょう。
- 大アイコンを登録する。512x512ピクセルの正方形アイコンを用意しましょう。
10. 「登録」が済んだら、必ず画面下部の「保存」をクリックしましょう。

## 4-5. プライバシーとコンプライアンスの登録
-  「このスキルを使って何かを購入をしたり、実際にお金を支払うことができますか？」に対し、「いいえ」を選択する。
-  「このスキルはユーザーの個人情報を収集しますか？」に対し、「いいえ」を選択する。
-  「このスキルは13歳未満の子供をターゲットにしていますか？」に対し、「いいえ」を選択する。
-  「輸出コンプライアンス」に対し、チェックを入れる。
-  「このスキルは広告を含みますか？」に対し、「いいえ」を選択する。
-  「プライバシーポリシー URL」が「オプション」の場合は、未登録でOK。
-  「利用規約 URL」が「オプション」の場合は、未登録でOK。

# 5. AWS Lambdaの作成手順
ここでは、音声ロジック（プログラム部）のメインロジックを作成します。なれないうちは難しいことも多くありますが、なれてしまえば音声会話を全てプログラム制御できますので、楽しみながらコーディング＆デバッグしてください。作成のコツとしては、ちょっとロジックを追加して、ちょっと動かす、ちょっと追加、ちょっと動かすの繰り返しが、おすすめです。

## 5-1. Lambdaプログラムの新規作成
- AWS にログインする。
- 画面上部のリージョンが「東京」であることを確認する。リージョンは「バージニア」、「オハイヨ」でも、日本語のAlexaスキルが動作するはずですが、安定版としては、リージョン「東京」が、おすすめです。
- 「サービス」から「Lambda」を選択する。
- 「関数の作成」をクリックする。
![8.png](https://qiita-image-store.s3.amazonaws.com/0/240522/3cce5e4e-268e-d479-adbd-4a0d3e43b474.png)

　

- 「設計図」を選択し、検索キーワードに「alexa」を入力しエンターキーを押下する。
![9.png](https://qiita-image-store.s3.amazonaws.com/0/240522/1ba58be8-3cb7-016c-8bab-0c27ffa58aff.png)

　

- 設計図の検索結果から、「alexa-skill-kit-sdk-factskill」を選択する。このサンプルでは、alexa-sdkパッケージが利用されており、プログラムのコーディング量を抑えるこおとができます。他にも、Pythonなどのサンプルもあるはずですので、ぜひ見てみてください。
![10.png](https://qiita-image-store.s3.amazonaws.com/0/240522/0a21bb3c-bfe8-78b1-3022-86696f331602.png)

　

- 任意の「関数名」を入力し、「ロール」の設定をおこない、画面下部の「関数の作成」をkリックする。（ご自身のAWS環境に合わせて、ロール設定を選択する必要があります。基本的にはLambda Functionの操作権限＆実行権限が満たせればよいかと思います。）
![11.png](https://qiita-image-store.s3.amazonaws.com/0/240522/5f04be8d-dfc8-a050-fa79-82037f10066d.png)

　

- 画面上部の「ARN」をコピーして、メモしておく。このARNが、Alexaスキルに設定する「エンドポイント」になります。
![12.png](https://qiita-image-store.s3.amazonaws.com/0/240522/f7a42dae-30b4-b665-e84a-c2f5971ddb34.png)

　

- トリガーから「Alexa Skills Kit」をダブルクリックで選択し、Lambda Functionに対するトリガー（起動のきっかけ）を登録する。
![13.png](https://qiita-image-store.s3.amazonaws.com/0/240522/7402c2cd-efde-089b-fce3-58e60b556b9f.png)

　

- トリガー「Alexa Skills Kit」が選択された状態のまま、画面中央まで下スクロールし、スキルID検証で「有効」を選択し、スキルIDに「Amazon Developer Portalで発行されたアプリケーションID」を入力し、「追加」をクリックする。この登録は必須ではありませんが、登録することで、悪意のある者からのLambda Functionの実行でないことを判断する材料となります。
![14.png](https://qiita-image-store.s3.amazonaws.com/0/240522/ff0c6342-063d-6cc5-b533-862b18cacfa9.png)

　

- 画面上部まで上スクロールで戻り、Lambda Functionアイコンを選択後、「保存」をクリックする。
![15.png](https://qiita-image-store.s3.amazonaws.com/0/240522/04d79775-b3a5-3260-c5d9-faa2705bca2e.png)

　

- その後、再度、画面中央まで下スクロールで戻ると、サンプルプログラムの内容 index.js を確認することができます。サンプルプログラムが表示されていない場合は、「コードエントリタイプ」の選択内容が、「コードをインラインで編集」であることを確認してください。
![16.png](https://qiita-image-store.s3.amazonaws.com/0/240522/8bbe5b4a-2858-18f7-b54f-37fbe66982a8.png)

　

実際には、これからプログラムソースである「index.js」を編集する必要があるのですが、先に、Amazon Developer Portalの残りの設定を済ませて、テスト実行ができる環境を整えたいと思います。

# 6. Amazon Developer Portalの残りの設定手順
ここでは、Amazon Developer Portalでの残作業、エンドポイント設定およびテスト実施について説明します。

## 6-1. 設定の登録
- Amazon Developer Portalから、作成中のAlexaスキルを選択する。
- 「設定」を選択後、「サービスエンドポイントのタイプ」を「AWS Lambda の ARN」にチェックし、「デフォルト」にLambda Function作成時にメモした「ARN」をペーストする。
![17.png](https://qiita-image-store.s3.amazonaws.com/0/240522/91e9e365-b489-68cb-ea9e-508ad8c5c760.png)
- 「エンドポイントの地理的リージョンを設定しますか？」に対し、「いいえ」を選択する。
- 「保存」をクリックする。

## 6-2.テストシミュレータの実行
- 「テスト」選択後、テスト機能が「有効」となっていることを確認し、「テストシミュレータに進むベータ」をクリックする。おそらく近い将来にはベータ版ではなく、正式版に格上げされ、画面の見た目が変わる可能性はあるかと思います。Amazonの提供するサービスは、頻繁にバージョンアップがなされるので、見た目が変わったくらいで、いちいち驚かないよう心がけよう。
![18.png](https://qiita-image-store.s3.amazonaws.com/0/240522/a43be78b-3fb0-65ca-f828-4efcf82b04c0.png)

　

- テストシミュレータを開くと、ブラウザから「マイクの利用許可」を求めるポップアップがでる場合がある、この場合は迷わず「許可する」を選択すること。ブラウザによっては、マイクがなかなか有効にならない場合もあるが、その場合は、他のブラウザで試そう。また、マイクが付いていないPCの場合は、音声発話の代わりにキーボード入力もおこなえるため、最後まであきらめないこと。
![19.png](https://qiita-image-store.s3.amazonaws.com/0/240522/9c732b58-1725-0437-eeaa-6889f19dddfb.png)

　

- まずはAlexaスキルを起動する必要があるため、マイクアイコンをクリックしたまま「アレクサ とっさの英語（アプリ呼び出し名） を 開いて。」とユーザ発話してみよう。マイクが使えない方は、キーボード入力で「アレクサ とっさの英語 を 開いて」と入力し、エンターキーを強めに叩こう。みなさんのLambda Functionはまだ完成していないため、エラーが発生するかと思いますが、Lambda Function の index.js を修正すれば、Alexaスキルの音声テストができるはずです。また、ここでは「JSON Input」で「Request」の内容を、「JSON  Output」で「Response」の内容を確認できまます。Alexa応答が設計通りでなかった場合は、Lambda Functionの内容を見直してみてください。きっとそこにはバグがいるはずです。
![20.png](https://qiita-image-store.s3.amazonaws.com/0/240522/751a5726-c5ab-4289-dfac-0cf540ea88d7.png)

　
# 7. Lambda Function index.js の中身公開
ここでは、Alexaスキル [とっさの英語](https://smarthacks.jp/db/5788/)  の音声プログラム index.js を公開いたします。index.jsをAWS Lambdaへ反映（コピー＆ペースト）した後は、必ずAWS Lambda上で「保存」をクリックして、保存反映してください。
ぜに、みなさんの環境でテストシミュレータを実行してみましょう。
（みなさんに分かりやすくするため一部改変してます。）

## 7-1.音声ロジック index.js

```javascript:index.js
// 厳密モード有効
'use strict';

// alexa-sdkを有効
const Alexa = require('alexa-sdk');

const util = require('util');

// アプリケーションID　↓↓↓ Amazon Developer Portal にログインし、当該AlexaスキルのアプリケーションIDに変更してください。
const APP_ID = 'amzn1.ask.skill.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';

// 文字列国際化（i18n）リソースオブジェクト
const languageStrings = {
    // 日本
    'ja-JP': {
        translation: {
            PLRASE_LISTS: [
                // abracadabra、アブラカタブラ
                '<break time="1s"/>アブラカタブラ。<break time="1s"/>アブラカタブラ',

                // achoo、アチュー
                '<break time="1s"/>はくしょん、くしゃみ。<break time="1s"/>アチュー',

                // aha、アハ
                '<break time="1s"/>わかった、なるほど。<break time="1s"/>アハ',

                // ahem、エヘン
                '<break time="1s"/>えへん、うふん。<break time="1s"/>エヘン',

                // ahoy、アホーイ
                '<break time="1s"/>船に対するの呼び掛け、おーい。<break time="1s"/>アホーイ',
                
            ],

            SKILL_NAME: 'とっさの英語',
            HELP_NAME: '【ヘルプ】',
            
            WELCOME_MESSAGE: 'とっさの英語をご利用いただき、ありがとうございます。とっさの英語は、英語学習用のスキルです。普段の生活で、とっさのひとことが、ネイティブ並みの英語だと素敵ですよね？この体験を通じて、さまざまな方々と出会い、たくさんの国際交流がおこなわれ、音声スキルの可能性を実感して頂けると幸いです。私の発音を真似て、リピートアフターミーしてください。',
            WELCOME_REPROMPT: '正しい発音を認識することができませんでした。私の発音を真似て、リピートアフターミーしてください。',

            REPEAT_MESSAGE: '',
            REPEAT_REPROMPT: '正しい発音を認識することができませんでした。私の発音を真似て、リピートアフターミーしてください。',
            
            HELP_MESSAGE_1: 'とっさの英語をご利用いただき、ありがとうございます。とっさの英語は、英語学習用のスキルです。普段の生活で、とっさのひとことが、ネイティブ並みの英語だと素敵ですよね？この体験を通じて、さまざまな方々と出会い、たくさんの国際交流がおこなわれ、音声スキルの可能性を実感して頂けると幸いです。',
            HELP_MESSAGE_2: '<break time="1s"/>私の発音を真似て、リピートアフターミーしてください。',
            HELP_REPROMPT: '正しい発音を認識することができませんでした。私の発音を真似て、リピートアフターミーしてください。',
            
            STOP_MESSAGE: 'スキルの終了を受け付けました。',
            
        },
    },
};


/**
 * ロジック部
 */
const handlers = {
    // LaunchRequest　ユーザ発話「アレクサ、スキル呼び出し名 を 開いて。」
    'LaunchRequest': function () {
        // AskWelcome関数にジャンプ！！
        this.emit('AskWelcome');
    },

    // AskWelcome
    'AskWelcome': function () {
        // ファーストフレーズの決定
        const plraseListArr = this.t('PLRASE_LISTS');
        const plraseIndex = Math.floor(Math.random() * plraseListArr.length);
        const randomPlrase = plraseListArr[plraseIndex];

        // スピーチアウトプット
        const speechOutput = this.t('WELCOME_MESSAGE') + randomPlrase;
        const reprompt = this.t('WELCOME_REPROMPT') + randomPlrase;

        this.emit(':ask', speechOutput, reprompt);
    },

    
    // SlotPhraseIntent　ユーザ発話で、英語フレーズを発話した際に呼び出されるインテント。
    'SlotPhraseIntent': function () {
        // NextPhrase関数にジャンプ！！
        this.emit('NextPhrase');
    },

    // NextPhrase
    'NextPhrase': function () {
        // スロットの取得
        // let phraseWordsValue = this.event.request.intent.slots.PhraseWords.value;
        const phraseWordsSlot = this.event.request.intent.slots.PhraseWords;

        if (phraseWordsSlot) {
            const phraseWordsValue = phraseWordsSlot.value;
        }
    
        // ネクストフレーズの決定
        const plraseListArr = this.t('PLRASE_LISTS');
        const plraseIndex = Math.floor(Math.random() * plraseListArr.length);
        const randomPlrase = plraseListArr[plraseIndex];

        // スピーチアウトプット
        const speechOutput = this.t('REPEAT_MESSAGE') + randomPlrase;
        const reprompt = this.t('REPEAT_REPROMPT') + randomPlrase;

        this.emit(':ask', speechOutput, reprompt);
    },

    // SessionEndedRequest　ユーザがだんまりを決め込んだ時などに呼ばれる終了リクエストです。
    'SessionEndedRequest': function () {
        // スピーチアウトプット
        this.emit(':tell', this.t('STOP_MESSAGE'));
    },

    // AMAZON.CancelIntent　ユーザ発話「キャンセル。」
    'AMAZON.CancelIntent': function () {
        this.emit('SessionEndedRequest');

        // // スピーチアウトプット
        // this.emit(':tell', this.t('STOP_MESSAGE'));
    },

    // AMAZON.StopIntent　ユーザ発話「止めて。」
    'AMAZON.StopIntent': function () {
        this.emit('SessionEndedRequest');
        
        // // スピーチアウトプット
        // this.emit(':tell', this.t('STOP_MESSAGE'));
    },
    
    // AMAZON.HelpIntent　ユーザ発話「ヘルプ。」
    'AMAZON.HelpIntent': function () {
        // リピートフレーズの決定
        const plraseListArr = this.t('PLRASE_LISTS');
        const plraseIndex = Math.floor(Math.random() * plraseListArr.length);
        const randomPlrase = plraseListArr[plraseIndex];

        // スピーチアウトプット
        const speechOutput = this.t('HELP_MESSAGE_1') + this.t('HELP_MESSAGE_2') + randomPlrase;
        const reprompt = this.t('HELP_REPROMPT') + randomPlrase;
        const cardContent = this.t('HELP_MESSAGE_1');

        this.emit(':askWithCard', speechOutput, reprompt, this.t('HELP_NAME'), cardContent);
    },
};


/**
 * main処理
 */
exports.handler = function (event, context, callback) {
    const alexa = Alexa.handler(event, context, callback);

    // アプリケーションID
    alexa.APP_ID = APP_ID;

    // 文字列国際化（i18n）機能を有効にするには、リソースオブジェクトを設定する必要あり
    alexa.resources = languageStrings;

    alexa.registerHandlers(handlers);
    
    alexa.execute();
};
```

## 7-2.ざっくりソース解説
**Amazon Developer Portal にログインし、作成したAlexaスキルのアプリケーションIDに変更してください。**
const APP_ID = '<font color="Red">amzn1.ask.skill.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</font>';

**プログラムの開始位置**
exports.handler = function (event, context, callback) {

**引数でロジック部を指定（複数指定することも可能）**
alexa.registerHandlers(handlers);

**ユーザ発話：「アレクサ、アプリ呼び出し名 を開いて。」で実行されるところ**
'LaunchRequest': function () {

**ユーザ発話で英語フレーズを発話した際に呼び出されるインテント**
'SlotPhraseIntent': function () {

**ユーザ発話のスロット値を取得しているところ**
const phraseWordsSlot = this.event.request.intent.slots.PhraseWords;
if (phraseWordsSlot) {
    const phraseWordsValue = phraseWordsSlot.value;
}

**アレクサ応答メッセージと、聞き直しメッセージを設定し、アレクサ応答（ask：質問）しているところ**
const speechOutput = this.t('REPEAT_MESSAGE') + randomPlrase;
const reprompt = this.t('REPEAT_REPROMPT') + randomPlrase;
this.emit(':ask', speechOutput, reprompt);

**終了メッセージを設定し、アレクサ応答（tell：告げる）しているところ**
this.emit(':tell', this.t('STOP_MESSAGE'));

**音声ロジックのポイント**
<font color="Red">アレクサ応答は2通り。ひとつは（ask：質問）、もうひとつは（tell：告げる）。</font>
<font color="Red">この2通りのアレクサ応答（emit：音声を発する）の使い分けが重要です。


# 8. スキル申請
テストシミュレータで、ばっちし動作が確認できて、問題がなければ、あとはスキル申請あるのみです。Amazon Developer Portalの当該Alexaスキルを選択し、画面下部から「申請する」をクリックしましょう。5営業日以内に審査結果がアマゾンジャパン様からメールで届くかと思います。審査がNGの場合は、修正点もメールに明記してあるので、めげずにAlexaスキルの再申請をおこないましょう。

# 9. さいごに
みなさん、Amazon Alexa スキル開発はいかがでしたか？
まだ、みなさんにお伝えできていない、Lambda Functionのソース作成のコツ、スキルのテスター招待方法、スキルの有効化、スキル審査時に気を付けること、[ビルトインスロット（AMAZON.NUMBER／AMAZON.DATE／AMAZON.TIME）](https://developer.amazon.com/ja/docs/custom-skills/slot-type-reference.html)、[はい／いいえ制御（AMAZON.YesIntent／AMAZON.NoIntent）](https://developer.amazon.com/ja/docs/custom-skills/standard-built-in-intents.html)、セッション情報保持（sessionAttributes）、[状態遷移制御(state)](https://developer.amazon.com/ja/blogs/alexa/post/cddf2434-42ee-422f-886d-5be9c36dba14/jp-training-chapter3)などなどは、おいおい記事をアップしていきますので、お楽しみに。

2018/02/25 TAKAHIRO NISHIZONO