アルパカログ

Webエンジニア兼マネージャーがプログラミングやマネジメント、読んだ本のまとめを中心に書いてます。

アレクサを喋らせる「Alexaスキル」作り方解説(Amazon Echo)

f:id:otoyo0122:20200909110314p:plain:w300

アレクサを喋らせるには「スキル」を作成する必要がある。

スキルの作成は意外とハマり箇所が多い。

このエントリでは、アレクサスキルを作成してアレクサ(Amazon Echo)を自由に喋らせる方法を説明する(※)。

※注意: 第1世代Echo Dot発売時点の情報なので注意

アレクサスキルの仕組み

アレクサスキルを作り始める前に、スキルがどんな仕組みで動いているのか説明する。

Echoに話しかけると発話情報はアレクサに送られ、アレクサからイベント情報がAWS Lambdaに送られる。

f:id:otoyo0122:20180220134442p:plain:w600

スキルを開発するにあたってやるべきことは大きく分けて次の2つになる。

  1. Alexa Developer Console で対話モデルを作成する
  2. Lambda関数を作成しスピーチテキストを返す

対話モデル作成、Lambda関数作成の順に説明する。

対話モデルの作成

対話モデルというと難しく聞こえるが、Alexa Developer Consoleの指示を順にこなしていくだけでいい。

まずは Alexa Developer Console にログインする。

「Alexa Skills Kit」を選択しスキルの作成を開始しよう。

f:id:otoyo0122:20180220190830p:plain:w320

スキル情報の設定

f:id:otoyo0122:20180220191141p:plain:w480

スキルの情報を適当に入力していく。迷う場合は下の表を参考にしてほしい。

入力したら保存して次に進む。

項目
スキルの種類 カスタム対話モデル
言語 Japanese
スキル名 おじいさんのキャンディ
呼び出し名 おじいさんのキャンディー

対話モデル

対話モデルへ進むと「Skill Builder」が立ち上がるので、左カラム「Intents」横の「ADD+」を選択する。

インテント名を適当に入力して作成しよう。

f:id:otoyo0122:20180220192540p:plain:w480

次にインテントにサンプル発話を登録する。話しかけそうなテキストを適当に入力しておく。

f:id:otoyo0122:20180220192847p:plain:w480

インテントとは、対話モデルに解釈させたいユーザーの意図のことで、ここで解釈された意図が後ほどLambdaに送られる。

インテントにはAlexa Skills Kitのデフォルトで用意されているものもあり、例えば「会話を中断したい」や「使い方が知りたい」といったものがある。

スキルの作成は以上だが、Lambda側に取り掛かる前にスキルIDを確認しておこう。

サンプル発話を入力したら、上部ナビゲーションバーの「Configuration」から次に進む。

f:id:otoyo0122:20180220193436p:plain:w240

スキルIDはスキル一覧から確認することができる。

あとで必要になるのでメモしておこう。

amzn1.ask.skill.xxxがスキル ID だ。

f:id:otoyo0122:20180220194032p:plain:w320

次にLamda関数の作成に移るが、この画面は後で使うので閉じずに残しておこう。

Lambda関数の作成

AWSマネジメントコンソール にログインし、Lambda関数を新規作成する。

「設計図」を選び、検索フィルターに "alexa" と入力する。

フィルターされた「alexa-skill-kit-sdk-factskill」を選択する。

f:id:otoyo0122:20180220135744p:plain:w600

関数名を適当に入力する。例ではgetWerthersOriginalとしている。

ロールはmyAlexaとしておく。

f:id:otoyo0122:20180220135936p:plain:w600

Alexa Skills Kit トリガーの追加

「左側のリストからトリガーを追加します」を選択する。

左側にトリガーの一覧が出てくるので「Alexa Skills Kit」を選択する。

f:id:otoyo0122:20180220140230p:plain:w600

そのまま画面を下にスクロールするとAlexa Skills Kitの設定項目がある。

スキルID欄に先ほど確認したスキルIDを入力して追加しよう。

f:id:otoyo0122:20180220140404p:plain:w600

関数コードの設定

スクロールして上に戻り、先ほど作成したLambda関数を選択しよう。この例ではgetWerthersOriginalになっている。

Alexa Skills Kitの設定欄がコード編集画面に変わるので、下記のサンプルコードを例にトークスクリプトを入力しよう。

サンプルコード内で変更すべき箇所は以下の通りだ。

  • APP_IDを自分のスキルIDに変更する
  • translation内のトークスクリプトを自分なりに入力する
  • WerthersOriginalIntentを自分で設定したインテント名に置き換える
'use strict';

const Alexa = require('alexa-sdk');

const APP_ID = 'amzn1.ask.skill.xxx';  // TODO replace with your app ID (OPTIONAL).

