そういう、モデルなんです。

ビジネスモデル、設計図、模型などの現状と動向を考察、関連書籍の紹介

アレクサスキル Alexa Skill を、どうにか公開できた。

最初は、アレクサ開発者コンソール Alexa Developer Console 上で試しながら直接実装していたが、

  • 実装量が増えるにつれて、エラー発生時の切り分けが困難に
  • リグレッションテストが場当たり的になり、品質が低下
  • 開発中ソースコードのバージョン管理はコンソールではできず不便

という、ありきたりといえばありきたりな壁にブチ当たった。

結局のところ、通常の開発と同様に、ちゃんとしたローカル開発環境を用意することによってスキルの公開まで到達することができた。 

tombi-aburage.hatenablog.jp

サイコロ係

サイコロ係

 

とりあえず動くレベルまでの開発はひじょうに簡単だった 

3月上旬に、スマートスピーカーでの開発に興味を持ち、いくつか初心者向けの書籍を読んで、どのようなものか調べた。

tombi-aburage.hatenablog.jp

スマートスピーカーを持っていない状態でも、エミュレータ利用で開発できるようだったので書籍片手に作ってみた。

書籍刊行時(昨年)とは異なり、現在ではスキルサービス(AWS Lambda サービス)側とスキルインタフェース(発話モデル)も統合されていたので、開発は難しくなかった。

コンソールで自動生成した Hello World を直せば、簡単に動く状態にはできた。

初回の審査は3月25日、以下のような指摘事項だった。

なんか一応動く状態にはなったので、スマートスピーカーを持っていないクセに、いきなりスキルストアの審査に出すという暴挙に出た w、

アクレサ開発者コンソール上で、ちょこちょこ作っていった結果、こんな感じになった。

f:id:tombi-aburage:20190418112157p:plain

審査の申請は簡単だったが、もちろん一発で通るワケはない。
3つほど指摘をもらってしまった。

  1. スキルがタスクを完了した後、ユーザーへのプロンプトが提示されていないにもかかわらずセッションが開いたままになっています。スキルは、リクエストを完了した後、ユーザーの入力を求めるプロンプトを提示していない場合はセッションをクローズする必要があります。

    再現手順:

    ユーザー:アレクサ、サイコロ係を起動して

    スキル :何面体のサイコロを何個振りましょうか?

    ユーザー:五六面体サイコロを一個振って

    スキル :56面体を1個振ります。40が出ました。

      (セッションオープン)

    セッション管理の方法については、申請チェックリストのテストケース4.1を参照してください。

  2. コンパニオンアプリ及びスキルのプロンプトに提示されている発話例(ウェイクワードおよびサポートされている呼び出しフレーズを除く)が、サンプル発話に含まれていません。現在、サンプルフレーズ及びヘルププロンプトに次のフレーズをご提示いただいています。


    該当するサンプル発話:

    6面体のサイコロを3個振って

    「何面体のサイコロを」 「何個」 「振って」

     

    以下のサンプル発話を追加してください:

    RollDiceIntent   {diceType} 面体のサイコロを {amount} 個振って

  3. データのフォーマットが弊社の規定に沿っていません。サンプル発話、スロット値のデータは、全て日本語で表示する必要があります(頭文字、イニシャリズム、アクロニムを除く)。以下のように訂正の上、再度ご申請ください。

該当する発話:

RollDiceIntent  {amount} {diceType} を振って

修正例:

RollDiceIntent  {amount} d {diceType} を振って


補足:
サンプル発話内では、イニシャルを小文字にし、半角スペースで区切る必要があるため、修正をお願いいたします。

2つめ、3つめの指摘はポカミスのレベルであり、発話例や公開申請時の説明文を直すだけで済むものなので治せたが、1つめは多分デザイン上のルールにかかわる指摘であり、何をすれば合格になるのか、ちょっとよくは分からなかった。

