kun432's blog

Alexaなどスマートスピーカーの話題中心に、Voiceflowの日本語情報を発信してます。たまにAWSやkubernetesなど。

〜スマートスピーカーやVoiceflowの記事は右メニューのカテゴリからどうぞ。〜

Voiceflow TIPS #34 Voiceflowのここがイケてない/わかりにくい・Choice Block編

久々のAdvent Calendar延長戦です。今回はVoiceflowでハマりやすいブロックの一つであるChoice Blockについて、ハマリポイントと回避方法について説明したいと思います。

Choice Blockとは?

Choice Blockは、シンプルにユーザの発話を受け取って、分岐させるためのブロックです。サンプルを見てください。

f:id:kun432:20191008000121p:plain

このサンプルでは、フルーツジュースの注文を聞いて、注文された内容に応じて発話を分岐させる処理を行っています。Interaction Blockを使った場合はインテント、サンプル発話、スロット、シノニムなど、細かい対話モデルを設計することになりますが、Choice Blockではそういったことは意識することなく、単純な発話内容をもとにシンプルに分岐させることができます。実際の動きはこんな感じになります。

f:id:kun432:20191008000639p:plain

インテントやサンプル発話を使っていないので、幅広いユーザの発話バリエーションに対応するには手間がかかりますが、シンプルな回答を想定するのであれば全然問題ないですよね。

想定していない注文が来た場合もElseに流して再度聞き直すようなフローになっているので、問題ないように思えます。

f:id:kun432:20191008001013p:plain

実際に見てみましょう。

f:id:kun432:20191008001205p:plain

あれ?想定していない注文が両方ともオレンジジュースになってしまいました・・・Elseに行かないですね・・・・

Choice Blockのハマりポイント① Elseが動作しない

これが1つ目のハマリポイントです。Choice Blockは、現状Elseが正しく動作しません。ではなぜ動作しないのでしょうか?Alexa開発者コンソールの対話モデルを見てみましょう。

f:id:kun432:20191008001723p:plain

ランダムな文字列のインテントが3つ作成されています。Voiceflowではユーザの発話を取るブロックを使うとこのようにAlexa開発者コンソール側にインテントを作成します。それぞれのインテントの中身を見てみましょう。

f:id:kun432:20191008002038p:plainf:id:kun432:20191008002047p:plainf:id:kun432:20191008002055p:plain

Choiceの分岐の数だけ、インテントとサンプル発話が作成されているのがわかります。ただ、この設定だと、Choiceの分岐に用意されていない選択肢はインテントが用意されていないので、紐付くインテントがないことになります。紐づくインテントがなければスキルは終了してしまいますので、こういう場合、Alexaはなんとかしてどれかのインテントに紐付けようとします。つまり、誤ったインテントに紐付いてしまう場合があるということなのですね。

これを回避するには、Choiceで予め用意していない発話がされた場合、なんでもかんでも紐づくような別のインテントを無理やり用意してやればよいです。Intent Blockを適当に起きます。

f:id:kun432:20191008010418p:plain

Intent BlockでIntentを作成し(ここではすべてを拾うという意味で "catchall_intent" と名付けています)に以下のようなサンプル発話を入力してやります。(書いてあることは意味不明なのですが、これは昔某サービスであらゆる発話を一つのインテントに紐付けるために取っていたやり方で、実は意味があるんだろうと思います。)

f:id:kun432:20191008010429p:plain

Choicesでcatchall_intentを選択します。線を引く必要はありません。

f:id:kun432:20191008010440p:plain

はい、これでテストしてみたいと思います。

f:id:kun432:20191008011351p:plain

はい、いちごジュースではElseが動作するようにはなりました。Choiceで用意されているインテントに紐付かずに別のインテントに紐づく、つまり、Elseに流れたということですね。

ただし、これをやってもまだメロンジュースは誤ってオレンジジュースのインテントに紐付いていますね?つまり、この方法は完璧ではないということです。特に今回のように、正しく認識するためのサンプルが少ない場合(Choiceの発話だけしかない)は非常に誤認識が起きる確率が高くなります。

したがって、可能な限り誤認識を抑えつつ、ユーザの発話を取得して分岐させる正しい方法は、きちんとインテント・サンプル発話・スロットを設計することになります。一例です。

f:id:kun432:20191008225352p:plain

Interaction Blockで、可変となる部分のみスロットを使います。今回はカスタムスロットタイプにしていますが、ビルトインスロットタイプが使える場合はそちらのほうが認識率は上がると思います。

f:id:kun432:20191008225729p:plain

サンプル発話も、ジュースの名前そのものだけじゃなくて、きちんとフレーズを用意していろんな言い方に対応できるようにします。

f:id:kun432:20191008225827p:plain

インテントをフローにつなげて、スロットを変数に入れます。

f:id:kun432:20191008225905p:plain

インテントに合致しない場合は、具体的なエラーではなく、少しざっくりとしたエラーを返すようにしておきます。きちんとしたエラーは後で説明します。

f:id:kun432:20191008230043p:plain

変数で渡されてきたスロット値をIf Blockで想定している値かどうかをチェックしつつ分岐させます。

f:id:kun432:20191008230331p:plain

想定していない値が渡ってきた場合は、If BlockのElseで具体的なエラーとして返しつつ、発話の候補をユーザに促します。

