【AmiVoice API Private・SDK】上級者向けの「ルールグラマ」を作ってみた【発展編】

大倉尭
皆さん、こんにちは!
「ルールグラマ」シリーズも最終回となります。今回は「基本編」「実践編」に続き、ルールグラマの上級者向けの書き方を解説します。「基本編」「実践編」の内容が前提となりますので、初めてルールグラマを作成する方は先に「基本編」「実践編」をご覧ください。
※なお、ルールグラマを使った音声認識には、AmiVoice API PrivateまたはAmiVoice SDKで「ルールグラマエンジン」を使用する必要があります。ルールグラマを使った開発にご興味のある方は、個別相談会からお申し込みください。
繰り返し
単語(列)を繰り返す発話は、以下のように書くことができます。
public <sample> = (はい)+;
※本記事のサンプルでは、ヘッダ行およびグラマ名定義行(「基本編」のサンプルにおける1行目・2行目)は省略します。
上記のように書くと、「はい」「はい はい」「はい はい はい」… を認識できます。
なお、繰り返しを表す記号は、0回以上の繰り返しを示す *(半角アスタリスク)と、1回以上の繰り返しを示す +(半角プラス)が使用できます。
カッコの中に単語列を書けば、単語列の繰り返しを認識することも可能です。また、並列の “|” と組み合わせることも可能です。
public <curling> = (イェップ | ウォー)+;
このように書くと、「イェップ ウォー」「ウォー イェップ ウォー」のように、「イェップ」または「ウォー」を複数回繰り返す発話を認識できます(ちなみに、「イェップ」「ウォー」はカーリングの掛け声です)。
privateルール
ルール名に”public”が付かないルールをprivateルールと呼びます。privateルールは、publicルールの中にルール名を記述すると音声認識の対象となります。
public <sample> = <department> <post>
<department> = (総務\そーむ | 技術\ぎじゅつ);
<post> = (部長\ぶちょー | 課長\かちょー);
上記の例では、<sample>がpublicルール、<department>と<post>がprivateルールになります。privateルールは変数のようなもの、と考えてください。すなわち、上記の例は、
public <sample> = (総務\そーむ | 技術\ぎじゅつ) (部長\ぶちょー | 課長\かちょー);
と書くのと同じで、「総務 部長」「総務 課長」「技術 部長」「技術 課長」の4通りの音声認識が可能なルールグラマになります。「総務」のように、privateルールのみを発話しても認識されません。
この例であればわざわざprivate変数を使わずに書いてもよいかと思いますが、部署の数が増えるなどすると1行では見にくくなるでしょう。読みやすさ・編集のしやすさも考慮して使用してください。
private変数を繰り返しと組み合わせた例も見てみましょう。
public <sample> = <number>+;
<number> = (1\いち | 2\にー/に | 3\さん);
このように書けば、「1 2 3」や「1 1 1 1」といった数字の繰り返しを認識できます。
さらに、繰り返しの回数が決まっている場合、private変数を使うと便利です。
public <sample> = <number> <number> <number>;
<number> = (1\いち | 2\にー/に | 3\さん);
このように書くと、認識できるのが3桁の数字に限定されます。当然、”<number>+”でも3桁の数字を認識できますが、3桁以外の数字も認識できるので、望む桁数の認識結果が出ない可能性があります。
“*” や “+” の記号は正規表現と同じですが、ルールグラマでは正規表現のように繰り返しの回数を指定することはできません。繰り返したい回数分、素直に書いてください。
特殊ルール
以下のルール名は特殊ルールであり、これらは予約されているルール名です。自身で作成するルール名に使用することはできません。
- <NULL>
何もないことを意味します。例えば、省略可能の書き方を使った [はい] は、(はい | <NULL>) と同義です。 - <VOID>
合致するものがないことを意味します。JSGFの仕様にはありますが、AMIのルールグラマで使用することはまずないので、詳しい説明は割愛します。 - <GARBAGE>
弊社ルールグラマ独自の仕様です。全てに合致することを意味します。%wildcardとも記述できます。
<GARBAGE>は、例えば発話に雑音やフィラー(「あのー」や「えー」など)が入る可能性がある場合に使用することができます。
public <sample> = <GARBAGE>* おはよう;
このようにすると、「おはよう」の前に雑音やフィラーが入っても認識できる可能性が高まります。
タグ
単語を認識した時に、認識結果とは別にアプリへ返す文字列(タグ)を設定できます。タグは、認識したい単語の右側(読みがある場合は読みの後)に “{ }”(半角波カッコ) で記述します。
public <sample> = (はい{ok} | おっけー{ok} | いいえ{ng} | えぬじー{ng});
このようなルールグラマを設定し、「はい」と発話した場合の出力の一例は以下の通りです。
{
"results": [
{
"tokens": [
{
"written": "はい",
"confidence": 1,
"starttime": 610,
"endtime": 1050,
"spoken": "はい"
}
],
"confidence": 1,
"starttime": 350,
"endtime": 1390,
"tags": [
"ok"
],
"rulename": "sample",
"text": "はい"
}
],
"utteranceid": "20240327/11/018e7db88cf40a303ecb94c4_20240327_112350",
"text": "はい",
"code": "",
"message": ""
}
“tags”(16行目)の部分に”ok”という設定値が出力されています。なお、認識された複数の単語それぞれにタグが設定されている場合は、
"tags": [
"1",
"2",
"3"
],
のように、認識された順番にカンマ区切りでタグが出力されます。
タグの用途は様々ですが、例えば、同じ意味を持つが読みの異なる別々の単語を扱いやすくなる、などのメリットがあります。認識したい語句と認識結果を行う処理の間にタグを挟んだ場合、ルールグラマで認識したい語句を修正することになっても、タグに変更がなければプログラム側の修正が不要になります。
なお、必ずしも全ての単語にタグを設定する必要はありません。重要なキーワードにのみタグを設定する、といった使い方も可能です。先ほどの例であれば、
public <sample> = (はい{ok} | おっけー{ok} | いいえ | えぬじー);
のようにすると、「はい」と「おっけー」と発話した時だけ”ok”というタグが出力されます。
おわりに
本記事では、上級者向けのルールグラマの書き方を解説しました。
ルールグラマを書く上で重要なのは、「認識したい言葉に必要十分なグラマを書く」ことです。そのためのポイントをいくつかまとめておきます。
- 認識してほしい言葉は漏らさず書く!
ルールと読みが正しく書かれていないと、正しく認識することができません。また、読みやすい・編集しやすい書き方を心がけるのもミスを減らすコツです。 - 認識しないでよい言葉はグラマに書かない!
複雑なルールグラマになるほど、無駄な言葉が入りがちです。今までの記事で説明した書き方を駆使して、意図した言葉だけが認識できるルールグラマを書きましょう。 - 並列数が多いほど認識が難しい!
5個の並列は適当に選んでも1/5の確率で当たりますが、1000個の並列から適当に選んでもまず当たりません。並列数を減らす工夫ができないか考えてみましょう。
ルールグラマはAmiVoice API Private・SDKで提供されている機能ですが、より手軽にAmiVoice APIの音声認識を試してみたい開発者の方がいましたら、ぜひ https://acp.amivoice.com/ を試してみてください。毎月音声60分までは全エンジン無料で使えます。
ここまでお読みいただき、ありがとうございました!
この記事を書いた人
-
大倉尭
新卒でアドバンスト・メディアに入社。
音声認識の精度向上のための研究開発に携わった経験から、このブログをはじめ、アドバンスト・メディアの技術力をアピールする仕事に挑戦中。
趣味は旅行(主に鉄道)・読書(主に小説)・ボードゲームなど。
よく見られている記事
新着記事
- 【AmiVoice API Private・SDK】上級者向けの「ルールグラマ」を作ってみた【発展編】
- 音声認識を使ったシステム開発の前提条件<後編>ー開発ノウハウシリーズ2ー
- 音声認識を使ったシステム開発の前提条件<前編>ー開発ノウハウシリーズ1ー