Amazon Alexaプログラミング入門 2

Alexaとの複数回に渡るやりとり(ダイアログ)

Alexaとの複数回に渡るやりとり(ダイアログ)

ダイアログとは

Alexa Skills Kitにおけるダイアログとは、ユーザーによる一度の発話では収集しきれない情報を、何度かのやりとりを通じて得る方法です。このやりとりの間、収集途中の情報などを覚えておく、いわゆる状態管理を行う必要がありますが、これはスキル・インターフェース側でやってくれます。したがって、AWS Lambdaを使ったプログラム・コードでは、パラメーターとして渡されてくる情報に基づいて処理をすればよく、簡単に期待する動作結果を得られます。スキル・インターフェースとスキル・サービスの間の、ダイアログに関する動作の流れは次のようになっています。

スキル・インターフェースとスキル・サービスの間の情報のやりとり

スキル・インターフェースとスキル・サービスの間の情報のやりとり

一連の会話である「ダイアログ」が開始すると、「STARTED」というダイアログの状態コードがスキル・サービスに渡されます。このとき、スキル・サービスは、ダイアログの続きをスキル・インターフェースに委ねるために「Delegate」という返答をするとともに、スロットの既定の値をスキル・インターフェースに返すことができます。ダイアログの途中、まだ情報収集が完了していない間は「IN_PROGRESS」という状態コードが渡されます。このとき、スキル・サービスは単に「Delegate」と返答するだけで構いません。

ダイアログが完了すると「COMPLETED」という状態コードが渡されるため、スキル・サービスはスロットの値がそろっていることを期待して、処理を進めることができます。

ダイアログを追加する

開発者コンソールを開き、スキル編集画面の左メニューから「eventName」のスロット名をクリックすると、eventNameスロットの詳細を設定するページが開きます。イベント名を必須項目とするため、「このインテントを完了させるために、このスロットは必須ですか?」を選択します。

Alexaの音声プロンプト」の欄には以下の内容を入力して[Enter]を押します。

    どのイベントについて調べますか

イベント名を伝えずに来場者数を尋ねた場合に、Alexaはここに入力した言葉を使ってイベント名を聞き返します。

ユーザーの発話」欄には、以下のように入力して[Enter]を押します。

    {eventName}です
    {eventCity}で開催の{eventName}です

こちらは、上記の音声プロンプトに対するユーザーの返答例となります。設定が完了したら保存とビルドを忘れずに行いましょう。

スロット入力

スロット入力

スキル・サービスをダイアログに対応させる

さっそくコード例を示します。

リスト3:コード例2:code2-2/index.js

'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(':responseReady');
    },
    'VisitorCountIntent': function () {
        // VisitorCountIntent に対応して呼び出される

        if (this.event.request.dialogState === 'STARTED') {
            // インテントObjectを取得する
            let updatedIntent = this.event.request.intent;

            // スロットの初期値をセットする
            updatedIntent.slots.eventDate.value = '2018-04-03';

            // スキル・インターフェースにダイアログの継続を依頼する
            this.emit(':delegate', updatedIntent); // 初期値あり
        } else if (this.event.request.dialogState !== 'COMPLETED') {
            // スキル・インターフェースにダイアログの継続を依頼する
            this.emit(':delegate');
        } else {
            // インテントObjectを取得する
            let intent = this.event.request.intent;

            // スロットの値を取得する
            var eventCity = intent.slots.eventCity.value;
            var eventName = intent.slots.eventName.value;
            var eventDate = intent.slots.eventDate.value;

            // 結果を生成する
            const speechOutput = eventCity + 'の' + eventName + 'の' + eventDate + 'の来場者数は' + visitorCount + '人です';
            // Alexa アプリで参照できる情報 (カード) を返す
            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');
    },
    'SessionEndedRequest': function () {
        // Do nothing
    },
};

exports.handler = function (event, context, callback) {
    const alexa = Alexa.handler(event, context, callback);
    alexa.APP_ID = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

VisitorCountIntent」を処理するハンドラーの中では、以下のようにダイアログの状態別に処理をしています。

リスト4:ダイアログの状態別の処理

if (this.event.request.dialogState === 'STARTED') {
    〜 STARTEDの場合の処理 〜
} else if (this.event.request.dialogState !== 'COMPLETED') {
    〜 途中(COMPLETED以外)の場合の処理 〜
} else {
    〜 COMPLETEDの場合の処理 〜
}

ダイアログの継続を指示するのは、下記に示した部分になります。

リスト5:ダイアログの継続指示

this.emit(':delegate', updatedIntent); //初期値あり

リスト6:別のダイアログの継続指示

this.emit(':delegate');

参考情報ですが、この連載ではスキル・サービスをAlexa Skills Kit SDK for Node.jsを使って実装しています。同SDKの詳しい説明は、GitHubのページで参照できます(英文)。

https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs

テストしてみましょう。期待通りの結果になりましたか?

スキルのテスト結果

スキルのテスト結果

次回はいよいよ、Amazon Echo、Echo DotなどのAlexa対応デバイスを使ったテストに挑戦します。スキル・サービス側のプログラムも充実させていきますので、ご期待ください。

この記事のキーワード

この記事をシェアしてください

人気記事トップ10

人気記事ランキングをもっと見る