Alexa Conversationsのチュートリアルやってみたの第3回です。
今回は、APIからの結果を別のAPIに渡すというのを同じコンテキストの中でやってみたいと思います。
目次
サンプルのダイアログ
"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 dog with high energy.
(大きくて、活発なのがいいな)
Do you want a dog that is good with family or better at guarding?
(人懐っこいのと、番犬向きとどちらがいいですか?)
Family.
(人懐っこいやつ)
Okay, in that case I recommend a Chihuahua.
(それならチワワがおすすめです。)
What is that?
(それってどんなやつ?)
The Chihuahua is one of the smallest dog breeds, bred in the Chihuahua region of Mexico...
(チワワは、メキシコのチワワ地方で生まれた小型犬種の1つです。...)
ちょっと文章と回答があってないのは気にしないでください。ポイントは、4行目でAPIにおすすめ犬種をリクエストしたあと、その犬種を元にして、6行目でさらに犬種の説明をAPIから取得する、ということですね。
前回の"context carry-over"と同じく、ダイアログモデルで同じことをする場合にはセッションアトリビュートを使う必要があり、かつ、こういった機能を増やしていくとその機能ごとに実装が必要になります。ということでAlexa Conversationsならこれがシンプルにできるということみたいですね。やってみましょう。
ダイアログの編集
今回もまずダイアログを修正していきます。Alexa ConversationsのDialogsをひらいて、dialog1の「編集」をクリックします。
以下の会話を追加しましょう。
U: What is that? A: A chihuahua is ...
とりあえず保存しておきましょう。
スロットタイプの作成
今回、ユーザの発話についてはスロットのアノテートは行う必要はありません。ユーザの発話にはスロットが含まれないからですね。 逆にAlexaの発話にはスロットのアノテートが必要です。こちらはAPIから犬種の説明という新しい情報が入っているからですね。Alexa ConversationsではAPIからの戻りの型もスロットタイプとして定義します。左のメニューから「スロットタイプ」メニューを開いて「+スロットタイプ」をクリックします。
まず、普通に犬種の説明が入るスロットタイプを作成します。"Create a custom slot type with values"を選択して、スロットタイプ名は"stringLiteral"にします。"Next"をクリックします。
スロット値は"dummy"と入れておきます。ユーザの発話ではなく、APIから文字列を取るだけなのでこういう使い方なんでしょう。スロット値を登録したら"Save"します。
もう一つ、今度はAPIのレスポンスを入れておくためのスロットタイプを作成します。"Create a custom slot type with properties"を選択、スロットタイプ名は"getDescriptionResult"とします。"Next"をクリックします。
"Add a new property"をクリックして、プロパティ名は"description"、スロットタイプはさきほど追加した"stringLiteral"を選択します。最後に"Save"してください。
発話セット
5行目のユーザの発話に対して、発話セットを設定していきましょう。これはダイアログ画面からインラインでも編集ができます。ダイアログメニューからdialog1をひらいてください。
"What is that?"をクリックすると、右にメニューが出てきます。まずダイアログアクトです。これはAPIを再度実行するので"Invoke APIs"を選択します。
発話セットを選択するドロップダウンから"Create New Utterance Set"を選択します。
発話セットの作成画面がインラインで開きますので設定していきます。発話セット名は"invoke_getDescription_recommendationResult"にします。APIはちょっと置いといてください。
下にスクロールして、以下のサンプル発話を登録していきます。一つづつ登録しても良いですし、バルクインポートしてもいいですね。登録したら"Save"します。
what's that what is that what is it what tell me about that
ダイアログのページでも"Save"しておいてください。
API定義
では、犬種の説明を行うAPIを定義していきましょう。ダイアログの6行目をクリックして、右のメニューで、ダイアログアクトは"Notify Success"、APIは"Create a new API"を選択します。
インラインでAPI新規作成画面が開きました。新しいAPI名は"getDescription"にします。
次に引数です。犬種の説明のためには犬種名が引数として必要になりますが、これは最初のAPIで取得した"getRecommendationResult"に入っていますので、それをそのまま渡すことができます。つまり、"context carry-over"がここでも有効になるわけですね。 "Add a new argument"をクリックして、引数名に"getRecommendationResult"、スロットタイプも"getRecommendationResult"を選択します。
次にレスポンステンプレートを作成しますが、ここはちょっとスキップして、APIからの戻り値の型を設定しましょう。ここが先ほど作成した"getDescriptionResult"になります。選択したら「保存」します。
では変数と引数のマッピングです。最初のAPIの結果は変数"getRecommendationResult0"に入っているのでこれをAPI引数として渡して、結果を"getDescriptionResult0"で受け取ります。このあたり、もうスロットなのか変数なのか引数なのか、よくわからなくなってきますね・・・
API定義ができたので、発話セットでスキップしていたAPIを設定しましょう。5行目のユーザの発話をクリックして、右のメニューに設定されている発話セット"invoke_getDescription_recommendationResult"の横の鉛筆アイコンをクリックして、発話セットを編集します。
発話セットの設定画面で、ダイアログアクト"Invoke APIS"の横のAPIに"getDescription"を選択して"Save"します。
これで残りはレスポンステンプレートだけです。
レスポンステンプレート
最後にAPIからの結果を受けて、Alexaが発話するためのレスポンステンプレートを設定します。ダイアログの最後の行をクリックして、右のメニューの一番下、レスポンスのドロップダウンから "Create a new response" を選択します。
レスポンステンプレート設定画面がインラインで開きますので、まずテンプレート名を"notifySuccess_getDescription"にしましょう。
サンプル発話を登録する前に、下にスクロールしてArgumentsで引数を設定します。"Add a new argument"をクリックして、スロットタイプ"getDescriptionResult"で引数名も同じに設定します。
ではサンプル発話の登録です。上にスクロールして、Audio Responseのドロップダウンから"Create a new prompt"を選択します。
プロンプト名は"notifySuccess_getDescription"とします。で、ダイアログに入力していた"A Chihuahua is ..." というのがサンプル発話として登録されていると思いますが、これを全選択して、スロットタイプ"getDescriptionResult.description"として設定します。
「保存」して「Save」します。
ダイアログの画面に戻ったらレスポンスに渡す引数と変数のマッピングができるようになっているので、上のAPIから受け取った結果の変数である"getDescriptionResult0"を選択します。
あと、もう一つ、レスポンステンプレートはAPI定義と紐付けないといけないんでした。"APIs to call" で "getDescription" が選択されている右横の鉛筆アイコンをクリックします。
API定義の画面が開いたら、レスポンステンプレートで"notifySuccess_getDescription"を選択して"+"をクリックして紐付けます。
紐付けが終わったら「保存」します。
対話モデルはこれで終了です。"Save"して"モデルをビルド"してください。
バックエンド
最後にバックエンドコードに犬種の説明を返すAPIを追加します。コードエディタでindex.jsを開いて、以下のハンドラをGetRecommendationAPIHandlerの前あたりに入れてください。
const GetDescriptionAPIHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'Dialog.API.Invoked' && handlerInput.requestEnvelope.request.apiRequest.name === 'getDescription'; }, handle(handlerInput) { const recommendationResult = handlerInput.requestEnvelope.request.apiRequest.arguments.getRecommendationResult; // setting the default response. let databaseResponse = `I don't know much about ${recommendationResult.name}.`; const energy = recommendationResult.energy; const size = recommendationResult.size; const temperament = recommendationResult.temperament; // setting the actual response if we find a match for their preference if (energy !== null && size !== null && temperament !== null) { const key = `${energy}-${size}-${temperament}`; databaseResponse = data[key]; } const descriptionEntity = { description: databaseResponse.description }; const response = buildSuccessApiResponse(descriptionEntity); console.log('GetDescriptionAPIHandler', JSON.stringify(response)); return response; } };
リクエストタイプとapiRequest.nameについては前々回お話したとおりなので割愛します。今回はAPI名が"getDescription"ということですね。
recommendationResultに1回目のAPIでおすすめ犬種を取得した時の情報が入ってます。そっか、PetMatch.jsonは、キーが"${energy}-${size}-${temperament}"でしたね、すっかり忘れてて犬種名で引くものだと思ってました、失礼しました。recommendationResultからそれぞれの情報を取り出して、キーを生成して、オブジェクトを検索して、マッチしたものからdescriptionを引っ張って返す、ということですね。getRecommendation API同様とてもシンプルです。
あと、skillBuilderハンドラにGetDescriptionAPIHandlerハンドラを登録するのをお忘れなく。
exports.handler = skillBuilder
.addRequestInterceptors(RequestInterceptor)
.addRequestHandlers(
GetDescriptionAPIHandler, // 追加
GetRecommendationAPIHandler,
IntentReflectorHandler,
SessionEndedRequestHandler
)
.addResponseInterceptors(ResponseInterceptor)
.addErrorHandlers(ErrorHandler)
.lambda();
「保存」「デプロイ」します。
これで終了です。ではテストしてみましょう。
テスト
ちゃんと動いてますねー。マルチターンのコンテキストがかんたんに維持されて、新しい機能につなげることができるというのがわかった気がします。
Alexa Conversationsのチュートリアルを3回に渡ってご紹介しました。Alexa Liveのときも少し思ったのですが、実際に触ってみるのが一番理解が早いですね。Alexa Conversationsは複数のコンポーネントに分かれていて最初は非常に複雑な感があるので、とりあえず手を動かしてやってみることをおすすめします。
(とはいいつつ、まだ日本には来てないのですが・・・)