Create "Hello World" Alexa Skill

最近 Amazon Echo が家に届いたので使い始めています。家族も音楽を流したりニュースを聞いたり、ラジオを聞くのに利用しているようです。

Echo と Alexa カスタムスキル

Echo は Amazon のスマートスピーカーで、 Amazon の開発している AI(Alexa) を呼び出して任意の命令を発行することが出来ます。

命令は Alexa においてはスキルと呼ばれていて、様々なスキルがあり(音楽再生、ニュース読み上げ、 TODO リスト等)、ユーザーが独自にスキルを開発することも可能です。ユーザーが独自に開発したスキルはカスタムスキルと呼ばれます。

カスタムスキル開発はチュートリアルが用意されており、チュートリアルの通りに進めれば(多少スクショと実際の画面に差異があったりもしますが)簡単にカスタムスキルを試すことができます。

チュートリアル第一回ではスキルを追加して管理画面上のテストまで行うところで終わっていますが、実機で実際に試す方法は下記の記事の「実機でのテスト」の項が参考になりました。

チュートリアル以外のまとまった資料としては ASK(Alexa Skills Kit) のドキュメントがあります。 👀

この記事でやること

全てを理解するには私の気持ちが追いつかないので(早く何か自分で実装したい)、この記事では以下のこと行う最低限の要点に絞って整理していきます。

  • 「Alexa、 実験スキルでハローワールドを実行して」と話しかけると「ハローワールド」と返答するスキルを作る
  • Lambda で行った処理を Alexa に渡すやり方を把握する

上を満たすには、チュートリアルの第一回、第二回と ASK のドキュメントを併せて読んでいけばよさそうです。

ハローワールドスキルの作成: Alexa の設定編

ここから新しいスキルを追加します。

ハローワールドするために最低限必要な Alexa の設定は以下。

スキル情報タブ

  • 言語: Japanese
  • スキル名: HelloWorld (管理画面上の名前)
  • 呼び出し名: 実験スキル ( 「 Alexa、 実験スキルでハローワールドを実行して」の呼び出し方の定義)

呼び出し名は意外に重要です。要件が多くて、なかなかうまく認識してくれなかったりします。 適当に「ハローワールドの実行」などとすると認識してくれなかったです。

この辺をちゃんと読んでおくと良いです。

「ハローワールドの実行」という呼び名がだめな理由は上のドキュメントを見るに、恐らく

  • 呼び出し名に、Alexaスキルの起動フレーズ(「を起動して」、「をスタートして」、「を実行して」など)とつなぎの語(「で」など)を含めることはできません

に該当しているからだと思います。もしくはハローワールド自体一般的な単語ではないからという理由もあるかも…。

あと

  • 1語の呼び出し名は許可されません。

もけっこう罠だと思います。

対話モデルタブ

  • インテントスキーマ:
{
  "intents": [
    {
      "intent": "HelloWorldIntent"
    },
    {
      "intent": "AMAZON.HelpIntent"
    },
    {
      "intent": "AMAZON.StopIntent"
    },
    {
      "intent": "AMAZON.CancelIntent"
    }
  ]
}
  • サンプル発話:
HelloWorldIntent ハローワールドを言って
HelloWorldIntent ハローワールドを実行
HelloWorldIntent ハローワールドを返して
HelloWorldIntent ハローワールドをスタート
HelloWorldIntent ハローワールドを教えて
HelloWorldIntent ハローワールドを答えて
HelloWorldIntent ハローワールドを知りたい

サンプル発話も重要。

インテント名( HelloWorldIntent )をサンプル発話に含める必要があるのが肝。今回スロット(変数的なやつ)はハローワールドには必要ないので無視します。

例えば、都市の天気を返すスキルの「アレクサ、天気予報で東京の天気を教えて」という発話を考えてみましょう。対話モデルでは例文としてサンプル発話を設定し、例えば「WeatherIntent {City}の天気を教えて」と表します。インテント名(WeatherIntent)やスロット名(City)をサンプル発話に含めているのがポイントです。では、それぞれについて詳しく見ていきましょう。

Alexaスキル開発トレーニングシリーズ 第2回 対話モデルとAlexa SDK : Alexa Blogs

インテントはユーザーの意図や要望を表します。今回の場合は「ハローワールドを聞きたい」「ハローワールドを実行して欲しい」というのがユーザーの意図になります。

AMAZON.HelpIntent などは標準で用意されているインテントです。ヘルプの呼び出しや終了処理など、一般的なインテントはビルトインインテントとして用意されています。

