Alexaのスキルを作ってみよう

2018年7月10日(火)
畠中 幸司(はたなか・こうじ)
音声での質問に応えてくれるAmazon Echo/Echo Dotで利用できる音声サービス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の取得

JSONエディタ

スキルIDを取得する

最後にこのスキルを一意に識別するための「スキルID」を取得しておきましょう。画面左の「エンドポイント」メニューをクリックします。

スキルIDは「エンドポイント」の画面に「amzn1.ask.skill.…」で始まる形式で表示されていますので、これをコピーして、テキストエディターなどに貼り付けて保存しておきましょう。AWS Lambda関数を作成する際に、この文字列が必要になります。

エンドポイント

エンドポイント

これで、最も基本的なスキル・インターフェースの実装が終わりました。次にスキル・サービスの実装に移ります。この作業はAWSにログインして行います。

Lambda関数を作成する

AWSのコンソールにログインして、AWSサービスの一覧から「Lambda」をクリックします。検索欄に「Lambda」と入力するとすばやくサービスにたどりつけます

Lambda関数の画面

Lambda関数の画面

AWS Lambdaの初期画面は下図のようになっています。さっそく「関数の作成」をクリックしましょう。

Lambda関数の作成

Lambda関数の作成

関数の作成」画面では、「設計図」をクリックします。画面の下半分に設計図(関数のひな型)の一覧が表示されますので、画面をスクロールさせて「alexa-skill-kit-sdk-factskill」を探します。

Labmda関数のテンプレート

Labmda関数のテンプレート

alexa-skill-kit-sdk-factskill」が見つかったらクリックし、さらに画面を一番下にスクロールさせて右下の「設定」をクリックします。

alexa-skill-kit-sdk-factskill

alexa-skill-kit-sdk-factskill

基本的な情報」ページに切り替わったら、「名前」の欄に作成する関数の名称を入力します。ここでは「visitorCountSkill」とし、「ロール名」には「myRole」と入力します。そのまま画面を下にスクロールさせて、「Lambda関数のコード」と書かれたセクションを表示させます。

基本情報の入力

基本情報の入力

ページの一番下にある「関数の作成」をクリックします。この操作でLambda関数が作成され、関数の編集ページに切り替わります。

Lambda関数を編集する

Designer」と書かれたセクションの「トリガーの追加」メニューから「Alexa Skills Kit」をクリックします。Designerセクションの内容が表示されていない場合は、「Designer」の文字列を一度クリックすると表示されます。下の画面のような表示になったら、再びページを一番下にスクロールさせます。

トリガーの追加

トリガーの追加

スキルID」欄に先ほど取得したスキルIDの文字列を入力しして「追加」をクリックします。追加したら、ページ右上の「保存」をクリックします。

トリガーの追加(関数コード)

トリガーの追加(スキルIDの設定)

保存が終わったら、ページ左上の「関数」と書かれたリンクをクリックして、いったん関数の一覧に移動します。次に「visitorCountSkill」をクリックして再び編集画面を表示させます。さらに、再度画面を下の方にスクロールさせて「関数コード」と書かれたセクションを表示させます。

関数の保存

関数コード

関数コード画面で「index.js」を選択し、右側の編集エリア内のコードを、コード例1のように書き換えます。このとき、「const APP_ID =‘amzn1.ask.skill.b6030ab0-…’;」のシングルクォーテーションで囲まれた内容には、先ほど取得したスキルIDの文字列を入力します。

リスト1:コード例1: code1/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('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の処理に動作を引き継ぎます。

リスト2:LaunchRequest

’LaunchRequest’: function () {

    this.emit(’VisitorCountIntent’);
},

(3)VisitorCountIntent のハンドラー

今回定義した、VisitorCountIntentインテントが呼び出された場合に行う処理を定義します。visitorCount定数を使って返答内容を生成し、それをthis.response.speak()に渡すことで、Alexaがその通り発話します。this.response.cardRenderer()にも渡していますが、これによりAlexaアプリ(Alexaの初期設定等に使用するスマートフォンアプリ)の画面にも結果を送ることができます。返答処理が完了し、再びリクエストを受け付けられるようにするのが「this.emit(’:responseReady’);」の役割です。

リスト3:VisitorCountIntent

’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つのインテント

アレクサ、来場者カウントで欠席者数を教えて

に答えるための設定画面とコード例を掲載しておきます。ご自身で追加して、うまく動作するか試してみてください。それでは次回をお楽しみに!

インテント/ AbsenteeCountintentの設定

インテント/ AbsenteeCountintentの設定

リスト4:コード例2: code2/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 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();
};
著者
畠中 幸司(はたなか・こうじ)

音楽と自然と猫を愛するソフトウェア&インフラエンジニア。日本ヒューレット・パッカード株式会社でクラウドネイティブなアプリケーションのためのインフラ提案、および構築業務に従事。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メルマガ会員のサービス内容を見る

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