the invention of t88

工作、資格取得、データ分析のことなど

アレクサスキル開発を始めてみる

一時は、ピカチュウを呼ぶ機械と化していた
我が家のecho dotも、現在はTVを消したり、
豆芝呼んだり、天気を伝えたり、
それなりに活躍の場を増やしています。
(相変わらずその程度、という見方をしてもいい。)

それはそれとして、
Facebookの広告等で度々目にして
気になっていたのがこのキャンペーン。

スキルを開発して、特典をもらおう | Amazon Alexa | アレクサ

期間中にスキルを作成、公開すると
特製Tシャツが貰えるらしい。

3月くらいからスタートしてましたが、何だかんだ毎月行われていて8月も継続中。

ちょっと欲しい。
マラソン参加賞以外のノベルティTシャツが欲しい。
ということで、試しにアレクサスキルを作ってみようと思います。

f:id:take213uv:20180807011136p:plain
毎月、柄が変わる。8月は犬。いいね

f:id:take213uv:20180807012551p:plain
7月は蛸。蛸なら8月ではと思った。蛸でない別の何かかも。

まずはお試し。公式のトレーニングに沿ってチュートリアルを行う。

Alexaスキル開発トレーニングシリーズ 第1回 初めてのスキル開発 : Alexa Blogs

チュートリアルの内容

宇宙の豆知識を教えてくれるサンプルスキルの作成を通して、スキル開発の一連の流れを学ぶというもの。
このサンプルスキル、仕組みとしては、複数の文字列の候補からランダムで一つ返す、という最も単純なものだと思われる。
単に、全く同じスキルを作るのも少し退屈なので、娘(1)がお気に入りの、今日のわんこを題材にスキルを作成します。

アカウント作成

  • Amazonアカウント
  • Amazon開発者アカウント(注意)
  • AWSアカウント

まずはアカウント作成。
通常のAmazonアカウント以外に
Amazon開発者アカウントとAWSアカウントが必要になります。

但し、開発者アカウントは、新規に作るのではなく、echoなどのalexaデバイスと紐付いたamazonアカウントでログインする必要があります。これが、割と深く広い落とし穴で、実際ハマリました。

alexaデバイスと紐付いたamazonアカウントでログインしてスキル開発をすれば、作成したスキルを自宅のechoなどで試すことが出来ます。一方で、新規に開発者アカウントを作成すると、(まあ、考えてみると当然なんですが)、紐付けがなされず公開前のスキルを実機で試すことが出来ません。
また、amazon.co.jpとamazon.com(U.S.A)で、同一のメールアドレス、パスワードのアカウントを持っていると、既存アカウントでログインしても勝手に.comの方にリダイレクトされて、上手くいかないようです。

僕の場合は、よく確認せず突っ走って、新規に開発者アカウントを作ってしまい、完成したスキルが実機で使えない現象に陥りました。 同一アドレス、パスワードの米国アカウントも持っていたので、パスワードを変更してから再度ログインし、一からスキルを作り直す羽目に。

参考: dev.classmethod.jp

前置きが長くなりましたが、ここからが本番。
といっても以降はトレーニングに沿って、進めていけば 特に詰まるところはなかった。

スキル設定と対話モデルの作成

  • スキル名
  • 呼び出し名
  • インテント作成

まずは開発者コンソールで対話部分の構築を行います。
スキル名は単純にスキルの名称。
呼び出し名は、「アレクサ、○○開いて」の○○部分に該当。
インテントは、ユーザが命令する際の想定フレーズを列挙するもの。
同じ命令でも複数種のフレーズがあるので、たくさん用意しておく必要がある。
対話モデルの品質面で割と重要な要素だと思います。

f:id:take213uv:20180809033209p:plain

f:id:take213uv:20180809033235p:plain
とりあえず列挙したけど、まだ勝手が分からない

AWS lambda関数作成

次にAWSに移って、lambda関数を作成。
スキルの実際の処理部分はlambda関数に記載する。
トレーニングではサンプルプログラムをDLしてコピペすることになっている。
以下、サンプルプログラム。

'use strict';
var Alexa = require('alexa-sdk');

//=========================================================================================================================================
//TODO: このコメント行より下の項目に注目してください。
//=========================================================================================================================================

