前回に続いてAlexa Conversationsのチュートリアルの続きです。
今回は、"context carry-over"を使った"User correction"に対応してみたいと思います。
目次
"context carry-over"と"User correction"
"context carry-over"と"User correction"とはそもそも何か?会話のサンプルを見てもらえばわかりやすいかと思います。
Alexa, open pet match.
(アレクサ、ペットマッチをひらいて)
Welcome to pet match. I can find the best dog for you. What are two things you’re looking for in a dog?
(ペットマッチにようこそ。あなたにピッタリの犬を教えます。あなたが求める犬の条件を2つ教えてください。)
I want a large family dog.
(大きくて、家族になれるのがいいな)
Do you want a high-energy or low-energy dog?
(活発なのとおとなしいのではどちらがいいですか?)
Low.
(おとなしいやつ)
I recommend a Great Pyrenees.
(それならグレート・ピレニーズがおすすめです。)
(hmm...Great Pyrenees is too big for us...)how about a medium sized dog?
(グレート・ピレニーズかぁ…ちょっと大きすぎるかな…中型犬だとどう?)
Ok, after changing large to medium, I recommend an American Eskimo.
(わかりました、大型犬から中型犬に変更するなら、アメリカン・エスキモー・ドッグがおすすめですね。)
最後の2つの発話のところですね。
- すべての質問を繰り返すことなく
- つまりコンテキストを引き継いでいる。これがcontext carry-over
- サイズだけ置き換えて再度回答する
- 新しいスロット値を置き換えている。これがUser correction
ダイアログモデルで同じことをする場合、dialogStateがCOMPLETEDになるとこれらの情報がなくなってしまうので、必要な場合はセッションアトリビュートなどを活用しないといけないため手間がかかるようですが、このあたりが標準的に想定されているのがAlexa Conversationsのメリットかと思います。
では早速やってみましょう。
ダイアログの変更
ではダイアログを変更してみたいと思います。Alexa ConversationsのDialogsをひらいて、dialog0を変更していきましょう。
以下の会話を追加します。
U: How about a medium sized dog? A: Ok, after changing large to medium, I recommend an American Eskimo.
ではスロットを設定しましょう。ユーザの発話の"medium"をスロットタイプ"size"と紐付けます。変数名がちょっと違いますね、1行目でスロットをセットしたときは"size0"でした。ここは後でわかります。
続けて、ユーザの発話にダイアログアクトを指定します。ここは"Invoke APIs"を選択します。もう一度マルチターンが始まる感じがしますね。
発話セットです。sizeのみのinvokeを処理するAlexa側の発話セットを指定します。つまり、"invoke_getRecommendationSize"になります。
スロットを変数に入れます。ここでは"slot1"でサイズを受け取っているので"slot1"を選択します。
これでユーザの発話は終了です。一旦保存しておきましょう。Alexa Conversationsではマメに保存したほうがいいですね。ビルドはまだしなくてよいです。
次にAlexaの発話です。
まずダイアログアクト、APIの結果を返す部分の発話なので、"Notify Success"を選択します。
APIを設定します。"getRecommendation"ですね。
APIに渡す引数にどの変数を割り当てるかを設定していきます。以下の通り設定します。
注意しないといけないのは、ここでAPIの引数"size"に割り当てるのは新しく追加した"size1"ということですね。このダイアログでいうと、1行目のユーザの発話時点でsize0に変更前のsizeが入っています。size1は5行目の発話で受け取ったユーザが変更したsizeスロットを指す変数です。それに対し、つまり古い情報はこのセッションの中で記憶されていて、新しい情報と組み合わせて、再度APIにリクエストを送るということになるわけですね。
また、return Type -> Variablesのところも"getRecommendationResult1"になっています。4行目では"getRecommendationResult0"になっていました。つまりAPIレスポンスも前回とは別の新しい変数として受け取るようにしておけば、前回の結果を保持できるということですね。
で、最後にレスポンステンプレートです。ここは4行目と同じ"notifySuccess_getRecommendation"を使うこともできるのですが、コンテキストを維持しているということがわかるように別のレスポンステンプレートを作りましょう。"Create New Response"を選択します。
この場合は、レスポンステンプレートのメニューに行かなくても、シームレスに作成ができるみたいですね。"notifySuccess_getRecommendation_context_carry_over"というレスポンステンプレート名にします。
で下にスクロールして、レスポンステンプレートに渡す引数を設定していきます。"Add a new argument"をクリックして、以下の3つの引数を作成してください。
ここで3つの引数を作成したのは、このダイアログの発話を見てもらえればわかるかと思います。
A: Ok, after changing large to medium, I recommend an American Eskimo.
つまり、ここにスロットを当てはめるとこうなります。
A: Ok, after changing {oldSize} to {newSize}, I recommend a {getRecommendation.name}.
変更前のサイズと変更後のサイズ、そして結果セットの名前がAlexaからのレスポンスとして返されるので、これを引数として指定するわけですね。
もうおわかりかと思いますが、これをレスポンステンプレートの発話として登録していけばよいですね。上にスクロールして"Audio Response"のドロップダウンから"Create a new prompt"を選択します。
プロンプト名も"notifySuccess_getRecommendation_context_carry_over"にします。
レスポンステンプレートのメニューから新規作成ではなく、ダイアログ内からレスポンステンプレートを作るとダイアログの発話がそのまま入っちゃうのですね。こっちのほうがスロット割り当てもそのままできるのでいいかもですね。では発話の部分をスロットに置き換えていきましょう。そろそろ慣れてきましたよね。
こんな感じになっていればOKです。「保存」して「Save」してください。
ダイアログの画面に戻って、テンプレートが必要とする引数にどの変数を割り当てるかを設定します。一番下はちょっと見えないですが、2回目のAPIリクエストの結果をレスポンステンプレートに渡すので、上のAPIの結果が入っている"getRecommendationResult1"を選択してください。
で、最後にもう一つ。API定義にレスポンステンプレートを紐付けます。前回やったときは特に意識してなかったんですが、これなんでやらないといけないんでしょうね・・・ダイアログが中心になって他のコンポーネントを紐付けるのに、コンポーネント同士を紐付ける意味がわからないな・・・ま、とりあえず、APIの横の鉛筆アイコンをクリックします。
"getRecommendation" のAPI定義が開きます。下の方にあるレスポンステンプレートで "notifySuccess_getRecommendation" が紐付いていると思うんですが、ここに "notifySuccess_getRecommendation_context_carry_over" も追加して、「保存」します。
これで終了です。「Save」「モデルをビルド」をクリックしてビルドします。
テスト
こんな感じでうまくいきました。
違うダイアログのパターンでも動作しますね。
ただ、他のスロットの言い換えは別途設定しないといけないようです。
まとめ
前回のチュートリアルで一通り触ったので、correctionはすんなり理解できたような気がします。これはとても便利ですね。