kun432's blog

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

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

Voiceflowにおける会話のコンテキストを考える ④文脈に沿ったインテント

f:id:kun432:20200724191613p:plain

ちょっと間が空きましたが「Voiceflowにおける会話のコンテキストを考える」シリーズの第4回です。今回は「文脈に沿ったインテント」です。

この記事は「Voiceflowにおける会話のコンテキストを考える 」シリーズの第4回の記事です。他の記事は以下にあります。よろしければあわせて読んでみてください。

第1回 第2回 第3回 第4回(この記事) 第5回 第6回

目次

文脈に沿ったインテントとは?

コーヒーショップのやりとりを一度振り返ってみましょう。

いらっしゃいませ。ご注文は何になさいますか?

コーヒーを一つ。

砂糖とミルクはおつけしますか?

お願いします

このやり取りの中でユーザが発話を求められるのは2回あります。

いらっしゃいませ。ご注文は何になさいますか?

砂糖とミルクはおつけしますか?

ですね。この2つは微妙にコンテキストが違うというのは第1回でお伝えしました。前者は「何の飲み物を注文するか?」を確認するコンテキスト、後者は「飲み物がコーヒーの場合に追加するものはなにか?」というコンテキストです。これらのコンテキストは連続性はあるものの微妙に異なりますよね。

で、仮にそれぞれの質問に対して、ユーザがどう答えていいかわからなかったとしましょう。こういった場合、アレクサではおなじみの「使い方を聞く」ためのインテント「Help」インテントを使いますが、それぞれコンテキストが異なるので、「ヘルプ」の意図も変わります。

  • 「何をご注文しますか?」に対して、ユーザが「ヘルプ」といった場合

いらっしゃいませ。ご注文は何になさいますか?

(何を注文できるんだろう・・・どういう言い方で注文すればよいのかがわからないな・・・)

  • コーヒーを注文したあと、「砂糖とミルクはおつけしますか?」に対して、ユーザが「ヘルプ」といった場合

砂糖とミルクはおつけしますか?

(ミルクだけほしいんだけど、なんて言えばいいのかな?)

同じ「ヘルプ」だったとしても、ユーザが期待している回答は違いますよね。おそらくこういう感じにすればユーザは回答の仕方が理解できると思います。

  • 「何をご注文しますか?」に対して、ユーザが「ヘルプ」といった場合

いらっしゃいませ。ご注文は何になさいますか?

(何を注文できるんだろう・・・どういう言い方で注文すればよいのかがわからないな・・・)ヘルプ!

当店では、コーヒー、紅茶、オレンジジュースを取り扱っております。例えば、コーヒーをちょうだい、と言ってみてください。

じゃあ、コーヒーをちょうだい

  • コーヒーを注文したあと、「砂糖とミルクはおつけしますか?」に対して、ユーザが「ヘルプ」といった場合

砂糖とミルクはおつけしますか?

(ミルクだけほしいんだけど、なんて言えばいいのかな?)ヘルプ!

例えば、砂糖とミルクの両方をおつけしてよろしければ「はい」、砂糖だけなら「砂糖だけ」、どちらも不要であれば「いらない」というふうに言ってみてください。

じゃあ、ミルクだけ

同じインテントでもコンテキストによって意図するものは違うので、それにあわせて返事が変わるのはとても自然なことですよね。

Flow Block

どうすれば文脈に応じて「ヘルプ」を使い分けることができるでしょうか?

第2回でやった「コマンド」は、「どのコンテキストから」でも呼び出せて、常に同じ動き回答を行って、それが終わったら呼び出した場所に「戻る」という便利なものでした。しかし、逆に言うと、コンテキストのどこで呼んだとしても同じことになしか使えません。プログラミングの世界では、これを「グローバル」といったりします。(”世界中”のどこからでも参照できるというようなところから来ています。)

f:id:kun432:20200914214607p:plain

逆に言うと、「グローバル」の反対に、特定のコンテキストの中だけで有効になる、いわば「ローカル」(”世界中”に対して、”地方”ということですね)な呼び出しができればいいということですね。そこで使えるのが「Flow Block」です。

では早速やってみましょう。

Condition Blockの後ろにつながっている、「コーヒーに追加するものを聞く」コンテキストと「紅茶に追加するものを聞く」コンテキストへの線を外します。

f:id:kun432:20201204000146p:plain

「コーヒーに追加するものを聞く」コンテキストのブロックと「紅茶に追加するものを聞く」コンテキストのブロックを少し右へずらして、ブロックを入れるスペースを空けましょう。ドラッグで複数のブロックをまとめて選択します。

f:id:kun432:20201204000841p:plain

どれか一つのブロックを右にドラッグするとまとめて移動ができます。

