実習:音声対話

2010年8月 西本卓也(東京大学)

更新日 2010-08-04

概要

  • この実習は、音声対話システムの各モジュールを「改変可能な個別のパーツ」としてではなく「一つのまとまったシステム」として扱います。
  • 実習には含めないが実演する内容:Webアプリケーションとしての VXML の実例、 Rails との連携
  • ISTCが提案した「6階層モデル」:タスク内制御は VoiceXML の FIA に、タスク間制御は Controller に対応。

演習課題

  • (1) 駅名、枚数などを変更して動作を確認して下さい。どのような単語が入力可能なのかは、リスト1 の grammar 要素を見て下さい。また、誤認識が起こったときに、(goto 要素などがないにも関わらず)なぜ対話の最初に戻るのか考えてみてください。
  • (2) リスト 1 のticket.vxml に、席種をたずねる対話を追加してください。席種はグリーン・指定席・自由席があるものとします。また、席種の確認も行うように確認の対話も変更してください。
  • (3) 出発駅と到着駅が同じであるかどうかをチェックし、同じであれば「不適切な入力です。」と応答して、対話を最初からやりなおすようにリスト1 のticket.vxml を変更してください。

リスト1(入力済みのファイル ticket.vxml を用意しています。1行目の encoding はエディタ環境および設定によっては UTF-8 などに変更してください)

<?xml version="1.0" encoding="euc-jp" ?>
<vxml version="2.0" xml:lang="ja">
<form id="form1">
<block>
<native>to @AM-MCL set AutoEmotionSpeak = 1</native>
<native>to @AM-MCL set AutoMove = 1</native>
<native>to @AM-MCL set AutoGaze = 1</native>
<native>to @FS-MCL set Background = woman01 bg1</native>
<native>to @AM-MCL set Mask = woman01 HAPPY 100 0 0 0</native>
</block>
<field name="source">
 <prompt>
 こちらは特急券販売システムです。出発駅をどうぞ。
 </prompt>
 <grammar root="#station1">
  <rule id="station1">
   <one-of>
    <item> <token sym="まいくてすと"> マイクテスト </token> </item>
    <item> <token sym="とうきょう" slot="source"> 東京 </token> </item>
    <item> <token sym="しながわ" slot="source"> 品川 </token> </item>
    <item> <token sym="なごや" slot="source"> 名古屋 </token> </item>
    <item> <token sym="きょうと" slot="source"> 京都 </token> </item>
    <item> <token sym="しんおおさか" slot="source"> 新大阪 </token> </item>
   </one-of>
  </rule>
 </grammar>
</field>
<field name="dest">
 <prompt>
 到着駅をどうぞ。
 </prompt>
 <grammar root="#station1">
  <rule id="station1">
   <one-of>
    <item> <token sym="まいくてすと"> マイクテスト </token> </item>
    <item> <token sym="とうきょう" slot="dest"> 東京 </token> </item>
    <item> <token sym="しながわ" slot="dest"> 品川 </token> </item>
    <item> <token sym="なごや" slot="dest"> 名古屋 </token> </item>
    <item> <token sym="きょうと" slot="dest"> 京都 </token> </item>
    <item> <token sym="しんおおさか" slot="dest"> 新大阪 </token> </item>
   </one-of>
  </rule>
 </grammar>
</field>
<field name="num">
 <prompt>
 枚数をどうぞ
 </prompt>
 <grammar root="#maisuu">
  <rule id="maisuu">
    <ruleref uri="#digit"/>
    <ruleref uri="#mai"/>
  </rule>
  <rule id="digit">
   <one-of>
    <item> <token sym="いち" slot="num"> 1 </token> </item>
    <item> <token sym="に" slot="num"> 2 </token> </item>
    <item> <token sym="さん" slot="num"> 3 </token> </item>
   </one-of>
  </rule>
  <rule id="mai">
    <item> <token sym="まい"> 枚 </token> </item>
  </rule>
 </grammar>