//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: var APP_ID = "amzn1.ask.skill.bb4045e6-b3e8-4133-b650-72923c5980f1";
var APP_ID = undefined;

var SKILL_NAME = "豆知識";
var GET_FACT_MESSAGE = "知ってましたか?";
var HELP_MESSAGE = "豆知識を聞きたい時は「豆知識」と、終わりたい時は「おしまい」と言ってください。どうしますか?";
var HELP_REPROMPT = "どうしますか?";
var STOP_MESSAGE = "さようなら";

//=========================================================================================================================================
//「TODO: ここから下のデータを自分用にカスタマイズしてください。」
//=========================================================================================================================================
var data = [
    "水星の一年はたった88日です。",
    "金星は水星と比べて太陽より遠くにありますが、気温は水星よりも高いです。",
    "金星は反時計回りに自転しています。過去に起こった隕石の衝突が原因と言われています。",
    "火星上から見ると、太陽の大きさは地球から見た場合の約半分に見えます。",
    "木星の<sub alias='いちにち'>1日</sub>は全惑星の中で一番短いです。",
    "天の川銀河は約50億年後にアンドロメダ星雲と衝突します。",
    "太陽の質量は全太陽系の質量の99.86%を占めます。",
    "太陽はほぼ完璧な円形です。",
    "皆既日食は一年から二年に一度しか発生しない珍しい出来事です。",
    "土星は自身が太陽から受けるエネルギーの2.5倍のエネルギーを宇宙に放出しています。",
    "太陽の内部温度は摂氏1500万度にも達します。",
    "月は毎年3.8cm地球から離れていっています。"
];

//=========================================================================================================================================
//この行から下のコードに変更を加えると、スキルが動作しなくなるかもしれません。わかる人のみ変更を加えてください。  
//=========================================================================================================================================
exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.APP_ID = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

var handlers = {
    'LaunchRequest': function () {
        this.emit('GetNewFactIntent');
    },
    'GetNewFactIntent': function () {
        var factArr = data;
        var factIndex = Math.floor(Math.random() * factArr.length);
        var randomFact = factArr[factIndex];
        var speechOutput = GET_FACT_MESSAGE + randomFact;
        this.emit(':tellWithCard', speechOutput, SKILL_NAME, randomFact)
    },
    'AMAZON.HelpIntent': function () {
        var speechOutput = HELP_MESSAGE;
        var reprompt = HELP_REPROMPT;
        this.emit(':ask', speechOutput, reprompt);
    },
    'AMAZON.CancelIntent': function () {
        this.emit(':tell', STOP_MESSAGE);
    },
    'AMAZON.StopIntent': function () {
        this.emit(':tell', STOP_MESSAGE);
    },
    'SessionEndedRequest': function () {
        // Nothing to do
    }
};

node.jsとか使ったことないけど、
dataの配列の中の文字列をランダムに返すのだな、
という雑な理解をした。

var data = [
    "ゆずくん オス 1才。 ポメラニアン",
    "春くん オス 2才6ヵ月。雑種",
    "ベイリーくん オス 1才5ヵ月。トイ・プードル。",
    "花子ちゃん メス 6ヵ月。柴犬"
];

今日のわんこ情報に書き換えた。

参考:

www.fujitv.co.jp

スキルとlambda関数の接続

作成したlambda関数とスキルを紐付けます。
開発者コンソールに戻ってlambdaのARNをエンドポイントに設定。

テスト

完成したスキルは、シミュレータを使ってPC上でテストできます。

f:id:take213uv:20180809040225p:plain

また、amazon.co,jpアカウントと紐付け出来てれば*1
自分のalexaデバイスでスキルが実行できるようになっています。

これで今日のわんこを教えてくれるスキルが完成しました。
※今日の、といいつつ聞くたびに内容が変わる。
※テキスト情報だけなので犬種とかから、姿を想像するしかない

何の役に立つの?何の役にも立たない。

まとめ

普通のプログラムだと本当にしょうもない処理ですが、
音声対話として形になると、わりと満足感があるのが面白いですね。
次回は、公開用のスキル作成に挑戦しようと思います。



次の記事:公開用のアレクサスキル作成

Tシャツの為だけにアレクサスキル開発 目次

*1:前述の通り、ここで過ちに気づき1から作り直した