Alexa Skills Kit SDK for Node.jsについて知る
こんにちは。
これまでの回を通して、Alexa Skills Kitを使って行う開発の基本的な流れを解説してきました。連載4回目となる今回は、スキル・サービス側のコードに焦点を当てて、フレームワークの使い方をより詳しく理解していくことにしましょう。
今回のテーマはこちらです。
- スキル・インターフェースから渡されるリクエストの概要
- Alexa Skills SDKを使ったコードの構造について
Node.jsについて
Alexaのスキル・サービスを開発する際にAWS Lambdaを使う場合には、Node.js、Java、Python、C#の4種類の言語(正確には言語と実行環境)が利用できます。AWS Lambdaについておさらいしておきましょう。AWS LambdaはWebアプリケーションを「関数」という小さな単位で配置、実行できるクラウドベースの実行環境で、いわゆるFaaS(Function as a Service)です。Alexaのスキル・サービスのような、他システム(ここではスキル・インターフェース)から呼び出されるアプリケーションを配置するのに適しており、毎月100万件までの呼び出しなら無料で利用できます。
上に挙げた4種類の言語のうち、この連載ではNode.jsを利用してきました。より正確に表現すると、Node.jsは言語ではなくJavaScriptの実行環境の一種です。JavaScriptはほとんどの開発者が一度は触れたことのある言語ではないかと思います。特にWebなどのフロントエンドを扱う開発者にとっては、今や必修の言語と言えるでしょう。このJavaScriptを、サーバーサイドのアプリケーション開発にも利用できるようにした実行環境がNode.jsです。多くの開発者にとって馴染みのあるJavaScriptで開発ができるNode.jsは、Alexaのような新しいツールのための開発にはぴったりだと思います。
このNode.jsが備える特徴のひとつに、「npm」と呼ばれるパッケージ管理ツールを利用できることが挙げられます。npmを使うと、膨大な数の既存ライブラリを活用して簡単に機能拡張ができるようになります。Alexaのスキル・サービスの開発でも、「Alexa Skills Kit SDK for Node.js」と呼ばれるパッケージを使います。パッケージ名は「alexa-sdk」です。
Alexa Skills Kit SDK for Node.jsの配布場所:
- npmパッケージ:https://www.npmjs.com/package/alexa-sdk
- ソースコード:https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs
スキル・インターフェースからのリクエスト
スキル・サービスは、スキル・インターフェースからの各種リクエストに応答するサーバープログラムです。カスタムスキルを実装する場合に、サービスが応答しなければならないリクエストは次の3種類です。
- LaunchRequest
- IntentRequest
- SessionEndRequest
以下、それぞれのリクエストについて概略を見ていきましょう。
LaunchRequest
ユーザーは「~を開いて」のように発話することで、呼び出し名のみでスキルを呼び出すことができます。この場合、スキル・サービスはLaunchRequestを受け取ります。ユーザーは機能(インテント)やそれに付随する情報(スロットの値)を指定していいないため、このリクエストを受け取ったサービスは既定の動作を行います。もしユーザーから追加の情報を得たい場合は、Alexaがそれを尋ねるようにもできます。
つまり、ユーザーが以前にこのスキルを使用した際の情報を覚えておくような仕組みを実装すれば、それに基づいて適切な応答をすることもできます。このような仕組みは、Amazon Dynamo DBのようなデータベースサービスを用いて実装できます。
IntentRequest
「Alexa、~で~して」というように、ユーザーがインテントを指定してスキルを呼び出すと、スキル・サービスはIntentRequestを受け取ります。このリクエストには、呼び出されたインテント名が含まれるほか、スロットがある場合にはスロット値も含まれます。サービスはこれらの情報に基づいて処理を行い、スキル・インターフェースに応答します。
SessionEndRequest
スキルが次のいずれかの理由で閉じられると、スキル・サービスはSessionEndRequestを受け取ります。
- ユーザーが「終了して」と発話した場合
- ユーザーが応答しなかった場合や、ユーザーの応答に対応するインテントが見つからなかった場合
- 何らかのエラーが発生した場合
スキル・サービスプログラムの構造
これまで扱ってきたスキル・サービスの構造について、より詳しく見ていきます。
Lambda関数ハンドラーを定義する
AWS Lambdaはハンドラーオブジェクトを介して関数を呼び出します。つまり、ハンドラーオブジェクトが指す関数が、プログラムコードの中で最初に実行される処理(エントリーポイント)となります。ここでは、index.jsというファイルでLambda関数ハンドラーを定義します。
// (1)Alexa Skills Kit SDKを読み込む const Alexa = require('alexa-sdk'); // (2)APP_IDを定義する const APP_ID = 'amzn1.ask.skill.~実際の値を入力してください~'; // (3)Lambda関数ハンドラーを定義する exports.handler = function (event, context, callback) { const alexa = Alexa.handler(event, context, callback); alexa.APP_ID = APP_ID; ////スキルIDをセットする alexa.registerHandlers(handlers); ////リクエストハンドラーをセットする alexa.execute(); };
※原稿執筆時点で、Alexa Skills Kit SDK for Node.jsのバージョン2(ask-sdk)がリリースされていますが、上述のコード例はバージョン1(alexa-sdk)を用いて実装しています。
順に解説していきましょう。
(1)Alexa Skills Kit SDKを読み込む
Node.jsは、モジュールを読み込んで機能を拡張できるという特徴を持っています。モジュールはrequire()関数を使って読み込みます。ここではAlexa Skills Kit SDKのパッケージに含まれるモジュール「alexa-sdk」を読み込み、「Alexa」という変数名でそのモジュールにアクセスできるようにしています。
(2)APP_IDを定義する
SDKがスキル・インターフェースからの呼び出しに正しく応答できるように、スキルIDをセットする必要があります。スキルIDは開発者コンソールのエンドポイントのページで取得できる文字列で、エントリーポイントとなる関数の中でSDKにセットします。ここでは後から変更しやすいようにプログラム冒頭付近の定数に入れておきます。
(3)Lambda関数ハンドラーを定義する
Lambda関数ハンドラーは以下の形式で定義します。
exports.myHandler = function(event, context, callback) { ... // callback()を呼び出して、呼び出し元に結果を通知します };
パラメーター | 説明 |
---|---|
event | AWS Lambdaからイベントデータが渡される |
context | AWS Lambdaから、実行中のLambda関数のランタイム情報が渡される |
callback | 呼び出し元に情報を返すために使用する。このパラメーターは省略可 |
関数名「myHandler」は自由に決めることができますが、この関数名をLambdaの編集画面にある関数コードセクションの「ハンドラー」に設定する必要があります。設定は<拡張子jsを除いたファイル名>.<関数名>の形式で行いますので、リスト1のコード例では下の図のようになります。
ハンドラーの中で行うことは次の通りです。
- Alexa Skills Kit SDKモジュールのhandler()関数を呼び出して、スキルの実装に必要なオブジェクトを取得します
- 取得したオブジェクトにスキルIDをセットします
- 同様に、取得したオブジェクトにリクエストハンドラーをセットします
- 最後に、execute()関数を呼び出します。この操作により、Alexa Skills Kit SDKがスキル・インターフェースからの要求を処理し、結果を呼び出し元に返します
リクエストハンドラーの構造
リクエストハンドラーは、スキル・インターフェースからの呼び出しに応答する処理を実装した関数群です。
Lambda関数ハンドラーを定義したら、次にスキル・サービスからの呼び出しに応じて実行される関数であるリクエストハンドラーを以下の形式で定義します。
const handlers = { 'LaunchRequest': function () { this.emit(':responseReady'); }, ... };
このように、「LaunchRequest」などスキル・サービスからのリクエストと、それに対応する関数をハッシュ形式で定義します。スキル・サービスは、スキル・インターフェースから送られる、次の3種類のリクエストに応答する必要があります。
- LaunchRequest
- IntentRequest
- SessionEndReques
そのうちIntentRequestに関しては、実際のインテント名をハンドラーの名称(ハッシュのキー)とします。
定義した内容は「handlers」という定数で参照できるようにしておきます。このハッシュ値を、エントリーポイント内の以下の一文でAlexa Skills Kit SDKに渡します。
alexa.registerHandlers(handlers);
代表的なハンドラーの一覧を、以下に示します。
ハンドラー | 役割 |
---|---|
LaunchRequest | 「~を開いて」などの発話によって、このスキルがインテントの指定無しに呼び出された時の動作を定義する |
SessionEndRequest | コードで明示的に終了させた場合以外の理由でセッションが終了した場合の動作を定義する |
AMAZON.HelpIntent | 「ヘルプ」などの発話で呼び出される標準インテントの動作を定義する。使い方についての説明を返答するのが良い |
AMAZON.CancelIntent | 「取り消し」などの発話で呼び出される標準インテントの動作を定義する。現在のタスクを取り消す処理を入れるか、それがない場合にはAMAZON.StopIntentの定義と同じにしても良い |
AMAZON.StopIntent | 「ストップ」などの発話で呼び出される標準インテントの動作を定義する。スキルを完全に終了させる処理を入れるのが良い |
<自分で定義したインテント名> | インテントに対応した処理を定義する |
この表に示した以外にもいくつかの標準インテントがあり、必要に応じてハンドラーを実装ます。利用できる標準インテントについては、以下のURL参照ください。
標準インテント:
https://developer.amazon.com/ja/docs/custom-skills/standard-built-in-intents.html
リクエストハンドラーを実装する
リクエストハンドラーでは任意の処理を行うことができますが、最低限リクエストの内容に応じた返答を用意して、スキル・インターフェースに返す必要があります。返答内容は、thisオブジェクトを通じてアクセスできるresponseオブジェクトの関数を呼び出してセットします。返答のパターンは、下記を組み合わせたものになります。
(1)Alexaデバイスがユーザーに対して応答する際の発話内容
以下の例のように、speak()関数に返答内容の文字列を渡します。
this.response.speak('このスキルは〇〇を行うスキルです');
(2)ユーザーに尋ね返す必要がある場合に、その質問の発話内容(プロンプト)
listen()関数に質問の文字列を渡します。
this.response.listen('何について調べますか');
(3)Alexaアプリに表示するカード情報
cardRender()関数にタイトルと内容を渡します。
this.response.cardRender('イベント情報スキル','○月○日開催のイベントは~です');
(4)応答後にセッションを終了するかどうか
shouldEndSession()関数にbool値を渡すことで制御できますが、他のresponse関数が自動的にセットしますので特に意識する必要はありません。既定値はtrue(応答後にセッションを終了する)となっていますが、例えばlisten()関数を呼び出すとfalseにセットされます。
This.response.shoudEndSession(false);
これらの応答は、以下のように続けて書くこともできます。
this.response.speak('イベント情報スキルです').listen('何について調べますか');
応答内容の準備ができたら、emit()関数を呼び出してSDKオブジェクトに通知します。通常は、これがリクエストハンドラー内で行う最後の処理となります。
this.emit(':responseReady');
スキル・サービスのプログラム構造が理解できたところで、次回以降はより高度な処理に取り組んでいきたいと思います。お楽しみに。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- Alexaのスキルを作ってみよう
- スロットを使って任意の入力を受け付けよう
- CloudサービスとRPAの連携
- Fabric SDK(Software Development Kit)を用いてNode.jsからchaincodeを呼び出す
- LINE、開発者向けカンファレンスでスマートスピーカーWAVEを実現するAI、Clovaの概要などを解説
- サーバーレスな事例が次々登場―ServerlessConf Tokyo 2016レポート
- APIを利用したownCloudの活用方法
- 生まれ変わったJavaScript/ECMAScript
- expressで開発したWebアプリをeXcaleで動かす
- マイクロサービスを連携してみよう