</field>
<field name="confirm">
 <prompt>
  <value expr="source"/>駅から
  <value expr="dest"/>駅まで
  <value expr="num"/>枚ですね。
  よろしいですか
 </prompt>
 <grammar root="#yes_no">
  <rule id="yes_no">
   <one-of>
    <item> <token sym="はい" slot="confirm" value="y"> はい </token> </item>
    <item> <token sym="いいえ" slot="confirm" value="n"> いいえ </token> </item> 
   </one-of>
  </rule>
 </grammar>
 <filled>
   <if cond="confirm == 'y'">
     御購入ありがとうございました。
     <goto next="#form1"/>
   <else/>
     もうしわけありません。最初からやりなおして下さい。
     <clear/>
   </if>
 </filled>
</field>
</form>
</vxml>
  • native 要素は Galatea プロトコルによる通信コマンドです

演習の流れ

  • 音声入出力に関する準備
    • ヘッドセットマイク
  • 対話マネージャの基本操作
    • サンプル対話の実行
  • 対話シナリオの変更・拡張
    • VXML ファイルのコピー・編集・実行

準備

  • ヘッドセットマイクの接続
  • 音量の設定
    • スピーカーのアイコン - 「音量調整ツール」
  • 音声の取り込みテスト
$ wavesurfer

実習:手順1

  • Galatea Dialog Studioの実行
$ cp (コピー元ディレクトリ)/form.vxml .
$ galatea-runner form.vxml
  • コピー元ディレクトリは /usr/local/galatea-demo/ など、実習環境に応じて指示します
  • 対話例は後述(マイクOFFのまま)
  • 終了(メニューからは終了できない)
    • ターミナルにフォーカス指定して Ctrl+C

Dialog Studioの操作

  • アドレスボックス / 「Go」
    • 実行中のファイル名または URL を表示
    • ファイル名などを入力して 「Go」 を押すと、指定された対話を開始
    • 実行中の対話があれば終了して実行
  • 「Validate」
    • ファイル内容の文法などをチェック
    • ただし実行時エラーはチェックできない
    • 実行中の対話に影響を与えない
  • 「Run」
    • Pauseで中断中の対話の再開
  • 「Pause」
    • 実行中の対話を一時中断・再開
    • 発話中の場合は、現在出力中の音声などを出力し終えてから待機
    • 注意:すぐに止まらないことがある
  • 「File」 - 「Open Local File...」
    • ダイアログからファイルを指定して実行
  • 「Face」 - 「Texture」/「Wireframe」/...
    • エージェントの表示方法を切替
  • 「Mask」
    • 顔と声を同時に切替える
    • 制約:組み合わせは固定
  • 「Auto」 - 「AutoMove ON/OFF」
    • 顔の制御を実行・停止
  • 「Auto」 - 「AutoGaze ON/OFF」
    • 視線の制御を実行・停止
  • 「Auto」 - 「EmotionSpeak ON/OFF」
    • 感情切替による声の制御を有効化・無効化
  • 「Expression」
    • 感情を切替(AutoMove ON にて有効)
  • 「Demo」 - 「Nod」/「Say Hello」
    • うなずく動作や音声合成のデモ
  • 「Demo」 - 「Demo1」/「Demo2」/「Demo3」
    • 定義済み対話デモ
    • 実行中に内容を閲覧するには、Source タブを使う。

実習:手順2

  • マイクをONにする
  • アドレスボックスを確認 : form.vxml
  • 「Go」 を押して対話

実習:手順3

  • 対話例(form.vxml)
    • ガラティアカフェにようこそ
    • テイクアウトですか?
    • 「はい」「いいえ」
  • お飲み物は何になさいますか?
    • 「コーヒー」「紅茶」
    • 参考:「コーヒーのホット」なども受理可能
  • ホットとアイスのどちらがいいですか?
    • 「ホット」「アイス」