気が変わって Amazon Echo (第二世代)を買う

別売バッテリーを買えば、標準的な Echo でも、好きなところに持ち歩きできると分かったので、購入することにした。

tombi-aburage.hatenablog.jp

  • セットで購入したスマートコンセントはまるで役立たずだった。
    しかも翌週に Echo は半額セールされるという酷い仕打ち。
  • リモコン無しでテレビの制御ができるのは便利。
  • セミの鳴き声はウケた。

ローカル開発環境を構築

公開できる品質にするまでには、ローカル開発環境をしっかり作ることが必要だったと冒頭述べたが、4~5冊目に読んだ以下の書籍がけっこう役に立った。

Amazon Alexaプログラミング入門 (impress top gear)

Amazon Alexaプログラミング入門 (impress top gear)

 

Visual Studio Code、Git など、基本的な開発環境については触れていないので、その辺はネット調査で補完するか、経験と勘で適当にやった。 

2回めの審査は4月18日、以下のような指摘事項だった。

ローカル開発環境が信頼できるものになったので、ほとんど全てをリファクタリング

自動テスト環境までは作っていないが、インテントごとに1~2パターン程度のテストデータを用意しておき、手動ながらもローカルで毎回再テストすることは徹底した。

これなら行けるだろうということで、2回目の審査提出。

  1. スキルがタスクを完了した後、ユーザーへのプロンプトが提示されていないにもかかわらずセッションが開いたままになっています。スキルは、リクエストを完了した後、ユーザーの入力を求めるプロンプトを提示していない場合はセッションをクローズする必要があります。

    再現手順:

    ユーザー:アレクサ、サイコロ係を実行して

    スキル:何面体を何個、振りましょうか?

    ユーザー:八面体を三個振って

    スキル:8面体を3個振ります。うりゃ!8、6、1、合計は15です。

    (セッションオープン)

    セッション管理の方法については、申請チェックリストのテストケース4.1を参照してください。

  1. いずれかのスロットに無効または空のスロット値を指定して1つ以上のインテントを呼び出した際、スキルがエラーを返します。

    該当箇所: RollDiceIntent

    再現手順:

    ユーザー:アレクサ、サイコロ係を開いて

    スキル:何面体を何個、振りましょうか?

    ユーザー:三個一億面振って

    スキル:スキルがリクエストに正しく応答できませんでした

     

    エラー処理の方法については、申請チェックリストを参照してください。

  1. 複数のインテントに同一のサンプル発話が含まれています。各インテントには独自のサンプル発話が必要です。ユーザーのリクエストが正しいインテントへ送られるように、修正・変更によって以下のサンプル発話の重複を取り除いてください。

    該当のサンプル発話:

    SayAgainIntent もう一回言って

    SayAgainIntent もう一度言って

     

    補足:

    上記のサンプル発話は既にAMAZON.RepeatIntentに定義されております。

1つめの指摘は、1回目の提出時のものと本質的に同じだった。

セッション管理の実装上の問題ではなく、発話が質問で終わっていないことが問題なのではないか?と仮説を立てて、

スキル:8面体を3個振ります。うりゃ!8、6、1、合計は15です。

と speak した後に、

何面体を何個、振りましょうか?

を追加し、利用者に対して結果を伝えた後、すぐ質問するような発話に変えてみた。
これまで repromt に書いていた文言を、speak の末尾に付けたすだけの修正。

修正前

speechText は「8面体を3個振ります。うりゃ!8、6、1、合計は15です。」

f:id:tombi-aburage:20190421075124p:plain

修正後

speechText は「8面体を3個振ります。うりゃ!8、6、1、合計は15です。(1秒間をおいてから)何面体を何個、振りましょうか?」

return handlerInput.responseBuilder
.speak(s.speechText + '<break time="1s"/>' + r.t('ASK_COMMAND'))
.reprompt(r.t('ASK_COMMAND'))
.getResponse();
}
};