f:id:kun432:20201204001020p:plain

この空いたスペースに、左のブロックメニューの"Logic"の一番下にある「Flow Block」をに2つ並べてください。

f:id:kun432:20201204001319p:plain

では、まず「コーヒーに追加するものを聞く」コンテキストのほうから設定していきましょう。上のFlow Blockをクリックするとメニューが表示されますので、入力欄に"coffee_flow"と入力して"Create"をクリックします。

f:id:kun432:20201204001849p:plain

"coffee_flow"が設定されました。で、そのまま待っていると・・・

f:id:kun432:20201204002817p:plain

画面が変わりましたね!これがFlow Blockによって作られた新しいフローになります。ブロックが全部なくなってしまったように見えますが、安心してください!

f:id:kun432:20201204003006p:plain

もしかするとこういう画面が出てくるかもしれませんが、"Return"をクリックして、上の画面になっていればOKです。 f:id:kun432:20201204002903p:plain

新しいフローの画面を見ると、下の方に"coffee_flow"という文字が見えていて、coffee_flow専用画面であることがわかります。

f:id:kun432:20201205180430p:plain

左のブロックメニューの"FLOWS"タブをクリックすると先ほど作成した"coffee_flow"以外にもHelpやStopのフローも見えますね。そしてその上に"Home"というアイコンも見えます。Homeをクリックしてみましょう。

f:id:kun432:20201205180703p:plain

はい、最初に作ったフローは見えています。ちなみに最初からできているフローを"Root Flow"といいます。Flow BlockはメインであるRoot Flowとは別のフローを作るために使います。

f:id:kun432:20201205181311p:plainf:id:kun432:20201205181408p:plain

ではメインのフローからつなげてみましょう。Condition Blockの条件から2つのFlow Blockへ線を引きます。

f:id:kun432:20201205181408p:plain

次に「コーヒーに追加するものを聞く」コンテキストにつながっていたブロックを範囲選択します。

f:id:kun432:20201205181742p:plain

Ctrl+Cでコピーします。

f:id:kun432:20201205181830p:plain

コピーできたらcoffee_flowに移動しましょう。別のフローに移動するには、いくつかやり方があります。1つ目はFlow Blockをクリックして、メニューからEnterをクリックします。

f:id:kun432:20201205182110p:plain

もう1つの方法は左のブロックメニューの"FLOWS"タブをクリックして、行きたいフローをクリックします。お好きな方でどうぞ。

f:id:kun432:20201205182328p:plain

coffee_flowに移動したら、キャンバス上でCtrl+Vでペーストしてください。さきほどコピーしたブロックがcoffee_flow内にコピーされます。

f:id:kun432:20201205182605p:plain

coffee_flowに最初からあるブロックとつなげます。左上のHomeアイコンをクリックしてつなげたらRoot Flowに戻りましょう。

f:id:kun432:20201205183030p:plain

Root Flowに戻ったら、cofee_flowにコピーした、「コーヒーに追加するものを聞く」コンテキストのブロックは不要ですので削除してください。範囲選択してDeleteキーでまるっと消せます。

f:id:kun432:20201205183631p:plain

f:id:kun432:20201205183642p:plain

f:id:kun432:20201205183652p:plain

同じように「紅茶に追加するものを聞く」コンテキストもtea_flowを作成してブロックをコピーしてください。ここは詳細を割愛します。

f:id:kun432:20201205184500p:plain

f:id:kun432:20201205184741p:plain

f:id:kun432:20201205184904p:plain

f:id:kun432:20201205185135p:plain

f:id:kun432:20201205185312p:plain

Flow Blockの動きがわかりやすいように少しおまけでブロックを追加します。Speak Blockを右端に1つおいて、スキル終了のメッセージを入れておきます。そして、追加した2つのFlow Blockと、元々ある「オレンジジュース」のコンテキストからつなげておきます。

f:id:kun432:20201205185632p:plain

開発者コンソールにアップロードしてテストしてみましょう。実は最近デザインが変わりました。右上の青いボタンはVoiceflow独自のテストシミュレータである「Prototype」になりました。開発者コンソールへのアップロードはその左にあるリサイクルマークのようなアイコンをクリックします。(Prototypeはちょっと日本語がうまく扱えないので・・・)

f:id:kun432:20201205190003p:plain

テストの結果です。コーヒー、紅茶、オレンジジュースそれぞれの結果を見てください。

f:id:kun432:20201205210603p:plainf:id:kun432:20201205210603p:plain

f:id:kun432:20201205210616p:plain

f:id:kun432:20201205210624p:plain