const languageStrings = {
    'ja': {
        translation: {
            TALKSCRIPTS: [
                '私のおじいさんがくれた初めてのキャンディ。',
                'それはヴェルタースオリジナルで私は四歳でした。',
                'その味は甘くてクリーミィで、',
                'こんな素晴らしいキャンディをもらえる私は、',
                'きっと特別な存在なのだと感じました。',
                '今では私がおじいさん。',
                '孫にあげるのはもちろんヴェルタースオリジナル。',
                'なぜなら彼もまた、特別な存在だからです。',
            ],
            SKILL_NAME: 'おじいさんのキャンディ',
            HELP_MESSAGE: 'おじいさんのキャンディと言うと、おじいさんのセリフが聞けます。',
            HELP_REPROMPT: 'おじいさんのキャンディを聞きますか',
            STOP_MESSAGE: 'わかりました。',
        },
    },
};

const handlers = {
    'LaunchRequest': function () {
        this.emitWithState('WerthersOriginalIntent');
    },
    'IntentRequest': function () {
        if (this.event.request.intent.name === 'WerthersOriginalIntent') {
            this.emitWithState('WerthersOriginalIntent');
        }
    },
    'WerthersOriginalIntent': function () {
        const talkscripts = this.t('TALKSCRIPTS');

        // Create speech output
        const speechOutput = talkscripts.join('');
        this.emit(':tellWithCard', speechOutput, this.t('SKILL_NAME'), speechOutput);
    },
    'AMAZON.HelpIntent': function () {
        const speechOutput = this.t('HELP_MESSAGE');
        const reprompt = this.t('HELP_MESSAGE');
        this.emit(':ask', speechOutput, reprompt);
    },
    'AMAZON.CancelIntent': function () {
        this.emit(':tell', this.t('STOP_MESSAGE'));
    },
    'AMAZON.StopIntent': function () {
        this.emit(':tell', this.t('STOP_MESSAGE'));
    },
};

exports.handler = function (event, context) {
    const alexa = Alexa.handler(event, context);
    alexa.appId = APP_ID;
    // To enable string internationalization (i18n) features, set a resources object.
    alexa.resources = languageStrings;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

アレクサはユーザの音声を受け取るとLaunchRequestIntentRequestのどちらかをLambdaに送る。

LaunchRequestは「アレクサ、<スキル名>を開いて」と呼び出したときにトリガーされる。

IntentRequestは対話モデルで定義したインテントに対応する呼び出しを行ったときにトリガーされる。

ちなみに、上のサンプルコードでは大丈夫だがLambdaの初期状態のコードでは下記のようなエラーとなる。

"errorMessage": "Invalid ApplicationId: amzn1.ask.skill.XXXXXXX"

これはalexa.APP_ID = APP_ID;の箇所が誤りで、alexa.appId = APP_ID;にすると解決する。

Lambda側の設定は以上となる。

画面右上に表示されている「ARN」をメモしておく。

f:id:otoyo0122:20180220195332p:plain:w600

保存したらAlexa Developer Consoleに戻ろう。

設定と公開情報

サービスエンドポイントのタイプとして「AWS Lambda の ARN」を選択し、テキストフィールドに先ほどメモした ARN を入力しよう。

f:id:otoyo0122:20180220195632p:plain

テストはスキップし、公開情報は適当に埋めつつ進もう。

途中スキルアイコンの設定がある。

スキルアイコンの設定

スキルアイコンの画像 (108*108px と 512*512px) を設定する必要がある。

f:id:otoyo0122:20180220195935p:plain:w320

開発バージョンなんだからそのまま使わせてくれよと思うが、あと少しなので頑張ろう。

Mac ユーザの場合、画像サイズの編集には sips コマンドが便利だ。

長方形の画像から 512px 四方の画像を作るには、短辺が 512px になるように拡大・縮小しクロップ (切り抜き) すれば良い。

例えば横長の画像では、短辺となる縦が 512px になるよう拡大・縮小する。

sips --resampleHeight 512 inputfile --out resampled_file

512px 四方でクロップする。

sips --cropToHeightWidth 512 512 resampled_file --out cropped_file

スキルの実機テスト

いよいよ実機にスキルをインストールして動かしてみよう。

ここまでで全ての手順に ✅マークが付いているはずだ。

f:id:otoyo0122:20180220200012p:plain:w160

もしまだ ✅が付いていない手順があれば戻って確認しよう。「テスト管理」からβテストができる。

f:id:otoyo0122:20180220200107p:plain:w480

自分のメールアドレスを入力してβテストの招待メールを送ろう。

招待メール内にスキルをインストールするためのリンクがあるので、アレクサと連携した端末で開きスキルを有効化しよう。

f:id:otoyo0122:20180220200134p:plain:w240

スキルのインストールが完了した画面だ (iPhone)。

話しかけてみる

「アレクサ、(スキル名)を開いて」と話しかけてみよう。

この例だと「アレクサ、おじいさんのキャンディを開いて」となる。

セリフが始まったら成功だ。

アレクサスキルの作り方は以上だ。

参考になった方は、ぜひ「はてブ」やSNSでシェアしていただけると幸いだ。

お詫びと訂正

  • IntentRequestによる呼び出しコードを修正しました (2018/2/21)

参考リンク

アレクサに買い物リストを連携する方法を知る

アレクサに買い物リストを連携する方法を知りたい方は下記の記事が参考になるだろう。

alpacat.hatenablog.com