Alexaのスキルを作ってみよう
サンプルを用いてスキルを作ってみる
まずはAlexa Skills Kit開発者コンソール(以下、開発者コンソール)にログインします。以下のリンクから開くことができます。
https://developer.amazon.com/alexa/console/ask
Amazon Developerアカウント登録直後は、下図のような画面になっているかもしれません。その場合はページの上部にある「ALEXA SKILLS KIT」と書かれたメニューをクリックしてください。開発者コンソールの画面が開きます。
新しいスキルを作成する
開発者コンソールを初めて開くと、下図のような表示になっているはずです。さっそく「スキルの作成」をクリックしてみましょう。
「新しいスキルを作成」というページに切り替わりますので、ここでスキルの名称を入力します。ここでは「来場者カウント」という名称をつけましたが、この名称は管理用ですので、わかりやすいものであればOKです。まず「スキル作成時のデフォルト」と書かれた欄で「日本語」を選択しておきます。選択後、「次へ」をクリックします。
「スキルに追加するモデルを選択」というページに切り替わりますので、「カスタム」を選択して「スキルを作成」をクリックします。
新しいスキルが作成されました。
スキルの呼び出し名を設定する
ページの上部には、先ほどつけたスキルの管理用の名称と、「ビルド」「テスト」などの操作メニューが並びます。左側には、「カスタム」という大項目の下に「対話モデル」という項目、さらにその下に「呼び出し」「ビルトインインテント」などの項目が並びます。これらは、このスキルが1つのカスタムモデルを持ち、その対話モデルの呼び出し名などの設定が行えることを示しています。
まずは呼び出し名を設定するため、「呼び出し」をクリックします。
「スキルの呼び出し名」欄に、このスキルの呼び出し名である「来場者カウント」と入力し、「モデルを保存」をクリックします。
インテントを追加する
次にインテントを追加するため、「ビルトインインテント(3)」と書かれた項目右側の「+追加」をクリックします。
すると「インテントを追加」と書かれたページに切り替わり、「カスタムインテントを作成」という項目が選択されていると思います。もし、インテントの一覧が表示される画面に切り替わった場合は、「インテントを追加」ボタンをクリックすることでこの画面を表示できます。
ここでは「インテントの名称」欄に「VisitorCountIntent」と入力します。この名称は後にプログラムから参照する名称ですので、英数字でつける必要があります。名称の決め方は「CancelIntent」などシステムに元々用意されているインテント(ビルトインインテント)にならって、「英数字の名称」+「Intent」とするのがよいでしょう。入力したら「カスタムインテントを作成」をクリックします。
追加したインテントにサンプル発話を追加する画面に切り替わりますので、「来場者数を教えて」と入力します。入力後、Enterキーを押すとサンプル発話が追加されます。追加されたらページの上の方にある「モデルをビルド」をクリックしましょう。
下の画面は、ビルド中のようすです。完了するとメッセージが表示されます。完成した対話モデルのスキーマ(JSON形式)を確認するため、今度はページ左側のメニューから「JSONエディター」をクリックしてみましょう。
対話モデルがJSON形式で表現されているのが確認できます。慣れてくると、最初からJSON形式で編集することで、作業効率を上げることができます。
スキルIDを取得する
最後にこのスキルを一意に識別するための「スキルID」を取得しておきましょう。画面左の「エンドポイント」メニューをクリックします。
スキルIDは「エンドポイント」の画面に「amzn1.ask.skill.…」で始まる形式で表示されていますので、これをコピーして、テキストエディターなどに貼り付けて保存しておきましょう。AWS Lambda関数を作成する際に、この文字列が必要になります。
これで、最も基本的なスキル・インターフェースの実装が終わりました。次にスキル・サービスの実装に移ります。この作業はAWSにログインして行います。
Lambda関数を作成する
AWSのコンソールにログインして、AWSサービスの一覧から「Lambda」をクリックします。検索欄に「Lambda」と入力するとすばやくサービスにたどりつけます
AWS Lambdaの初期画面は下図のようになっています。さっそく「関数の作成」をクリックしましょう。
「関数の作成」画面では、「設計図」をクリックします。画面の下半分に設計図(関数のひな型)の一覧が表示されますので、画面をスクロールさせて「alexa-skill-kit-sdk-factskill」を探します。
「alexa-skill-kit-sdk-factskill」が見つかったらクリックし、さらに画面を一番下にスクロールさせて右下の「設定」をクリックします。
「基本的な情報」ページに切り替わったら、「名前」の欄に作成する関数の名称を入力します。ここでは「visitorCountSkill」とし、「ロール名」には「myRole」と入力します。そのまま画面を下にスクロールさせて、「Lambda関数のコード」と書かれたセクションを表示させます。
ページの一番下にある「関数の作成」をクリックします。この操作でLambda関数が作成され、関数の編集ページに切り替わります。
Lambda関数を編集する
「Designer」と書かれたセクションの「トリガーの追加」メニューから「Alexa Skills Kit」をクリックします。Designerセクションの内容が表示されていない場合は、「Designer」の文字列を一度クリックすると表示されます。下の画面のような表示になったら、再びページを一番下にスクロールさせます。
「スキルID」欄に先ほど取得したスキルIDの文字列を入力しして「追加」をクリックします。追加したら、ページ右上の「保存」をクリックします。
保存が終わったら、ページ左上の「関数」と書かれたリンクをクリックして、いったん関数の一覧に移動します。次に「visitorCountSkill」をクリックして再び編集画面を表示させます。さらに、再度画面を下の方にスクロールさせて「関数コード」と書かれたセクションを表示させます。
関数コード画面で「index.js」を選択し、右側の編集エリア内のコードを、コード例1のように書き換えます。このとき、「const APP_ID =‘amzn1.ask.skill.b6030ab0-…’;」のシングルクォーテーションで囲まれた内容には、先ほど取得したスキルIDの文字列を入力します。
'use strict'; const Alexa = require('alexa-sdk'); //============================================================================= //TODO: The items below this comment need your attention. //============================================================================= //Replace with your app ID (OPTIONAL). You can find this value at the top of your skill's page on http://developer.amazon.com. //Make sure to enclose your value in quotes, like this: const APP_ID = 'amzn1 .ask.skill.bb4045e6-b3e8-4133-b650-72923c5980f1'; const APP_ID = 'amzn1.ask.skill.b6030ab0-d878-4bd3-bff0-790750d638d2'; const SKILL_NAME = '来場者カウント'; const HELP_MESSAGE = '来場者数を教えて、で今日の来場者数をお知らせします'; const HELP_REPROMPT = '何をお調べしますか'; const STOP_MESSAGE = '終了します'; const visitorCount = 156; //============================================================================= //Editing anything below this line might break your skill. //============================================================================= const handlers = { 'LaunchRequest': function () { this.emit('VisitorCountIntent'); }, 'VisitorCountIntent': function () { const speechOutput = '今日の来場者数は' + visitorCount + '人です'; this.response.cardRenderer(SKILL_NAME, speechOutput); this.response.speak(speechOutput); this.emit(':responseReady'); }, 'AMAZON.HelpIntent': function () { const speechOutput = HELP_MESSAGE; const reprompt = HELP_REPROMPT; this.response.speak(speechOutput).listen(reprompt); this.emit(':responseReady'); }, 'AMAZON.CancelIntent': function () { this.response.speak(STOP_MESSAGE); this.emit(':responseReady'); }, 'AMAZON.StopIntent': function () { this.response.speak(STOP_MESSAGE); this.emit(':responseReady'); }, }; exports.handler = function (event, context, callback) { const alexa = Alexa.handler(event, context, callback); alexa.APP_ID = APP_ID; alexa.registerHandlers(handlers); alexa.execute(); };
関数の編集後にページ右上の「保存」をクリックして完了です。
保存が完了したら再びページを上にスクロールさせ、右上の「arun:aws:lambda:ap-northeast-1:」で始まる文字列をコピーして、テキストエディターなどに貼り付けて保存しておきます。この文字列を、今度は開発者コンソールから先ほど作成したスキル・インターフェースに設定して、スキル・インターフェースとスキル・サービスの関連付けを行います。この流れを次の図に示します。
サンプルプログラムの解説
ここで、今回のサンプルプログラムの説明をしておきます。
(1)ハンドラーの定義
ユーザーからのリクエストに応じてスキルサービスが応答するために、リクエストごとの処理を定義するのがハンドラーの役割です。このサンプルで使用しているフレームワークでは、リクエストをキーに、処理内容の関数を値にセットした配列の形式で定義します。
(2)LaunchRequest のハンドラー
「アレクサ、〇〇を開いて」のように、インテントを特定しないでスキルを呼び出すと、LaunchRequestと呼ばれるリクエストがスキルサービスに渡されます。この例では、規定の動作としてVisitorCountIntentの処理に動作を引き継ぎます。
’LaunchRequest’: function () { this.emit(’VisitorCountIntent’); },
(3)VisitorCountIntent のハンドラー
今回定義した、VisitorCountIntentインテントが呼び出された場合に行う処理を定義します。visitorCount定数を使って返答内容を生成し、それをthis.response.speak()に渡すことで、Alexaがその通り発話します。this.response.cardRenderer()にも渡していますが、これによりAlexaアプリ(Alexaの初期設定等に使用するスマートフォンアプリ)の画面にも結果を送ることができます。返答処理が完了し、再びリクエストを受け付けられるようにするのが「this.emit(’:responseReady’);」の役割です。
’VisitorCountIntent’: function () { const speechOutput = ’今日の来場者数は’ + visitorCount + ’人です’; this.response.cardRenderer(SKILL_NAME, speechOutput); this.response.speak(speechOutput); this.emit(’:responseReady’); },
スキルのテスト
それではもう一度、開発者コンソールから先ほど作成した「来場者カウント」の「エンドポイント」ページを表示させましょう。もしログインからやり直した場合には「Alexaスキル」の一覧ページから「来場者カウント」スキルの「編集」をクリックしてから「エンドポイント」をクリックします。
「サービスのエンドポイントの種類」で「AWS LambdaのARN」を選択し、「デフォルトの地域」欄に取得した「arun:…」の文字列を貼り付けて「エンドポイントを保存」をクリックします。「マニフェストスキルが正常に保存されました」というメッセージが表示されれば完了です。
それではいよいよテストです。作成したスキルを試してみましょう。
開発者コンソールのスキルの編集画面の上にあるメニューから「テスト」をクリックします。ブラウザにマイクの使用を許可するか尋ねられた場合は許可しておきましょう。
スキルテストを有効にする
テストページを初めて開いた場合は「このスキルでは、テストは無効になっています」と表示されていますので、クリックして有効に切り替えます。
マイクのアイコンをクリックしながら、PCのマイクに向かって話してみましょう。マイクを搭載していないPCの場合は、代わりにテキストを入力できます。
「アレクサ、来場者カウントを開いて」
で規定の動作として来場者数を答え、
「アレクサ、来場者カウントで来場者数を教えて」
でも来場者数を答えています。うまく動きましたか?
トラブルシューティング
うまく動作しない場合にはいくつかの原因が考えられますが、まずは下記の点を確認してみてください。
- 音声入力でうまく動作しない場合、テキスト入力ではどうか? Alexaシミュレーターの動作が不安定で、テキストの場合にのみ動作することもあるようです。
- エンドポイントとして設定したAWS Lambdaの文字列は正しいか?
- AWS Lambdaにトリガーを作成したか。スキルIDに正しい文字列を入力したか?
- AWS Lambdaのコードは「設計」から作成したか?
これらを確認した上で、まだ問題点が見つからない場合には、問題箇所の発見のために次のツールが利用できます。
Alexaシミュレーター上のデバイスのログを有効にする
シミュレーターのページ右側にある「デバイスのログ」を有効にすると、スキル・インターフェースとスキル・サービスの間のやりとりを確認できるようになり、動作の把握に役立ちます。
AWS Lambda関数の「モニタリング」ページ
モニタリングのページを参照すると、実際にLambda関数が呼び出されたかどうかや、エラーの発生状況などを確認することができます。スキル・サービスと正しく接続されているかどうかの検証に役立ちます。
最後に、もう1つのインテント
「アレクサ、来場者カウントで欠席者数を教えて」
に答えるための設定画面とコード例を掲載しておきます。ご自身で追加して、うまく動作するか試してみてください。それでは次回をお楽しみに!
'use strict'; const Alexa = require('alexa-sdk'); //============================================================================= //TODO: The items below this comment need your attention. //============================================================================= //Replace with your app ID (OPTIONAL). You can find this value at the top of y our skill's page on http://developer.amazon.com. //Make sure to enclose your value in quotes, like this: const APP_ID = 'amzn1.a sk.skill.bb4045e6-b3e8-4133-b650-72923c5980f1'; const APP_ID = 'amzn1.ask.skill.b6030ab0-d878-4bd3-bff0-790750d638d2'; const SKILL_NAME = '来場者カウント'; const HELP_MESSAGE = '来場者数を教えて、で今日の来場者数をお知らせします'; const HELP_REPROMPT = '何をお調べしますか'; const STOP_MESSAGE = '終了します'; const visitorCount = 156; const absenteeCount = 18; //============================================================================= //Editing anything below this line might break your skill. //============================================================================= const handlers = { 'LaunchRequest': function () { this.emit('VisitorCountIntent'); }, 'VisitorCountIntent': function () { const speechOutput = '今日の来場者数は' + visitorCount + '人です'; this.response.cardRenderer(SKILL_NAME, speechOutput); this.response.speak(speechOutput); this.emit(':responseReady'); }, 'AbsenteeCountIntent': function () { const speechOutput = '今日の欠席者数は' + absenteeCount + '人です'; this.response.cardRenderer(SKILL_NAME, speechOutput); this.response.speak(speechOutput); this.emit(':responseReady'); }, 'AMAZON.HelpIntent': function () { const speechOutput = HELP_MESSAGE; const reprompt = HELP_REPROMPT; this.response.speak(speechOutput).listen(reprompt); this.emit(':responseReady'); }, 'AMAZON.CancelIntent': function () { this.response.speak(STOP_MESSAGE); this.emit(':responseReady'); }, 'AMAZON.StopIntent': function () { this.response.speak(STOP_MESSAGE); this.emit(':responseReady'); }, }; exports.handler = function (event, context, callback) { const alexa = Alexa.handler(event, context, callback); alexa.APP_ID = APP_ID; alexa.registerHandlers(handlers); alexa.execute(); };