【AmiVoice API Private・SDK】アプリケーション開発者目線で見た具体的なルールグラマの書き方《数値入力編》

みなさま、こんにちは。
AmiVoice向けのルールグラマについては、以下のとおり基本編・実践編・発展編の記事がありますが、この基本・実践・発展をアプリケーション開発でどのように利用していくかを、数値入力を題材にして具体的にご紹介します。
※ヘッダの書き方やグラマ名の定義、publicルールなどルールグラマファイルの説明は以下の記事をお読みください。ここでは音声認識の対象となるpublicルールの書き方を中心にご説明します。
1桁の数値を認識させる
例えば、0から3までの数値を1桁だけ音声認識するルールグラマを書こうと思った場合、並列で書けば次のようになります。
public <0_3> = 0\ぜろ | 1\いち | 2\にー | 3\さん;
直列で書くと次のように4つのpublicルールになります。
public <0> = 0\ぜろ;
public <1> = 1\いち;
public <2> = 2\にー;
public <3> = 3\さん;
並列と直列、どちらも1桁の「ぜろ」「いち」「にー」「さん」を音声認識しますが、認識したい数値の分だけ直列のpublicルールを書くより、並列で1つのpublicルールにまとめていただいた方が良いのがお分かりいただけるかと思います。0から9まで1桁の数値を音声認識するルールグラマを書く場合は、並列の例をそのまま拡張してください。
他の例》
数を「1個」「2個」「3個」または「1」「2」「3」と数えるような場合は、次のようにルールグラマを書くことができます。 [ ] で囲んだ内部は省略可能です。
public <sample> =( 1\いち/いっ | 2\に/にー | 3\さん ) [ こ ];
複数桁の数値を認識させる
電話番号を音声認識させたいルールグラマを書くと、10桁と11桁の場合あわせて次のように3つのpublicルールと1つのprivateルールの組み合わせになります。
public <number01> = <0_9> <0_9> [の] <0_9> <0_9> <0_9> <0_9> [の] <0_9> <0_9> <0_9> <0_9>;
public <number02> = <0_9> <0_9> <0_9> <0_9> [の] <0_9> <0_9> [の] <0_9> <0_9> <0_9> <0_9>;
public <number03> = <0_9> <0_9> <0_9> [の] <0_9> <0_9> <0_9> <0_9> [の] <0_9> <0_9> <0_9> <0_9>;
<0_9> = (0¥ぜろ/れい/まる | 1¥いち | 2¥にー/に | 3¥さん | 4¥よん | 5¥ごー/ご | 6¥ろく | 7¥なな | 8¥はち | 9¥きゅー );
3つのpublicルールは、それぞれ発話「○○の○○○○の○○○○」、「○○○○の○○の○○○○」、「○○○の○○○○の○○○○」の3パターンを、「の」を省略しても音声認識できるようにしてあります。
この電話番号を音声認識させるルールグラマのポイントは、各publicルールで同じ記述となる個所をprivateルールにして共通部品化している点と、予想される桁数だけ数値の発話を受け付けるようにした点にあります。
privateルールで共通部品化を行わないと、同じような記述がpublicルール内に数多く記述され、どこかで記述ミスがあった際の修正にかかる労力が多くなります。
また、10桁と11桁の数値を音声認識するルールグラマでしたら繰り返し記号「+」を利用して次のようにも書けますが、これだと1桁以上の数値を全て認識してしまうので、「いち に さん」で発話を止めた時も音声認識が成功し、「1 2 3」を音声認識結果とし出力します。電話番号をアプリケーションは受け取りたいのに、「1 2 3」と3桁の数値を音声認識結果として渡されることを考えたら、電話番号ではない桁数を受け取った時のエラー処理をアプリケーション側は実装しなければなりません。
public <number04> = <0_9>+;
桁読み(位取り読み)の数値を認識させる
上記では、数値「123」を「いちにさん」と読む粒読みを認識するルールグラマを紹介してきましたが、「123」を「ひゃくにじゅうさん」と読む桁読みを認識するルールグラマは次のように書けます。
public <0_999> = ([<num100>] [<num10>] [<num1>]) | <num0>;
<num0> = 0\ぜろ/れい;
<num1> = ( 1\いち | 2\にー/に | 3\さん | 4\よん | 5\ご | 6\ろく | 7\なな | 8\はち | 9\きゅう );
<num10> = (10\じゅう | 20\にじゅう | 30\さんじゅう | 40\よんじゅう | 50\ごじゅう | 60\ろくじゅう | 70\ななじゅう | 80\はちじゅう | 90\きゅうじゅう );
<num100> = ( 100\ひゃく | 200\にひゃく | 300\さんびゃく | 400\よんひゃく | 500\ごひゃく | 600\ろっぴゃく | 700\ななひゃく | 800\はっぴゃく | 900\きゅうひゃく );
1から999までの桁読みが《百の位》《十の位》《一の位》の形で構造化できるので、それぞれprivateルールで記述したものをpublicルールで参照するようにしています。桁読みであるならば0は単独で「ぜろ」または「れい」と発話されます。そのため0は一の位に含めず、単独で音声認識できるよう1から999までと分けて並列に記述しています。
Tech Blogで既に説明されているルールグラマの基本編・実践編・発展編では、AmiVoice API Privateより返ってくる音声認識結果をサンプルとして紹介していましたが、AmiVoice SDKが返す音声認識結果は次のような文字列となっています。
例》発話「ひゃくにじゅうさん」を上記 public<0_999> で音声認識した場合の音声認識結果文字列
100|20|3\u0001ひゃく|にじゅう|さん\u00017700-8940|7740-8080|8080-8480|8480-8900\u0001\u00010_999\u0001
この例は、Windowsで動作させた音声認識結果のため「¥u0001」が区切り文字コードになっており、AmiVoice API Privateの音声認識結果のように表現すると、
written : 100|20|3
spoken : ひゃく|にじゅう|さん
starttime-endtime : 7700-8940|7740-8080|8080-8480|8480-8900
rulename : 0_999
と切り分けることができます。
音声認識結果を数値として扱いたいのであれば、writtenの「100|20|3」を100と20と3に分けてから文字列を整数にパースして加算すれば 100 + 20 + 3 = 123 となり、発話された「ひゃくにじゅうさん」を整数の123としてアプリケーションは扱うことができるようになります。
まとめ
ここまでお読みいただきありがとうございました。実運用向けにルールグラマを書く際のポイントは次の2つです。
- 同一記述はprivateルールにしてpublicルールから呼び出すと便利です
- 実際の運用を想定したルールグラマを記述するようにしましょう
ルールグラマを利用して音声入力を実現しようとしたとき、1発で思い描いたとおりに音声入力できるルールグラマを書けないことは時々あります。また、運用を続けていくとルールグラマの内容を変更する必要が生じることもあると思います。privateルールとpublicルールをうまく組み合わせて構造的なルールグラマを書くと、メンテナンスしやすく運用に適した良いルールグラマになりますので、どうぞお試しください。