2つめは、実装ミスというよりは仕様ミス

2つめは、Cloud Watch のログを追ったら、言語レベルでメモリ確保できないという趣旨のエラーだった。大変申し訳ございません・・・要素が1億個の配列 Array を漫然と new しておりました…

確かに AMAZON.Number はただの数値なので、一億面ダイスも入りうるわな。

ユーザー:三個一億面振って
スキル:スキルがリクエストに正しく応答できませんでした 

var rollSummary = new Array(this.dicetype);

面白いかと思って、何面体のサイコロでもOKという仕様にしていたが、実用性は全くないので、仕様見直しを行い、一般に市販されている100面体までに制限した。

,'TOO_MANY_DICE' : '振れるのは100面体を20個までなんです。すみません。'

ついでに、スロットに万が一マイナス値が入った場合にはプラスに変換するようにもしておいた。実機テストで「マイナス」と発話しても、負の値は入らないようではあるが一応対策はしておく。

if(handlerInput.requestEnvelope.request.intent.name === 'RollDiceIntent'){
if(slots.diceType.value !== undefined) s.dicetype = Math.abs(slots.diceType.value);
if(slots.amount.value !== undefined) s.amount = Math.abs(slots.amount.value);
 

本来はサイコロを振るユーティリティクラス DiceRoller でチェックや補正するか例外を投げて呼び出し側に結果のみ伝えるべきとも思うが、JavaScript のクラスからの例外の投げ方がわかんないので、呼び出し側でスロットへの入力値をチェックしたり、値を変更するだけで済ませた。

サイコロは20面体までで実用上は十分だが、一応100面体までは存在する

私自身は D&D、AD&D で使っていた 4、6、8、12、20面体ダイスは持っているが100面体は10面体2個で代替できるので持っていない。

100面体ダイスは、ほぼ球体なので中々止まらない。止まりやすいように

  • 出目の部分が平たく削ってあり、
  • 球の中にも鋼球の重りが入っている

という精密加工品・芸術品のような代物だった。しかし所詮プラスチック製であり、加工はいい加減だったので、多分確率は均等ではなかったと疑われる。

とあるマニアによれば、3面体なども存在する

oreore.red

によれば、

  • 2面体(6面体の辺を4カ所丸く削り、2曲面にする)
  • 3面体(考え方は2面体と同じ)
  • 果ては1面体(メビウスの輪というオチ)

すらも存在するらしいので、100面体以下であれば面数の制限はしないことにした。

個数のほうは、メモリ確保に関する問題は起きない実装だったが、とてつもなく大きい数を言われたら内部的にはくそ真面目にサイコロを振ってしまうし、出目ごとにサマリーする工夫はしているとはいえ、個数が増えて出目のバラツキが増えると結果の読み上げがいつまでも終わらないので、やはり20個くらいに制限することにした。

トンネルズ&トロールズでは、ドラゴンだが何だかの攻撃のさいに十数個の6面体ダイスを同時に振るようなことはあったかと思うので10個だと少ないだろう。

3つめは、サンプル発話を増やしたことによるバッティング

実際には、全く同じ発話は RepeatIntent に定義されてはいなかったのだが、表現的に近似している「もう一回」「もう一度」が引っ掛かっていそうだったので削除した。

Alexaスキル サイコロ係 が公開されました!

対応方法はあっていたらしく、翌4月19日には公開の通知をもらえた。

この度は サイコロ係 スキルを申請いただき、誠にありがとうございます。 おめでとうございます。スキルは認定プロセスに合格し、まもなくスキルストアに公開されます。

もしアレクサ開発者コンソールでの開発を続けていたら、リファクタリングに失敗して、もうとっくに諦めていたに違いない。やはりローカル開発環境は大事だな。

f:id:tombi-aburage:20190421092621p:plain

「開発中」のほかに「公開中」のエントリが増えた