サンプル発話でユーザーの発話を適切なインテントに紐付けています。 なるべく多くのサンプルがあると精度が上がるみたいです(日本語は特に言い回しがたくさんあるので…)。

設定タブ

  • エンドポイント: AWS Lambda の ARN (Amazonリソースネーム)にチェック
  • デフォルト: Lambda 関数の ARN を指定 ( Lambda のダッシュボードから確認できる)

公開情報タブ

Alexa のスキルページを表示したときに見れる情報。

キーワード以外は全て埋める必要があります。

プライバシーとコンプライアンスタブ

スキルを使って何かを購入できるかなどの設定。

13未満の子供を対象にすると、実機でのテストができないので注意。

ハローワールドスキルの作成: Lambda 関数の作成編

Alexa からインテントを受け取ったり、 Alexa へ結果を渡すための SDK が用意されています。公式で提供されているものは今のところ Node.js だけっぽい。

SDK を含む Lambda のブループリントを使えば楽なので( Web 管理画面で完結する)それを使います。

  • Name: HelloWorld
  • Role: 既存のロール or 新規ロールで lambda_basic_execution を選択

トリガーに Alexa Skills Kit を追加し、新規トリガーの追加をします。

index.js の中身を全て消して、ハローワールドを返すコードに書き換えます。

"use strict";
const Alexa = require('alexa-sdk'); // Alexa SDKの読み込み

exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);

    // Alexa SDKの処理
    alexa.registerHandlers(handlers);
    alexa.execute();
};

// ハンドラの定義
var handlers = {
    // インテントに紐付かないリクエスト
    'LaunchRequest': function () {
        this.emit('AMAZON.HelpIntent'); // AMAZON.HelpIntentの呼び出し
    },

    // スキルの使い方を尋ねるインテント
    'AMAZON.HelpIntent': function () {
        this.emit(':tell', 'ハローワールドを返します');
    },

    // 対話モデルで定義した、ハローワールドを実行するインテント
    'HelloWorldIntent': function () {
        this.emit(':tell', 'ハローワールド');
    }
};
  • Alexa SDKの処理 の部分で appID を指定することができて、特定のスキルからの呼び出しにのみ応じさせることができる
    • 必須ではないが、スキルを公開するなら指定しておくのが良い

  • this.emit がユーザーに返答する音声を定義するメソッド
  • appID を指定している場合で Lambda からテスト( Alexa Start Session )を実行する場合は、 applicationIdalexa.appId で指定したものに書き換える必要があるので注意

ハローワールドスキルの作成: 実機に登録編

以下を参照。

ハローワールドスキルの作成: スキルの実行編

今回のスキルは、以下のようにして呼び出せます。

「Alexa、実験スキルでハローワールドを実行して。」

なぜこのような回りくどい言い方なのかというと、言い回しも以下のドキュメントにあるようにある程度決まっているからです(例: 「<呼び出し名> で <アクション> を開始して」)。

自然な言い回しでスキルを呼び出すには、スキルの呼び出し名やサンプル発話の要件を理解してうまく定義する必要があります。

コツとか

  • 呼び出し名やサンプル発話を何度もいじるより、スキルを作り直したほうが良い場合がある
    • よくわかりませんが最終的な成果物が全く同じにも関わらず、調整を繰り返したものと作り直したものでは結果が異なりました
    • そして作り直した方が良い結果(期待した結果)を得られる場合が多かったです
  • 一度実機に登録したあとでも、登録し直す必要なく呼び出し名や Lambda ファンクションを変更できる
    • 楽ちん!ただし正式にスキル公開した場合はできません(当たり前っちゃ当たり前)
  • デバッグ方法として、 Echo の管理画面から発話の内容を取れる
    • 取れない場合もあるので条件がよくわからない…
    • 音声も記録される場合があるのでだいぶすごいw
    • もし恥ずかしいことを言っていたら… 😱

まとめ

最低限のことをやると言いつつ、結構苦戦した…。呼び出し名とサンプル発話の理解と設計がめちゃくちゃ重要。

逆に言えばそこさえできれば楽だと思います。

今回は決まった発話に対して決まった結果を返すだけでしたが、スロットを使うともっと複雑な発話に対応できたり、クイズのように結果に対してさらにユーザーからの入力を求めるようなことも出来るので、夢が広がりング!

しかし今のところ Node.js しか正式対応していないので Node.js が書けないとだめ。夢がしょんぼりング!!

参考リンク

チュートリアル。

ASK ドキュメント。

事例。