Alexa Skills Kit (ASK) SDK for Node.jsのバージョン2がリリースされました。新しいSDKではより見通しの良いコードを書けるように様々な改善が行われていますので、ぜひお試しください。ASK SDK v2での主な変更点を以下で紹介します。
ASK SDK v1では alexa-sdk
だったSDKのパッケージ名が ask-sdk
に変更されました。 ask-sdk
パッケージはモジュール化されており、DynamoDBを使ったデータ永続化のような拡張機能を利用しない場合、 ask-sdk-core
および ask-sdk-model
というパッケージのみを利用することでプログラムが利用するSDKのサイズを小さく最適化することができます。
ASK SDK v1ではインテントとその処理を1対1に定義していましたが、ASK SDK v2ではリクエストハンドラごとに処理の条件をプログラムで記述することができるようになりました。具体的には下記のコード例のように、 canHandle
という関数の中でそのハンドラが処理すべきリクエストの条件を指定することができます。このコード例の場合には、 LaunchRequest
と HelloWorldIntent
の両方を受け付けるリクエストハンドラを定義しています。リクエストタイプやインテント名、後述するアトリビュートの値等に応じた条件の指定が可能です。
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
// HandlerInput から RequestEnvelope にアクセス
const request = handlerInput.requestEnvelope.request;
return request.type === 'LaunchRequest'
|| (request.type === 'IntentRequest' && request.intent.name === 'HelloWorldIntent');
},
handle(handlerInput) {
const speechText = 'Hello World!';
return handlerInput.responseBuilder // HandlerInput から ResponseBuilder にアクセス
.speak(speechText)
.withSimpleCard('Hello World', speechText)
.getResponse();
}
};
リクエストハンドラの実際の処理は handle
という関数の中で定義します。レスポンスの構築には ResponseBuilder
を利用でき、ASK SDK v1でのレスポンス作成方法と類似のものになっています。詳細はこちらをご確認ください。 ResponseBuilder
は、コード上ではリクエストハンドラの関数に引数として渡される HandlerInput
からアクセスできます。 HandlerInput
からは ResponseBuilder
以外にも、リクエストデータそのものを含む RequestEnvelope
等を利用できます。 HandlerInput
の詳細はこちらをご確認ください。
作成したリクエストハンドラは次のようなコードでスキルビルダに登録して利用します。リクエストハンドラには登録した順番で優先順位が付けられます。例えば以下の例で FooHandler
と BarHandler
がともに特定のインテントリクエストを処理できる場合、先に登録した FooHandler
での処理が優先されて BarHandler
での処理は実行されません。この挙動を利用すると canHandle
で常に true
を返すリクエストハンドラを最後に最も低い優先度で登録することによって、ASK SDK v1に存在した Unhandled
ハンドラのような挙動を実装することができます。
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers( // リクエストハンドラの登録
FooHandler, // 最も優先順位の高いリクエストハンドラ
BarHandler,
HelloWorldIntentHandler,
FallbackHandler) // 最も優先順位の低いリクエストハンドラ
.addRequestInterceptors(FooRequestInterceptor) // リクエストインターセプタの登録
.addResponseInterceptors(BarResponseInterceptor) // レスポンスインターセプタの登録
.addErrorHandlers(ErrorHandler) // エラーハンドラの登録
.withSkillId(skillId) // リクエスト元スキルIDの検証
.lambda(); // Lambda用ハンドラを作成
上記のコードに登場するインターセプタは、リクエストハンドラに対してその処理の前後で実行したい別の処理を差し込むための仕組みです。ハンドラの処理の前に実行されるのがリクエストインターセプタ、後で実行されるのがレスポンスインターセプタとなります。インターセプタの利用は必須ではありませんが、後述のアトリビュートと組み合わせてリクエストハンドラの処理の前後でハンドラが利用するデータを管理するといったことを実現できます。詳細はこちらをご確認ください。
またリクエストハンドラとは別に、リクエストの処理中に発生した例外をキャッチして対応するためのエラーハンドラの仕組みも用意されました。定義方法はリクエストハンドラと類似ですので、こちらから詳細をご確認ください。
最後にハンドラやインターセプタを登録するスキルビルダについては、データ永続化や外部APIへのアクセス方法をカスタムに指定できる CustomSkillBuilder
と、デフォルトのデータ永続化やAPIアクセスを備えた StandardSkillBuilder
の2つが存在します。 StandardSkillBuilder
は ask-sdk
パッケージのみに存在し、 ask-sdk-core
パッケージには存在しません。 StandardSkillBuilder
のコード例は下記の通りです。詳細はこちらをご確認ください。
exports.handler = Alexa.SkillBuilders.standard()
.addRequestHandlers(FooHandler)
.addErrorHandlers(ErrorHandler)
.withTableName('MySkillAttributes') // アトリビュート永続化に利用するDynamoDBテーブル名を指定
.withAutoCreateTable(true) // DynamoDBのテーブルを自動的に作成
.lambda();
リクエストをまたいで変数の値を保持するために、ASK SDK v1ではセッションアトリビュートが用意されていました。ASK SDK v2ではアトリビュートの概念が整理・拡張され、次の3種類が用意されました。
canHandle
で参照して条件判定に使うことで同様の挙動を実現できます。PersistentAdapter
で永続化の実装を指定しますが、 ask-sdk
パッケージに含まれる ask-sdk-dynamodb-persistence-adapter
パッケージではDynamoDBを使った実装があらかじめ提供されています。コード上でアトリビュートの取得・セットを行うには AttributesManager
を利用します。 AttributesManager
は ResponseBuilder
と同様、ハンドラの関数に引数として渡される HandlerInput
からアクセスできます。セッションアトリビュートのコード例は下記の通りで、詳細はこちらをご確認ください。
// セッションアトリビュート
const hoge = handlerInput.attributesManager.getSessionAttributes().hoge;
所在地APIのようなAlexaのAPIをスキルから簡単に利用するためのサービスクライアントが用意されています。サービスクライアントはハンドラの引数である HanderInput
の ServiceClientFactory
からアクセスできます。ただし ServiceClientFactory
を利用するにはスキルビルダに ApiClient
が設定されている必要があるため、設定があらかじめ行われている StandardSkillBuilder
を利用すると追加設定なしに ServiceClientFactory
にアクセスできます。サービスクライアントの詳細はこちらをご確認ください。
既存のコードをASK SDK v2で動かすため、 ask-sdk-v1adapter
というパッケージが用意されています。このパッケージを利用して次の様にコードを書き換えてください。
const Alexa = require('alexa-sdk’);
const Alexa = require('ask-sdk-v1adapter');
また下記の例のように、この状態からASK SDK v1のリクエストハンドラとASK SDK v2のリクエストハンドラを混在して定義・登録することができます。その場合、v1のリクエストハンドラがv2のものよりも優先された状態でリクエストが処理されます。詳細はこちらをご確認ください。
// v1形式でのLambda用ハンドラの定義
exports.handler = function(event, context, callback) {
const alexa = Alexa.handler(event, context);
alexa.registerHandlers(handlers); // v1のリクエストハンドラを登録
alexa.registerV2Handlers(V2RequestHandler); // v2のリクエストハンドラを登録
alexa.execute();
};
以上のように、ASK SDK v2ではスキルのコードをモジュール化して柔軟に組み合わせるための変更が取り入れられました。既存コードからの移行方法も用意されていますので、ASK SDK v2でのスキル開発をぜひお試しください。より詳細なドキュメント・チュートリアル・サンプルコードにつきましてはGitHub上のASK SDK for Node.jsをご確認ください。