2.1はじめに
本章ではAmazonが提供するAmazon Alexaスキル(プログラム)の開発環境を利用して簡単なAlexaスキルを作成し実行する方法を説明します。なおWebAPIを利用して他のアプリと連携する方法については別の章で説明します。
本章の構成は次の通りです。
2.1 はじめに
2.2 関連アカウントの取得
2.3 Hello World例題による基本操作説明
2.4 フロントエンドとバックエンド
2.5 NLUモデルの作成とコードの記述
2.6 複数のスロットを持つインテントと演算・判断処理
なお、Alexaで実行するスキル(アプリ)はあらかじめ端末への登録が必要です。登録されていないスキルや存在しないスキル名が指定された場合には、自然言語処理システムが、関連するスキルの登録を提案したり、データベースから関連情報の提示を行います。ただし、言語設定(ロケール)ならびにAmazon accountが一致していれば自分で開発したスキルはAlexaだけでなく他の端末(携帯電話など)で特に登録作業なくそのまま使用できます(自分専用スキルとして使用可能)。
2.2関連アカウントの取得
(1) Amazon.co.jpアカウントの取得
すでにAmazonの通販を利用するなどして日本におけるAmazonアカウントを所有している場合にはこの手続きは不要です。そのアカウントがそのまま使用できます。合衆国など海外のAmazonアカウントを所有している場合は改めて日本のAmazonアカウントを取得してください。
(2)Alexa開発者アカウントの取得
Alexa開発者アカウントの取得は間違いやすい箇所があるので十分に注意して行ってください(実際には新規取得ではなく既得のamazon.co.jpのアカウントをAlexa開発者アカウントに関連づける操作です)。
Amazon 開発者ポータル- Amazon Developer(https://developer.amazon.com/ja/ )にアクセスし、開発者アカウントの登録作業を行います。Amazon Developerの初期画面で「開発者コンソール(Developer Console)」をクリックします。

すると開発者コンソールのアカウント入力/アカウント作成画面となります。ここで上部の欄に既得のamazon.co.jpのアカウントとパスワードを入力してログインをクリックします。決して、最下段の「Amazon Developerアカウント作成」はクリックしないでください。非常にまぎらわしい部分ですが、ここで間違えるとあとで煩雑な修正操作が必要となります。

確認コードがアカウントにひもづけられた携帯電話/メールアドレスに送られるので、それを登録画面で入力して ”Submit code” をクリックします。そうすると開発者情報の入力画面となるので情報を入力します。なお、「開発者名」(ソフト開発者のハンドル名)は作成後に変更することができないので注意。必要な情報を入力したら最下部の送信ボタンをクリックします。

作成したスキルを一般公開する場合には、次の画面でさらに詳細なプロファイル入力が必要です。しかし練習用もしくは自分専用であれば不要なので、そのまま「コンソールの利用を開始」をクリックします。

なお、Alexa開発者アカウントの取得後はamazon developer (https://developer.amazon.com/ja/ )から、開発者コンソールにログインするとAmazon開発者ポータル画面となるので、そこでAlexa Skills Kitをクリックします。

2.3 Hello World例題による基本編集操作
Alexaスキルの作成では、その実行時にAmazonのクラウドサービスであるAWS (Amazon Web Services)を利用することとなるため本来であればAWSへのアカウント登録も必要です。AWSは有料サービスなので、その利用に応じて課金も発生します。ただし一定の制約条件のもとでAlexa hosted skillとしてAWSの存在・課金を気にすることなく無料で使用することもできます。ここではAlexa hosted skillとして”Hello World”スキルを統合環境で作成・実行する方法を説明します。
・作成するHello worldスキルの内容
ここで作成・実行するHello worldスキルはほとんどテンプレートそのものなのでコードに関する知識はあまり必要ありません(ただし英語圏向け)。スキルが呼び出されると、次のように動作します。
Welcome, you can say Hello or Help. Which would you like to try?
(ようこそ、HelloかHelpと言ってください)
-それに対してHelloと応えると:Hello world! (終了)
-Helpと応えると:You can say hello to me! How can I help?
(Helloと言えばいいの、いいかな? <次の入力待ち>)
-それ以外:Hmm, I'm not sure. You can say Hello or Help. What would you like to do?
(うーん、わかりません。HelloかHelpと言ってください。<次の入力待ち>)
・新規スキルの作成
まずはamazon developerにログインした状態で、Amazon Alexa Consoleを開き、Alexaスキルの一覧画面で「スキルの作成」をクリックします。

新しいスキルの作成画面が表示されるので「スキル名」の項目を入力します。この「スキル名」は管理上の名前であって、スキルを実行するときの呼び出し名(invocation name)とは異なります。ただしスキル名としては、このあと設定するプライマリロケールが「日本」の場合には日本語名(ひらがな、漢字)を、「英語(US)」の場合には英単語2語以上(例:hello test)を推奨します。単語にもよりますが、そうすると多くの場合、呼び出し名が自動的にスキル名と同じに設定されます。ただし、今はテンプレートを使用するのでプライマリロケールの言語は「英語(US)」とし※、スキル名は”hello test”であるとして説明します。入力したら「次へ」をクリックします。
※ここで使用するテンプレートプログラムのオリジナルロケール言語は英語です。そのため、内容に手を加えずロケールだけを日本として実行すると不自然な動作となるためです。

「1.エクスペリエンスのタイプ」としては汎用性の高い「その他」を選択します。

次に「2. モデルを選択」では汎用性のある「カスタム」を選択します。「3. ホスティングサービス」では記述言語に応じてAlexa Hosted Skillに対応する「Alexa-Hosted(Node.js)」(または「Alexa-Hosted(Python)」)を選択します。画面に説明があるように、Alexa Hosted SkillではバックグラウンドでAWS (Amazon Web Services)を無償使用できますが、その利用可能範囲には一定の制限があります。
「ホスト地域」は通常はそのままの標準値とします。そして「次へ」をクリックします。

テンプレートの選択画面となります。テンプレートを利用することで、いわゆる定型的なコードがあらかじめ入力された状態からコーディングを開始することができます。ここでは「スクラッチで作成」を選択し、右上の「次へ」をクリックします。「スクラッチ」といっても白紙状態からの作成ではなく、”Hello World!” のテンプレートが読み込まれます。

「審査(Review)」画面となるので設定内容に問題がなければ ”スキルを作成する(Create Skill)” をクリックします。

Alexa-hostedスキルのテンプレート作成画面となるので、そのまましばらく待ちます。画面の右下にbuild completedと表示されれば作成終了です。

なお初回のスキル作成時にはセキュリティ確認のための画面が表示されるのでその指示にしたがってください。
何らかの理由でスキル作成がいつまで待っても終了しない場合には、新規スキルの作成画面(https://developer.amazon.com/alexa/console/ask) に戻って、作成済スキルの一覧を確認します。そこに、先ほど作成したスキルが追加されていればOKで、なければ再度新規作成の手続きを行ってください。
スキルが無事作成された場合(あるいは作成済みスキル一覧画面で当該スキルをクリックした場合)、次のような、呼び出し名の設定等の画面となります。

*環境によりウィンドウ下部の選択言語が「Japanese(日本語)」と設定されているにもかかわらず、英語表記となることがありますが、下記説明と対応する部分を操作すれば問題ありません。
上記画面になったなら、「1.呼び出し名」をクリックして現在の設定値を確認、必要に応じて修整します。

この例ではスキル名が呼び出し名として採用されず、設定を要求する”change me”が表示されています(change meと表示されている場合にはそのまま放置はできません)。ここで、呼び出し名をhello worldと設定します。入力後、必ず「スキルをビルド( Buil Skill )」をクリックします。
・テンプレートのコード確認
この例では読み込まれたテンプレートがそのまま、いわゆる”Hello World”スキルとなっているので、特にコードの追加は不要です。ただ、「コードエディタ」タブをクリックするとそのコードが確認でき、必要に応じてテキストエディタとしてコードの追加や修正が可能です。今は手順の確認が目的であるため、コードの詳細な説明は省略し、見るだけとして編集も行いません。ただ、コードを見るとスキルの中にインテントに対応するルーチンが並列に配置されているのがわかります。スキル開始時の挨拶(”Welcome….”)の後に、入力待ちとなり、その後の音声入力に応じて処理が実行される流れとなっているのがなんとなく理解されると思います。

なお、もしコードエディタでコードを修整した場合にはコードエディタの画面で「保存」→「デプロイ」を順に実行して更新を反映させます(今はコード修整を行わないので不要)。
・スキルの実行
すでにビルド済みのスキルがある場合(あるいはコード修正後に「デプロイ」処理が終わっている場合)には「テスト」で動作確認ができます。「テスト」はAlexaシミュレータとなっていて開発途上もしく開発公開済のスキルの動作確認が行えます。

作成したスキルは初期状態では「非公開」扱いとなっています。「テスト」処理の画面左上に「非公開」と表示されている箇所があるので、こちらを「開発中」に変更すると作成中のコードの実行ができるようになります。さらに、ここが「開発中」であれば、同一のamazonアカウントを持つ他の端末(Alexaアプリをいれた携帯電話など)で設定ロケールが一致しているものならそのまま動作確認ができます(ただし、この例題のプライマリロケールの言語は「英語(US)」なので日本国内の端末では動作不可)。
さて作成したスキルの名称は「hello test」ですが呼び出し名(invocation name)は”Hello world”です。実行時に必要なのは呼び出し名であることに留意してください。テスト画面での実行は音声入力でもキーボードからの文字入力でも可能です。マイク入力が可能なPCであればマイクからの入力もできます(音声入力の許可を求めるウィンドウが開いたら適宜入力します)。
PC上でキーボードを利用して動作確認するには画面左上の入力欄に「Open Hello World」と入力し、キーボードの「Enter」キーを押します。開発画面(Alexa developer console)で動作確認する際にはwake wordである「Alexa」の入力(呼びかけ)は不要です。起動(あるいは開始)を意味するOpenなどの単語がなくても、呼び出し名によっては、単に「Hello World」のように呼び出し名だけでも起動します。
そうすると「Welcome, you can say Hello or Help. Which would you like to try?(ようこそ、HelloかHelpと言ってください)」と英語の返事が流れるとともに、その記録がチャットのように画面の左に記録されます。なお、仮にもしプライマリロケールとして日本を設定して英文を発音させたなら、その発音は日本語風読みの(カタコト)英語となります。このようにプライマリロケールに応じた言語モデルが用意されています。
さて選択肢の一つである「Help」を入力欄に入力します。すると使用法の説明を担当するHelpインテント(インテント:関数のようなもの)が起動され、” You can say hello to me! How can I help?”(ハローと言ってね)と返されて入力待ちとなります。引き続いて、「Good night」と不適切な入力するとエラー処理用のFallbackインテントが起動され、” Sorry, I don't know about that. Please try again.”(何をいっているのかわからないので、もう一度)と返されます。「Hello」と入力すれば”Hello World!”と返され、スキルが終了します。このように、入力した音声(単語)に対応して適切なインテントが実行されます。
このスキルの処理終了後、再度実行するためにはスキルを再起動(invoke)しなければなりません。すなわち、再度「Open Hello World(または単に Hello World)」と入力する必要があります。
このテスト環境は開発途中のスキルだけでなく、通常のAlexa環境のシミュレータともなっています。そのためスキルを再起動(invoke)せずに、Helpと入力すると、通常のAmazon Alexaシステムに「Alexa, Help.」と話しかけたときと同様に取り扱われるので注意が必要です。ロケールが米国の場合には、”If it is a life threatening situation….”(もし生命の危険を感じているなら至急、緊急電話をかけて…)と応答します。ロケールが日本だと楽曲の「Help」の聴取方法が説明されます。
したがって、同じ入力をしてもそれがスキルの中でインテントを起動するためのutteranceとして扱われるか、Alexaの動作を制御するinvocation wordとして取り扱われるかで異なります。AIスピーカーの場合、現在の状態がスキルを開始するinvocation word待ちの状態なのか、スキル開始後の指示待ちの状態なのか利用者の立場からはわからないことが多いので、この点は利用時に注意が必要です。
・冗長性への対応(インテントのサンプル発話)
ここで、再度スキルを実行してみます。「HelloかHelpと言って」という要求に、あえて「How are you?」と入力します。これまでの例からすると、”Good night!”と同じく、意味不明として対応されそうですが、”Hello”と入力したときと同様に”Hello World!”と返ってきます。
これは音声入力の冗長性を確保するために、”Hello”だけではなく、それに類する入力も同じ扱いとする仕掛けがあるからです。それを確認するには「ビルド」→「対話モデル(interaction Model)」→「インテント(intents)」→「HelloWorldIntent」をクリックします。

するとHelloWorldIntentを起動するサンプル発話として”Hello”だけではなく”How are you”など複数の発話が登録されていることがわかります。そのため、このリストにある入力であればどれもこのインテントを起動することができます。また必要であれば、入力欄にサンプル発話を入力し「+」をクリックすることで追加も可能です。(追加した場合には実行の前に「スキルのビルド」(Build Skill)をクリックして再ビルドが必要)。このようにしてサンプル発話として登録すれば、スキルの実行時に”Good night!”と入力して、”Hello World”の応答を得ることもできます。

サンプル発話はプライマリロケールとして設定した言語でなくてもかまいません。例でとりあげているテンプレートのスキルは、ロケールとしてUSを設定しています。しかし、発話サンプルとして日本語の「こんにちは」や「やあやあ」なども登録できます。ただ、後述するように言語の混在はエラー処理の際に若干の問題が発生します。
なお、修正・追加した発話サンプルが意図するインテントに結びつけられたかどうかは、「スキルのビルド」後にインテントの編集画面の上にあるモデルを評価 (Evaluate model)を左クリックすることで確認できます。

次の図は「モデルの評価」画面の一例です。
この例では発話例として「こんにちは」を入力し「送信」を左クリックしています。すると、選択したインテントとしてHelloWorldIntentが表示されています。すなわち「こんにちは」と入力があるとHelloWorldIntentにジャンプすることを意味します。
これにより、発話サンプルにないような単語でも(たとえば「こんちは」など)でもどこに処理が移るか実行前に確認できます。ただし現状では後述するようにプライマリロケールの設定(US)と異なる日本語が入力された際の処理で問題が生じることがあります。実際、このテンプレートの例では、「いただきます」と入力してもHelloWorldIntentにジャンプしてしまいます。

・スキルの呼び出し名変更、削除と追加、コードの編集
(1) 呼び出し名(invocation name)の変更
スキル名がロケールと対応しかつ後述の条件を満足しているのなら、呼び出し名(invocation name)は通常はデフォルトとしてスキル名が採用されます。そうでない場合には前述のように自分で設定する必要があります。一度設定した呼び出し名は別の名前に変更することもできます。そのためには「ビルド」→「呼び出し名」(invocation name)を左クリックします。
表示される「スキルの呼び出し名」(Skill Invocation Name)の欄で呼び出し名を設定できます。ただし呼び出し名には設定したロケールに応じた一定の条件があります。
ロケールがUSなど英語圏の場合:2つの単語の組み合わせであること
→ hello world, great greeting, fishy fish
ロケールが日本の場合:2文字以上のかなや漢字 →あいさつ試験、はじめて演習、極楽挨拶
また音声入力デバイスであること、誤動作を防ぐために、一般的な単語と区別しやすいことなども考慮します。次の例では”great greeting”を設定しています。

呼び出し名の入力が完了したら右上の「スキルをビルド」 を左クリックします。もし不適切な名称の場合にはビルド処理中にウィンドウ下部にエラーが表示されます。ビルドがエラーなく完了すれば、ウィンドウ上部のタブ「テスト」で新しい呼び出し名を用いて実行可能となります。
(2) スキルの削除と追加
スキルの追加や削除はAlexa開発コンソール(Alexa developer console)の「スキル一覧」タブ(https://developer.amazon.com/alexa/console/ask ) をクリックして行います。
削除は該当スキルの右側の「アクションを選択」から[削除]を選びます。新たなスキルを作成するには[スキルを作成]ボタンをクリックします。

(3) コードエディタによる編集
コードを編集するには「コードエディタ」タブをクリックしてコードを表示させます。そして、たとえばスキル起動時のメッセージ部分を「Welcome, you can say Hello or Help. Which would you like to try?」から「Welcome, I’ve been waiting for your arrival. 」に書き換え、「保存」→「デプロイ」とクリックします(ビルドは不要)。その上で、「テスト」で実行すると今度は応答が変化しているのが確認されます。

・ システム組み込みインテントと言語混在時の問題点
Alexa開発システムには、他のシステムでいう組み込み関数のような標準的なインテントが用意されており、ロケールがUSなら発話サンプルを追加することなくそのまま使えます。
よく使うものとしては、AMAZON.HelpIntent(ヘルプ処理用)、AMAZON.StopIntent(スキル停止用)、AMAZON.FallbackIntent(誤入力処理用)があります。AMAZON.HelpIntentは”Help”、AMAZON.StopIntentは”Stop”入力に対応するインテントです。このふたつは発話サンプルとして日本語の単語や文を追加することもできます。
AMAZON.FallbackIntentは誤入力処理用のインテントです。ロケールがUSと設定してあれば、どのインテントの発話サンプルにもない英単語が入力されると、AMAZON.FallbackIntentにジャンプし、英語で「意味不明の入力です」と応答します。しかしいずれかのインテントの発話サンプルとして日本語の文を登録したり、ロケールを日本と設定した場合には、発話サンプルにない単語を受け取ったときにAMAZON.FallbackIntentには分岐しません。この例では、HelloWorldIntentが実行されます。結果として発話サンプルにない単語が入力されれば、HelloWorldIntentに処理が移り、”Hello World!”と応答します(見かけ上、誤作動のようになります)。
これを回避するには自分で日本語誤入力処理用のインテントを作成する必要がありますが、それについては後述します。
2.4 コードの意味(フロントエンドとバックエンド)
本節では処理の流れをNode.jsのコード面から説明し、メッセージ出力だけの簡単なスキルのコード記述法を学習します。
2.4.1 フロントエンドとバックエンド
Alexaスキルの処理の流れを思い出してください。処理の流れは大別して二つの部分に分かれています。前半は入力を待ち受け、どのintentに分岐するか決定する部分です。これをフロントエンドと呼びます。この部分もコード(正確にはJSON)で記述されていますが、ユーザはスキル作成の際に対話形式で必要事項を入力するためコードを意識することはあまりありません。後半はコードエディタで確認したように、主にそれぞれのintentの処理を記述した部分で、これをバックエンドと呼びます。
フロントエンドのJSON形式データを確認するには、Alexa開発コンソールで編集の対象とするスキルを選び、左側のメニューから「対話モデル」(interation model)→「JSONエディタ」(JSON Editor)を選択します。
次の図に、前章で作成したHello World例題のフロントエンドのデータを示します。Invocation nameが ”hello world”であること、各種のシステムインテントのほかにHelloworldIntentがあること、そしてそれぞれのインテントを起動するサンプル発話の例が示されています(実際に発話例が記述されているのはHelloworldIntentのみ)。このような形でスキル作成時に指定したInvocation nameやサンプル発話は、フロントエンドのデータとして落とし込まれます。

バックエンドのコードについてはすでに説明したように、Alexa開発コンソールの上部メニューの「コードエディタ」から確認できます。バックエンドのコードの記述法については、これから順次説明してゆきます。
2.4.2 サンプルスキル(コードくん)の作成
前章ではテンプレートのスキルを読み込んで、メッセージ出力の一部を書き換えただけであったが、ここではコードの内容を説明しながらメッセージ出力をするAlexaスキル「コードくん」を作成します。
(1) 新規スキルの作成
前章で説明した手順にしたがい、新規スキルを作成します。
・スキル名は「コードくん」、プライマリロケールは「日本語」とします。
・エクスペリエンスのタイプは「その他」とし、モデルは「カスタム」、ホスティングサービスはNode.jsでコードを編集するために「Alexa-hosted(Node.js)」とします。ホスト地域はデフォルト値のままとします。



・テンプレートは「スクラッチで作成」を選択した後に、各種設定内容を確認し、右上の「スキルを作成する」ボタンを押します。
・スキルが準備できたら呼び出し名を「コードくん」に変更し、「Build skill」を実行します。


(2) バックエンドコードの修正
コードエディタでindex.jsを開きます。バックエンドコードには先に触れたようにシステムインテントを含む各種intentの処理内容が記述されています。またそれと合わせてスキルが最初に起動されたときに処理されるLaunchRequestHandlerオブジェクトも記述されています。今回のサンプルプログラムではLaunchRequestHandlerオブジェクトの記述法について説明します。先に書き換え後のコードを提示します(実際にはテンプレートと比べ13,17行目がわずかに異なるだけです)。

LaunchRequestHandlerオブジェクトの中には、canHandle( ) とhandle( ) の二つの重要なメソッドが記述されています。
canHandle( ) メソッドはユーザの入力に対してリクエスト(この場合はスキルの起動:LaunchRequest)に対応可能か判断します。対応可能(true)であれば handle( ) メソッドに書かれた処理が実行されます。
handlerInput.responseBuilderはユーザへの応答を作成する部分で、.speak( )関数は、 responseBuilderにspeechText の値をユーザに読み上げるよう指示します。コメントアウトされています(//)が.reprompt( )はプロンプト読み上げ関数でユーザからの応答がない(無言)のときに読み上げる関数です。.getResponse()関数は、responseBuilderが作成した内容をスキルが返す応答に変換します。この行は、送信ボタンを押すようなイメージで、応答を送信します。
これがスキル起動部分のオブジェクトの内容です。変更内容を反映させるためにデプロイし、テストで動作確認を行います。なおインテントの処理については次節で説明します。
2.5 NLUモデルの作成とコードの記述
NLU(Natural Language Understanding)モデルとは自然言語処理系モデルで、Alexaでは受け付けたキーワードから、どのintentを実行するか決定するモデルとなります。これはフロントエンドが担当する部分となります。本章では複数のパターンで起動されるintentの例を提示し、さらにそれらに対応するバックエンドのコード記述法についても説明します。
2.5.1 想定するインテントの起動パターン
ここでは2つのパターンで起動されるインテントを想定します。
(1) intent_A
あらかじめ定められた次の文例(単語)と入力が合致したとき起動します。
・コスモス
・ばら
・ひまわり
・あじさい
(2) intent_B
単語帳と紐付けられた単語群{animal}を含む次の文例(単語)と入力が合致したとき起動します。なお、intent側では起動時に{animal}の部分で指定された値を引数として変数で受け取ることができます。
・{animal}
・{animal}が好き
・好きなのは{animal}
また{animal}は、別途用意された次の単語を含む単語帳{animal_names}と結びつけられています。
犬、ねこ、ねずみ、うさぎ
2.5.3 インテントの追加と設定
Alexa developer consoleを開き[ビルド]タブ→[インテント(Intents)]→[インテントを追加(Add Intent)]を選択します。


intent_Aを追加し、「Create custom intent」を押します。サンプル発話(Sample Utterances)の欄に{コスモス|ばら|ひまわり|あじさい}を登録します。

入力が終わったら、左のIntentsメニューをクリックし、intentの一覧にintent_Aが追加されていることを確認します。
同様にしてintent_Bを追加します。ただし今度は単語の集合があるので操作が複雑です。まず、サンプル発話(sumble utterances)の欄に{animal}と記入します。すると{animal}が単語の集合を表すスロット(Slot)として認識され、新規のスロットを作成するかどうか確認が求められるので追加(Add)を押します。

なお、欄に入力しただけでは登録されないのでEnterキーを押すか、右端の「+」をクリックするのを忘れないこと(登録されると下の行に移る)。

スロット{animal}を含む文では前後の単語との間に半角空白が必要です。キーボードから発話サンプルを入力した場合には自動的に挿入されますが、コピー・ペーストの場合には挿入されずエラーの原因となることもあるので注意してください。またサンプル発話の末尾に区点「。」をつけるとエラーとなります。
この段階ではスロットanimalには単語群は紐付けられていません。Alexaシステムでは別にスロットタイプと呼ばれる語彙群を用意し、それをスロットに紐付ける形をとります。スロットタイプとしては既存のビルトインスロットタイプと独自の単語で構成するカスタムスロットタイプが選択できます。
既存もしくはビルトインスロットタイプを選択するのであれば、下部のSLOT TYPEの「Select slot type」の欄をクリックするとスロットタイプの一覧が表示されるので適切なものを選択します。
新規にカスタムスロットタイプを作成するのであれば、左側の「スロットタイプ(Slot Types)」メニューを選び「スロットタイプの追加(+Add Slot Type)」を選択します。

「スロットタイプの追加(Add Slot Type)」画面となるので、「値を持つカスタムスロットタイプを作成(Create a custom slot type with values)」を選択、名称欄に「animal_names」を指定し、「NEXT」ボタンを押します。
単語の登録画面となるので、「犬/ねこ/ねずみ/うさぎ」を順次登録してゆきます。登録はしても、この段階ではまだスロット{animal}とスロットタイプ{animal_names}は紐付けられていないことに注意してください。

左側のメニューで「インテント(intents)」を選択し、さらにintent_Bを選びます。下部のスロットタイプの割り当て部分を見ると、今度はカスタムスロットとしてanimal_namesがあるのでそれを選択します。

これでインテントの設定は終わりですが、Hello Worldのテンプレートを使用したために必要のないHelloWorldIntentが残っています。そこでIntentの一覧でHelloWorldIntentを削除します。

最後に右上のBuild skillを押します。Buildでエラーが出たら次の点を再確認します。
*サンプル発話で「{animals}です」(スロット前後に半角空白なし)、「{animals} です。」(末尾に句点あり)とすると、「スキルのビルド」で次のような文を含むエラーが出ます。
・Sample utterances can consist of only unicode characters, spaces, periods for abbreviations, underscores, possessive apostrophes, and hyphens.
・Parsing error in sample.
次に入力語句が正しくインテントと結びつけられているかの確認を行います。ビルドのウィンドウ上部にある「モデルの評価(Evaluate model)」をクリックします。中央の部分に、語句を入力すると、それがどのインテントと結びつけられスロット値として何が得られるかが単体で確認できます。
図の例では「ねこ」をsubmitするとintent_Bに結びつけられ、{animal}の値(スロット値)として「ねこ」が得られることがわかります。思うように認識されない場合はNLUモデルの修整を行います。評価モードを終わるには再度「モデルの評価(Evaluate model)」を押します。

最後に、左側のメニューJSON Editorでフロントエンドにこれまでの設定が反映されていることを確認します。

2.5.4 バックエンドのコード修整
(1) 開始メッセージの変更とrepromptによる入力待ち
フロントエンドの設定が終わったら、コードエディタを開いてバックエンドのコード修整を行います。まずスキル起動直後のメッセージ出力を「コードの練習にようこそ。花かお好きな動物の名前を教えてください。」と変更します。さらに、前回はコメントアウトした .reprompt も活用します。
.reprompt( ).関数は次のような機能を持ちます:
スキルに、終了するのではなく、ユーザからの回答を待機するよう指示する。
ユーザが答えなかった場合に、もう一度たずねる方法を指定する。
ここではintent_Aかintent_Bが実行されるよう、.reprompt の出力メッセージとして「コスモスとか犬が好きのように応えてください。」を指定します。
これらをindex.jsに反映させると、関係する部分は次のようになる。

この状態ではintent_A, intent_Bの処理内容の記述がまだバックエンドにはありませんが、その場合にはシステムインテントIntentReflectorHandlerが実行されて、どのintentに分岐しようとしたかが表示されます。
そのため、この状態でもデプロイしてテストすることは可能で、図のようにどのintentに分岐しようとしたかのメッセージ(You just triggered intnt_B)が表示されます。

(2) intentハンドラの意味と修整
各intentに対応して処理を行うブロックをハンドラと呼びます。HelloWorldIntentは削除したので実行されることはないですが、バックエンドのコードにはHelloWorldIntentHandlerがまだ残っています。このコードについて説明してから、その内容をintent_Aに適した形に書き換えることとします。まずは現在のHelloWorldIntentHandlerの内容とその意味を下に示します。

22行目:intentのハンドル名(任意に指定可能)
23~26行目:リクエストがintentの起動(IntentRequest)でかつそれがHelloWorldIntentの起動であるかの判定
27~34行目:判定結果がTrueなら、speakoutに’Hello World’をしまって、それを.speak関数に渡し.getResponse関数で応答を返す(コメントアウト「//」部分の説明は省略)。
これを踏まえて、上記の内容をハンドル名も含めて先に作成したintent_A用に書き換えると次のようになります。

同様にしてintent_Bのハンドラも記述できますが、こちらはスロット{animal}があるので、少し表現が異なります。スロット{スロット名}で受け取った内容は次の変数に格納されています。
handlerInput.requestEnvelope.request.intent.slots.スロット名.value
この値をローカル変数animalにしまいます。またその変数の引用は \${変数名}(今の場合\${animal})で表されます。これらを踏まえてintent_Bが開始されたときに、スロット名を含めてメッセージを表示させると次のようになります。
*文字列中に変数値 ${ } を含む場合には、文字列は「’」ではなく「`」(バッククォート)で囲むことに注意。

(3) 追加したハンドラのexports
最後に追加した二つのハンドラをexportsでシステムに通知する必要があります。それを行うのがコードの下の方にあるexports.handlerに続く「.addRequestHandlers(…)」 の部分です。このハンドラのリストから不要となったHelloWorldIntentHandlerを削除し、新規に作成したintent_AIntentHandlerとintent_BIntentHandlerを追加すると次のようになります。

コードの変更が終了したらデプロイします。
2.5. 5 動作確認
デプロイが無事終了したらテストメニューで動作確認します。

意図しない動作となった場合、よくある原因として次のようなものがあるので確認します。
・出力でスロット値が表示されない→変数を含む文字列がバッククォート「`」で囲まれていない。
・追加したintentの表記に間違いがある(大文字小文字の違いなど)。
・追加したハンドラのシステムへのexports(.addRequestHandlers(…)の修整)を忘れている。
またintent作成後のモデルの評価(Evalute model)で気づいたかもしれませんが、intentで指定したサンプル発話やスロットタイプに完全に一致しなくてもそのintentが実行されることがあります。サンプル発話やスロットタイプは入力を限定するというよりは例示する内容と捉えた方がよいかもしれません。
2.6 複数のスロットを持つインテントと演算・判断処理
インテントによっては「○○から▽▽まで」のように複数のスロット(情報の受け皿)を持つものがあります。そのようなケースで情報の一部が書けているときの扱い、また必要に応じて演算や判断を行う場合の記述法について説明します。
2.6.1 複数のスロットをもつインテント
(1) 想定するインテントとスキル
複数のスロットをもつインテントの例として、乗車券の購入を考えます。すなわち次のような入力で起動されるインテントです。
・東京から新大阪まで/東京駅から新大阪駅まで/新大阪まで東京から
駅名の部分がスロットとなるので一般的な表記で表せば次のようになります。ただし乗車駅を{StartSt}、下車駅を{DestSt}とします。
・{StartSt}から{DestSt}まで/{StartSt}駅から{DestSt}駅まで/{DestSt}まで{StartSt}から
ただし、人によっては「新大阪まで」とだけ言って、「東京から」を言わない人もいるかもしれません。そういう場合の処理も含めて説明します。
スキル動作としてはInvocation nameが「切符くん」で、入力内容を確認後に、「○○から△△までの乗車券をご用意します」と応えるものとします。
(2) インテントの設定
ロケールを日本語として新規スキル「切符くん」をすでに説明した方法で作成します。呼び出し名(Invocation name)も前述のように「切符くん」とします。
インテントの新規作成画面でCaptureRouteIntent(名称は任意だがここでは説明用にこのように設定)を作成します。

サンプル発話(Sample Utterance)の欄は2つのスロット{StartSt}、{DestSt}を用いて記述します。入力中に新しいスロットを作成するかのポップアップウィンドウが表示されますがいったん無視してそのまま入力を続け、Enterキーを押します(または右の+をクリックする)。するとふたつのスロット部分が異なる色で表示されると同時に、ウィンドウ下部のIntent Slotsの欄にスロット{StartSt}、{DestSt}が追加されているのが確認されます。
そのまますべてのサンプル発話の入力を行います。すでに最初のサンプル発話の入力でスロット{StartSt}と{DestSt}は作成されているので、次からは「{」を入力しただけで右図のようにスロットの選択肢が現れます。それを適宜選択して、サンプル発話を随時入力します。


まだこの段階ではこれらのスロットに紐付けられる単語の集合であるスロットタイプは用意されてません。内容から理解できるように対応するスロットタイプは駅名の集合と考えられるので、左側のSlot Types()のメニューから新規スロットタイプStations(名称は任意)を作成します(既存のスロットタイプで適切なものがあればこの操作は不要)。

次図の例ではスロットタイプStationsのデータとして東京~新大阪まで5駅を登録しています。登録後にいったん保存(Save)して左側のメニューIntentsを選び、CaptureRouteIntentの設定画面に戻ります。

そして次の図のようにSLOT TYPEの欄を編集し二つのスロット{StartSt}、{DestSt}とスロットタイプStationsを紐付けします。

さらにウィンドウ下部の「インテントの確認(Intent Confirmation)」スイッチをスライド(on)にすると、入力後に指定の形式で入力内容を復唱させることができます(右側の+クリックまたはEnterを忘れないように)。Intent Confirmationは必須ではありませんが、必要に応じて指定すると便利です。復唱させた場合には、それに対して「はい」などのようにユーザが応答する必要があります。
場合によっては「名古屋まで」と情報の一部しか入力されないこともありえます。そのような場合に備えて、これらのスロット{StartSt}、{DestSt}は入力必須とし、情報が不足していたらプロンプトを出して、不足情報の入力を要求することもできます。そのためには上図NAME欄のスロット名{StartSt}(または{DestSt})をクリックし、スロットのプロパティを編集します。
次の図はスロット{StartSt}のプロパティ編集例で「このスロットは必須(Is this slot required to fulfill the intent?)」のスライドスイッチを右側(on)にします。そしてプロンプト文として「乗車駅がわかりません。教えてください。」と指定します。入力後に右側の+またはEnterキーを押して登録するのを忘れないようにしてください。
なお、このプロンプトに対する応答に対しても確認メッセージを出力したいときには下部のSlot Confirmationのスライドスイッチをonにして指定することもできます。

{DestSt}についても同様に設定します。
これでインテントの設定は完了なので右上のBuild SkillボタンをクリックしてBuildします。
(3) インテントの動作確認
インテントの設定とbuildが終わったら、バックエンドコード修整の前にフロントエンド側の動作確認、すなわち入力とインテントの関係確認を行います。左側のメニューでインテント(intent)を選び、画面上部の「モデルの評価(Evaluate model)」を選択します。

この「モデルの評価(Evaluate model)」ではフロントエンド側だけの動作確認ができます。またどのスロットに何が格納されたか確認できます。
新規であれば下図の左側の白紙状態でモデル評価が開始されますが、再実行や修整などを行った場合には(Buildをしても)右図のように前回の状態が継続されることがあります。そのときには古い情報が残っていて正しい評価ができないので、Exit muti-turnをクリックして情報をクリアします。

白紙状態から、さまざまなパターンで入力し、CaptureRouteIntentが起動され二つのスロットに適切な情報が格納されたかを確認してください。また情報が不足している場合に適切なプロンプトの表示と追加入力ができるかについても確認します。
動作に問題がなければ、最後に左側のメニューJSON Editorでフロントエンドのコードを確認しておきます。
(4) バックエンドのコード修整
コードエディタを開いてバックエンドのindex.jsのコード修整をおこないます。スロットが二つになっただけで追加・修正部分は基本的にスロットが一つの場合と同じです。ポイントは次の3つとなります。
・LaunchRequestHandlerを修整してスキル起動時のメッセージを出力させる
・新規にCaptureRouteIntentHandlerを作成し(あるいは不要となったテンプレート中のHelloWorldIntentHandlerを修整し)、受け取ったスロットの内容を表示させる。
・コード末尾の.addRequestHandlers( )に追加したCaptureRouteIntentHandlerの登録を行う。


コードの修整が終わったら、デプロイしてテストメニューで動作確認を行います。
2.6.2 インテントにおける判断や演算
Alexa開発コンソールのコードエディタでは、Javascript(またはPython)で判断構文や演算を記述できます。したがって判断や演算処理が必要な場合であっても、それらの文法にしたがってコードを記述するだけです。
ただし実行の際に数字の入力はキーボード入力では、図のように漢数字でないと正しく処理されない点に注意してください。音声入力であれば漢数字として変換入力されるので問題ありません。
