Alexa Skills Kit SDK for Node.jsについて知る

2018年8月21日(火)
畠中 幸司(はたなか・こうじ)
連載4回目は、スキル・サービス側のコードに着目して、フレームワークの理解を深めていきます。

こんにちは。

これまでの回を通して、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の配布場所:

スキル・インターフェースからのリクエスト

スキル・サービスは、スキル・インターフェースからの各種リクエストに応答するサーバープログラムです。カスタムスキルを実装する場合に、サービスが応答しなければならないリクエストは次の3種類です。

  • LaunchRequest
  • IntentRequest
  • SessionEndRequest

以下、それぞれのリクエストについて概略を見ていきましょう。

LaunchRequest

ユーザーは「~を開いて」のように発話することで、呼び出し名のみでスキルを呼び出すことができます。この場合、スキル・サービスはLaunchRequestを受け取ります。ユーザーは機能(インテント)やそれに付随する情報(スロットの値)を指定していいないため、このリクエストを受け取ったサービスは既定の動作を行います。もしユーザーから追加の情報を得たい場合は、Alexaがそれを尋ねるようにもできます。

つまり、ユーザーが以前にこのスキルを使用した際の情報を覚えておくような仕組みを実装すれば、それに基づいて適切な応答をすることもできます。このような仕組みは、Amazon Dynamo DBのようなデータベースサービスを用いて実装できます。

IntentRequest

Alexa、~で~して」というように、ユーザーがインテントを指定してスキルを呼び出すと、スキル・サービスはIntentRequestを受け取ります。このリクエストには、呼び出されたインテント名が含まれるほか、スロットがある場合にはスロット値も含まれます。サービスはこれらの情報に基づいて処理を行い、スキル・インターフェースに応答します。

SessionEndRequest

スキルが次のいずれかの理由で閉じられると、スキル・サービスはSessionEndRequestを受け取ります。

  • ユーザーが「終了して」と発話した場合
  • ユーザーが応答しなかった場合や、ユーザーの応答に対応するインテントが見つからなかった場合
  • 何らかのエラーが発生した場合

スキル・サービスプログラムの構造

これまで扱ってきたスキル・サービスの構造について、より詳しく見ていきます。

Lambda関数ハンドラーを定義する

AWS Lambdaはハンドラーオブジェクトを介して関数を呼び出します。つまり、ハンドラーオブジェクトが指す関数が、プログラムコードの中で最初に実行される処理(エントリーポイント)となります。ここでは、index.jsというファイルでLambda関数ハンドラーを定義します。

リスト1:コード例:index.js

// (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関数ハンドラーは以下の形式で定義します。

リスト2:Lambda関数ハンドラーを定義する際の形式

exports.myHandler = function(event, context, callback) {

   ...

   // callback()を呼び出して、呼び出し元に結果を通知します
};

パラメーターの説明

パラメーター説明
eventAWS Lambdaからイベントデータが渡される
contextAWS Lambdaから、実行中のLambda関数のランタイム情報が渡される
callback呼び出し元に情報を返すために使用する。このパラメーターは省略可

関数名「myHandler」は自由に決めることができますが、この関数名をLambdaの編集画面にある関数コードセクションの「ハンドラー」に設定する必要があります。設定は<拡張子jsを除いたファイル名>.<関数名>の形式で行いますので、リスト1のコード例では下の図のようになります。

ハンドラー

ハンドラー

ハンドラーの中で行うことは次の通りです。

  1. Alexa Skills Kit SDKモジュールのhandler()関数を呼び出して、スキルの実装に必要なオブジェクトを取得します
  2. 取得したオブジェクトにスキルIDをセットします
  3. 同様に、取得したオブジェクトにリクエストハンドラーをセットします
  4. 最後に、execute()関数を呼び出します。この操作により、Alexa Skills Kit SDKがスキル・インターフェースからの要求を処理し、結果を呼び出し元に返します

リクエストハンドラーの構造

リクエストハンドラーは、スキル・インターフェースからの呼び出しに応答する処理を実装した関数群です。

Lambda関数ハンドラーを定義したら、次にスキル・サービスからの呼び出しに応じて実行される関数であるリクエストハンドラーを以下の形式で定義します。

リスト3:リクエストハンドラーの定義

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');

スキル・サービスのプログラム構造が理解できたところで、次回以降はより高度な処理に取り組んでいきたいと思います。お楽しみに。

著者
畠中 幸司(はたなか・こうじ)

音楽と自然と猫を愛するソフトウェア&インフラエンジニア。日本ヒューレット・パッカード株式会社でクラウドネイティブなアプリケーションのためのインフラ提案、および構築業務に従事。2000年にウェブスタートアップでエンジニアとしてのキャリアをスタートして以来、メガソフト株式会社の3Dマイホームデザイナーシリーズの開発や、マイクロソフト日本法人にて Windows Phone、Microsoft Officeシリーズの開発など、数多くの国内およびグローバルな開発プロジェクトに携わる。建設業向けモバイルアプリSTUCCO(スタッコ)のスタートアップ起業経験、500 KOBE Pre-Acceleratorへの参加等を経て2017年より現職。

連載バックナンバー

開発ツール技術解説
第6回

Alexa:ステートフルなサービスと聞き取りやすい音声応答

2018/9/20
連載6回目は、ステートフルなサービスの構築と、Alexaの音声応答を聞き取りやすくする手法を紹介します。
開発ツール技術解説
第5回

Alexaのためのローカル開発環境を整備する

2018/9/4
連載5回目は、より高度なプログラム作成に先駆けて、Alexaのためのローカル開発環境を整備していきます
開発ツール技術解説
第4回

Alexa Skills Kit SDK for Node.jsについて知る

2018/8/21
連載4回目は、スキル・サービス側のコードに着目して、フレームワークの理解を深めていきます。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています