[日本語Alexa] 4桁の数字を確実に受けとるためには 〜より自然に会話できるスキル作成のために〜

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

「より自然に会話できるスキル作成のために」シリーズも今回で4回目となりました。

今回は、特定の桁数の数値を受け取る方法について考えてみました。

以前紹介した、会議室予約のスキルですが、こちらでは、予約やキャンセルする会議室の番号を指定する場面があります。

例えば、こんな感じです。

User : 明日の3時から1001号室を予約して

ここで会議室の番号は非常に重要です。会議室の番号を聞き間違えると、本来の目的を達成できないどころか、意図しない処理が走ってしまいます。 かと言って、入力内容を確認しながら進める場合も、認識率が低いとちょっと辛くなります。

Alexa: 会議室の番号を言って下さい
User: 1001
Alexa: 10015で宜しいですか?
User: いいえ
Alexa: 会議室の番号を言って下さい
User: 1001
Alexa: 1011で宜しいですか?
User: ※△■◯✕※◯✕◯✕・・・ 

今回の内容は、公式のドキュメントに記載されている内容では無く、あくまで「私が試してみた結果」に過ぎ無いことを、予めご了承下さい。

2 AMAZON.NUMBER

数値を受け取るのに最初に思いつくのは、スロットのタイプをAMAZON.NUMBERにして受け取る方法です。

通常、AMAZON.NUMBERで全然問題ないと思います。

しかし、ここで少し気になるのは、AMAZON.NUMBERで、特定の桁数を指定することが出来ないところです。非常にまれですが桁数自体を間違えることもあり得ます。恐らく、これは(4桁で聞き取ろうとしている)人間では、まずあり得ない間違いだと思うので、可能であれば対応させたいところです。

User: イチ、ゼロ、ゼロ、イチ 号室を予約して
Alexa: 100015を予約しました。
User: ※△■◯✕※◯✕◯✕・・・ 

※ 注:非常に稀な例です

3 AMAZON.FOUR_DIGIT_NUMBER

日本語で使用可能な組み込みスロットに、AMAZON.FOUR_DIGIT_NUMBERがあります。

4桁の数字(「六、零、四、五」)を数字(「6045」)に変換します。

こちらは、4桁の数字グループを認識するためのスロットです。


https://developer.amazon.com/ja/docs/custom-skills/slot-type-reference.html#four_digit_number より

それでは、スロットのタイプをAMAZON.FOUR_DIGIT_NUMBERに変更してみます。

そして、テストするための簡単なコードを作成しました。

'ReservationIntent': function () {
    if (this.event.request.intent != undefined) {
      const intent = this.event.request.intent;
      if (intent.slots.number != undefined) {
        const number = this.event.request.intent.slots.number.value;
        this.emit(':tell', number + 'を予約しました。');
        return;
      }  
    }
    this.emit(':tell', '部屋番号を取得できませんでした。');
},

以下の例でわかるように、実は、AMAZON.FOUR_DIGIT_NUMBERでは、4桁以外でも受け取ることが出来ます。

User: ゴー、マル、ニーを予約して
Alexa: 502(ごひゃくに)を予約しました。
User: ゴー、マル、マル、ニーを予約して
Alexa: 5002(ごせんに)を予約しました。
User: ゴー、マル、マル、ニー、ニーを予約して
Alexa: 50022(ごまんにじゅうに)を予約しました。

4桁に限らず使用できるので非常に便利なのですが、逆に4桁に縛ることは出来ていない事になります。

4 桁数で縛る

数値の入力には、通常、AMAZON.NUMBERや、AMAZON.FOUR_DIGIT_NUMBERで充分でしょう。

しかし、ここでは、「より自然に会話できるスキル作成のために」ということで、人間のように桁数を意識して人の話を聞くところを検討して見たいと思います。

最初に、一つ一つの数字「0〜9」を表現するカスタムリスト(LIST_OF_NUMBER)を作成しました。

インテントのサンプル発話では、4桁の数字それぞれを別のスロットとして定義しました。

そして、それぞれのスロットのタイプは、先に作成したLIST_OF_NUMBERとします。

実装したコードは、以下のとおりです。slotのrequiredを設定してダイアログモデルで書いています。

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

exports.handler = function(event, context, callback) {
    console.log(JSON.stringify(event));
    const alexa = Alexa.handler(event, context);
    alexa.registerHandlers(handlers);
    alexa.execute();
};

function getId(slot) {
  if (slot.resolutions != undefined) {
    if (slot.resolutions.resolutionsPerAuthority != undefined) {
      const resolutionsPerAuthority = slot.resolutions.resolutionsPerAuthority;
      if (resolutionsPerAuthority.length > 0) {
        const values = resolutionsPerAuthority[0].values;
        if( values != undefined && values.length > 0){
          return values[0].value.id;
        }
      }
    }
  }
  return undefined;
}

// 数字を読み替える
function ConversionOfReading(str) {
  str = str.replace(/0/g, 'まる');
  str = str.replace(/1/g, 'いち');
  str = str.replace(/2/g, 'にい');
  str = str.replace(/3/g, 'さん');
  str = str.replace(/4/g, 'よん');
  str = str.replace(/5/g, 'ごう');
  str = str.replace(/6/g, 'ろく');
  str = str.replace(/7/g, 'なな');
  str = str.replace(/8/g, 'はち');
  str = str.replace(/9/g, 'きゅう');
  return str;
}

const handlers = {
  'ReservationIntent': function () {
    if (this.event.request.dialogState !== 'COMPLETED'){
        this.emit(':delegate');
    } else {
      const intent = this.event.request.intent;
      const first_number = getId(intent.slots.first_number)
      const second_number = getId(intent.slots.second_number)
      const third_number = getId(intent.slots.third_number)
      const fourth_number = getId(intent.slots.fourth_number)
      const number = first_number + second_number + third_number + fourth_number;
      this.emit(':ask', ConversionOfReading(number) + 'を予約しました。他にもありますか?');
    }
  },
  'LaunchRequest': function () {
    this.emit(':ask', '予約する会議室の番号を教えてください');
  },
  'AMAZON.YesIntent':function () {
    this.emit(':ask',"予約する会議室の番号を教えてください");
  },
  'AMAZON.NoIntent':function () {
    this.emit(':tell',"終了します");
  },
  'AMAZON.CancelIntent':function () {
    this.emit(':tell',"終了します");
  },
  'AMAZON.StoplIntent':function () {
    this.emit(':tell',"終了します");
  },
  'Unhandled': function () {
    this.emit('ReservationIntent');
  }
};  

動作している様子です。完璧に4桁の数字を取得できています。

5 最後に

実は、今回作成したサンプルは、人間のように「この場面では、相手は4桁で言ってくるはずだ!」というように意識して聞き取っているため、4桁以外で発話しても4桁として聞き取ってしまいます。これは、Alexaとして良い動作であるとは言い難いので、使い方には注意が必要です。 しかし、完全に4桁での入力を要求している箇所でピンポイントに上手に利用すれば、もしかすると効果的なのでは?と感じています。

はじめにお断りしたとおり、この内容は、公式のドキュメントに記載されている内容では無く、あくまで「私が試してみた結果」に過ぎません。

「数字を聞き取る」という作業を色々試行錯誤していて、組み込みのスロットは本当に偉大だと改めて痛感しています。