f:id:kun432:20191008230559p:plain

あとは同じなので割愛します。Choice Blockを使った場合と違って、きちんとやろうと思うと結構手間がかかることがわかるでしょうか。

Choice Blockではこういう細かい設計を省くことができる反面、正しく認識するための情報やチェックがどうしても甘くなってしまうので、誤った動作をしがちです。特にElseが正しく動かない場合があるというのは致命的で、公開に向けて審査に通す場合にはリジェクトされる可能性が高いので、注意してください。

Choice Blockのハマりポイント② はい/いいえを使う場合におかしくなる

最初の例では、あえてChoice Blockを使ったのですが、あえて使わなくてもデフォルトでChoice Blockが使われている箇所があります。Help Flowがそうです。

f:id:kun432:20191008231408p:plain

Voiceflowのヘルプは少し変わっているという話は、Voiceflow TIPS #10 Voiceflowのヘルプインテント - kun432's blog でも紹介しました。そのときには説明しなかったのですが、ヘルプフローに入った後、元のフローに戻るかどうかを「はい」「いいえ」で聞くところでChoice Blockは使われています。

f:id:kun432:20191008232906p:plain

で、見てもらうと分かる通り、ここ、日本語でスキル作成したとしてもデフォルトで英語になっているのですね。ただ、ここ英語に直さなくても動作します。なぜかというところで、開発者コンソールを見てみましょう。

f:id:kun432:20191008233342p:plain

最初の例で、Choice Blockで分岐を作ると、(カスタム)インテントが作成されるという話をしました。が、見て分かる通り、先程Interaction Blockで作ったカスタムインテント以外にはインテントはありません。では、「yes」「no」はどこに行ったかというと、

f:id:kun432:20191008233632p:plain

f:id:kun432:20191008233643p:plain

はい、標準ビルトインインテントであるYesIntent、NoIntentとして登録されているのですね。つまり、「yes」「no」は、Choice Blockの分岐として登録したとしても特別な扱いになるということです。なので、サンプル発話として日本語で「はい」「いいえ」を言ったとしても動作するというわけです。

ただ、見てもらうと分かる通り、「はい」は登録されているけど、「いいえ」は登録されていませんし、そもそも英語で「Sure」「Okay」なども勝手に登録されていて、英語のサンプル発話が登録されていると審査でリジェクトされる可能性がありますので、全部日本語に直したくなりますよね。また、最初の例で言ったとおり、Choice BlockではElseが動作しないので、「はい」「いいえ」以外の発話がきたとしても誤ってどちらかで認識される可能性があります。

なので、これもInteraction Blockを使います。インテント設計とかしないといけないのはめんどくさいなーと思われた方もいらっしゃるかもしれませんが、「はい」「いいえ」のような標準で用意されているビルトインインテントの場合は、Interaction Blockで簡単に設定ができます。実際にヘルプフローを直してみましょう。

Speak BlockとChoice Blockがコンバインブロックになっているのでこれを一旦ほどきます。

f:id:kun432:20191008235536p:plain

Choice Blockを消して、Interaction Blockを置きます。

f:id:kun432:20191009001115p:plain

IntentsやSlotsは設定不要です。Choicesで分岐を追加、ドロップダウンから"YesIntent"を選択します。

f:id:kun432:20191009000409p:plain

同様に"NoIntent"を選択します。

f:id:kun432:20191009000057p:plain

最後に線でつなぐだけです。

f:id:kun432:20191009000141p:plain

これだけです。いちいち英語のものを日本語に直す必要もないですし、「はい」「いいえ」のバリエーションも登録する必要ありません。非常にかんたんですよね。あと、以外の場合の処理をElseに入れてもいいと思います。

これ以外にも標準ビルトインインテントは多数あります。Choice Blockに自分で登録するのも手間ですし、間違って他のビルトインインテントで予め設定されている発話を登録したりする可能性もあります(審査で必ずリジェクトされますし、最近実装された「発話の競合」チェックで弾かれます)。Interaction Blockから選択するほうがかんたんで確実です。

標準ビルトインインテントについては公式ドキュメントを参照することをおすすめします。


Choice BlockはVoiceflow初期からあるブロックで非常にシンプルに使えますし、Voiceflowをこれから始めるという人にとっても理解しやすいですが、上記のように見た目よりも中身は複雑になっていて、正しく動かない場合がある、審査に通らない可能性がある、というようなハマリポイントが結構あり、個人的にも以前からChoice Blockにはいろいろと手を焼かされてきたので、少しおすすめしにくい印象を持っています。なので、公開せずに自分だけで使うとか、ちょっとぐらい正しく動かなくてもよいからサクッと作ってしまいたい、というような場合なら問題ないかなと思います。

Interaction Blockの場合、インテント・サンプル発話・スロット・変数等の概念を理解するのが最初のうちはハードルになると思いますし、設計等も多少必要になるので手間がかかって難しいという印象があるかもしれませんが、慣れてしまえばそこまで難しいものでもないと思いますし、細かく制御できて正しく動く・正式に公開するということを踏まえると、やはりこちらのほうがおすすめですね。

最初のうちはChoice Blockで、慣れてきて公開したくなったらInteraction Block、という感じで、徐々にステップアップしていただければと思います。