Flow Blockに分けたものもきちんと動いてますね。このようにFlow Blockを使うと、メインのフローからFlow Blockで作った別のフローにつなげることができます。ブロックがたくさん増えると見にくくなったりするので、処理ごとにフローを分けて管理しやすくできます。

そして、もう一つ注目してほしいのはここです。

f:id:kun432:20201205211011p:plain

f:id:kun432:20201205211026p:plain

f:id:kun432:20201205211038p:plain

Flow Blockの処理が終わった後は、メインのフローに戻ってきて、最後のSpeak Blockが話されているのがわかるでしょうか?図にするとこういう感じになります。

f:id:kun432:20201205231701p:plain

Flow Blockを使うと別のフローが作成され、メインであるRoot Flowから移動ができて、かつ、処理が終わったら戻ってくるということですね。これがFlow Blockの使い方になります。

Flow Blockを使ったコンテキストに沿ったインテント

で、ここまでだと単にFlow Blockの使い方になりますが、今回はコンテキストごとに同じインテントを使い分けるのが目的でした。ここからが本題です。早速やってみましょう。

まず、coffee_flowに移動します。ブロックメニューの"FLOWS"タブをクリックして、"coffee_flow"をクリックします。

f:id:kun432:20201205182328p:plain

coffee_flowに移動したら、第2回でやった「コマンド」を追加します。

f:id:kun432:20201205233026p:plain

コマンドの設定が開きます。まず、コマンドの名前は"coffee_help_command"にしておきましょう。

f:id:kun432:20201205233332p:plain

対応するインテントは、ビルトインの"Help"を選択します。

f:id:kun432:20201205233346p:plain

コマンド名とインテントを設定したら、"Enter Flow"をクリックします。

f:id:kun432:20201205233456p:plain

またFlowの画面が表示されましたが、これはさきほど作成したコマンド"coffee_help_command”のフローです。ここまで来るとおわかりになるかもしれませんが、「コマンド」もまたFlowで実現されています。

f:id:kun432:20201205234251p:plain

ではSpeak Blockをおいて「ヘルプ」といった場合のメッセージを入力しましょう。ここは「コーヒーに追加するものを聞く」コンテキストなので、こんな感じで設定します。

f:id:kun432:20201205234056p:plain

あとは、同じやり方でtea_flowの中でも"tea_help_command"を作成すればよいのですが、Flowの中にコマンドがある場合とない場合でどう違うのかを確認するために一旦おいておきましょう。

メインのRoot Flowにある、"Help"コマンドのフローはこんな感じで設定しておきます。

f:id:kun432:20201205234958p:plain

f:id:kun432:20201205235010p:plain

ではテストです。コーヒーを注文して、なにか聞かれたら一旦「ヘルプ」で聞いてみましょう。

f:id:kun432:20201205235423p:plain

コンテキストに応じて「ヘルプ」に対する応答が違いますね!「ヘルプ」というインテントが複数箇所にあっても、Flow Blockを使うとメインのフローとFlow Block内のフローで使い分けができるということですね。メインのフローにある「ヘルプ」は「グローバル」で、Flow Block内にある「ヘルプ」はそのFlow Blockの中でしか使えない「ローカル」な「ヘルプ」ということができるわけです。

Flow Block内に「ヘルプ」コマンドを設定しなかった「紅茶」も注文して、こちらもなにか聞かれたら「ヘルプ」で答えてみます。

f:id:kun432:20201205235849p:plain

こちらは「ヘルプ」といった場合にどちらも「グローバル」な「ヘルプ」として扱われていますね。Flow Block内に「ヘルプ」がなければ、グローバルな「ヘルプ」が呼び出されるというわけです。

まとめ

いかがでしたか?Flow Blockはちょっと抽象的な概念なので、Voiceflowを使い始めた頃だと少し難しく感じるかもしれません。ただ今回のように、同じインテントであってもコンテキストに沿った形で応答を変えることができると、通り一遍等ではない、とても人間らしい感じが実現できます。ぜひチャレンジしてみてください。

ちなみに、Flow Blockを使うと、

  • どこからでも呼べるグローバルな変数、Flow Block内でしか使えないローカルな変数の使い分け
  • グローバルな変数をFlow Block内のローカルな変数として受け渡し(プログラミングでいう関数の引数みたいなもの)
  • Flow Blockの中にFlow Blockを置く、といったフローの階層化

もできたりします。メインのRoot Flowで全てをやろうと思うと変数をたくさん作りがちになり、見通しが悪くなって、その結果変数の使い方を間違ったりもしがちです。Flowで処理を分割することでより安全・効率的なスキル開発ができますので、スキルの規模が大きくなったり複雑になってきたら積極的に使っていきたい機能です。

次回は「スロットによるコンテキスト」です。

続きはこちら