実習:手順4

  • ファイルの実行(演習課題1)
$ cp (コピー元ディレクトリ)/ticket.vxml .
$ galatea-runner ticket.vxml
  • 修正するための準備(演習課題2・3)
$ cp ticket.vxml ticket2.vxml
$ cp ticket.vxml ticket3.vxml

実習:手順5

  • 演習課題1=ticket.vxml(元ファイル)
    • 動作確認(さまざまな駅名や枚数で)
    • grammar要素の確認
  • 演習課題2=ticket2.vxml (コピー)
    • 席種を尋ねる対話とその確認対話を追加
    • グリーン車、指定席、自由席
  • 演習課題3=ticket3.vxml (コピー)
    • 出発駅と到着駅が同じでないようにチェック

実習:手順6

  • ticket2.vxmlの編集(3も同様)
$ emacs

あるいは

$ gedit

修正したファイルの実行

$ galatea-runner ticket2.vxml

注意事項

  • 日本語入力
    • 日本語キーボードの「半角/全角」で切替(環境による)
  • XML の規則(HTML より厳しい)
    • タグの入れ子構造
    • 大文字小文字、全角半角の区別
    • 属性の値は"" で囲む
    • 「Validate」 で確認できる
  • XMLを読みやすくするために
    • <!-- と --> ではさまれた部分はコメント
      • ただし入れ子にはできない
    • 改行や空行・字下げは自由に行ってよい
  • Dialog Studio が 不正終了したら
    • 不要プロセスが残る場合がある
    • 不要プロセスの消去: $ galatea-killall

ヒント

  • field要素のname属性と一致させるもの
    • token要素のslot属性(grammar)
    • value要素のexpr属性(prompt)
  • 出力の<prompt> 要素を省略できない場合
    • <field> の中で用いる場合
    • 属性指定:<prompt bargein="false"> など
    • 読み上げ方を指定する要素を含む場合
      • 日本語テキスト音声合成用記号(JEIDA-62-2000)要素 および W3C 仕様に準拠
  • 値の比較による条件分岐は if 要素で行う
    • cond 属性の中には ECMAScript の式を記述する
<if cond="a == 'x'"> <!-- 変数 a の内容が文字列 'x' と一致する -->
<if cond="a != b">   <!-- 変数 a と変数 b の内容が一致しない -->
<if cond="a &gt; b"> <!-- 変数 a > b である -->
<if cond="a &lt; b"> <!-- 変数 a < b である -->

演習課題2の回答例

<!-- 演習2:field "num" の後に追加 -->
<field name="type">
 <prompt>席種をどうぞ</prompt>
 <grammar version="1.0" root="#seat">
  <rule id="seat">
   <one-of>
    <item> <token sym="ぐりーんしゃ" slot="type"> グリーン車 </token> </item>
    <item> <token sym="していせき" slot="type"> 指定席 </token> </item>
    <item> <token sym="じゆうせき" slot="type"> 自由席 </token> </item>
   </one-of>
  </rule>
 </grammar>
</field>
<field name="confirm">
 <prompt>
  <value expr="source"/>駅から
  <value expr="dest"/>駅まで
  <value expr="type"/>を  <!-- 演習2:この行を追加 -->
  <value expr="num"/>枚ですね。
  よろしいですか
 </prompt>
  • 音声合成エンジン gtalk の辞書で 席種=セキシュ を追加する必要があるかも知れません

演習課題3の回答例

<filled>
   <!-- 演習3:filledに追加(ここから) -->
   <if cond="source == dest">
     不適切な入力です。
     <clear namelist="source dest"/>
   </if>
   <!-- 追加(ここまで) -->
   <if cond="confirm == 'y'">
     御購入ありがとうございました。
   <else/>
     もうしわけありません。最初からやりなおして下さい。
     <clear/>
   </if>
</filled>

実習:手順7(最後)

  • シャットダウンしてください
  • ヘッドセットを回収します