前回の記事では、ダイアログモデルを使用したスロットの確認について、コーヒーショップサンプルスキルを拡張し、Dialog.ConfirmSlotディレクティブを使用して動的にスロットを確認する方法を説明しました。ユーザーがコーヒーを注文したら、スキルのバックエンドがDialog.ElicitSlotディレクティブを返し、flavorスロットを引き出します。flavorには50円の料金がかかるため、Dialog.ConfirmSlotディレクティブを使用して追加料金の了承を得ます。
記事の最後で、問題が発生する可能性があることを指摘しました。ユーザーが水を頼んだらどうしたらよいでしょうか? 飲み物ならまだいいですが、野球やユニコーンやランプを頼まれた場合はどうでしょうか? 有効な値を指定するように、ユーザーに再プロンプトする必要があるでしょう。
何かデータを検証する方法が必要ですね。自分ならどのように問題を解決するか、ぜひ考えてみてください。前の記事でこう質問しましたね。必要なハンドラーは何か? スロットを再度引き出す方法は? 必要なダイアログディレクティブは何か?
この問題を解決するには、もしスロット値が有効であれば、スロットとルールのセットがtrueを返すヘルパー関数を作成し、次に、指定されたスロット値が無効かどうかを判別し、無効であればDialog.ElicitSlotディレクティブを使用してスロットを再引き出しするハンドラーを作成します。しかし、2018年11月に、ダイアログモデルのスロット検証が発表されました。つまり、スキルがDialog.Delegateディレクティブを返す限り、実際にコードを書く必要がなくなりました。不具合が起きず、テストする必要もなく、書き直す必要もないコードとは何でしょうか? その答えは、コードを書かなければいいのです。
ダイアログモデルのスロット検証を詳しく見ていく前に、コーヒーショップスキルをおさらいしましょう。
コーヒーショップスキルでは、ユーザーがコーヒーまたはお茶を注文できます。ユーザーが選択した飲み物(drink)に応じて、スキルはコーヒーのローストの種類(coffeeRoast)またはお茶の種類(teaType)を尋ねます。さらに、コーヒーが注文されたら、スキルはDialog.ElicitSlotディレクティブを使用して、ユーザーにフレーバー(flavor)を追加するかどうか尋ねます。「いりません」と言えばフレーバーを断ることができます。 ユーザーがフレーバーを選択した場合は、スキルはDialog.ConfirmSlotディレクティブを使用して、フレーバーの追加には50円の追加料金がかかることの了承を求めます。
自動的にdrinkスロットを検証して、ユーザーの選択が無効の場合はユーザーに再入力を促すよう、コードを追加せずにコーヒーショップスキルを更新する方法を見ていきましょう。
スロット検証機能がリリースされたので、開発者ポータルのビルドタブが更新され検証をオンにできるようになりました。OrderIntentからdrinkスロットを選択すると、ダイアログと検証というラベルの2つのタブがあります。検証タブをクリックすると、スロット用の検証ルールを作成できます。
3つの検証ルールから選択できます。
これらのルールを使用して、スロット値の検証方法を指定できます。コーヒーショップスキルでは、3つめのオプションである「スロットタイプの値と同義語のみを受け付ける」を使用します。 このオプションでは、同義語を定義して、値に加えて同義語でもユーザーが言ったことを検証できます。
このオプションを選択すると、スロットを再引き出しするためにAlexaが発話するプロンプトをいくつか用意する必要があります。これを行うために、drinkスロットが靴だった場合にAlexaが何というか考えてみましょう。
上記の例を見ると、それぞれに「コーヒーかお茶のどちらにしますか?」が入っていることに気が付くと思います。 これはdrinkスロットを再度引き出すときにAlexaがユーザーに尋ねるプロンプトとして含まれています。例に共通しているもうひとつのものは「靴」です。 暗黙の確認を使用して、ユーザーが頼んだものは聞き取れたが無効な選択であることをユーザーに知らせる、もっともよい方法です。サンプルを定義するときに、ユーザーが無効な選択として何を言うかわからない場合に、それを復唱させるにはどうしたらよいでしょうか。 簡単ですね。スロットを使います。このケースでは、drinkスロットを検証しているので、サンプル発話で使用します。
サンプル発話を変換してモデルに追加したら、モデルを保存してビルドします。
検証チェックを行うために追加でコードを作成する必要はありませんが、Alexaサービスが自動的にスロットを検証して、スロットが無効であればスロットを再度引き出すためには、スキルがDialog.Delegateディレクティブを返す必要があります。
Dialog.Delegateディレクティブを返す必要があります。スキルのハンドラー関数はさまざまな事例をチェックします。StartedInProgressOrderIntentHandlerハンドラーを覚えているでしょうか。 このcanHandle関数は次の場合にtrueを返します。
このハンドル関数はDialog.Delegateディレクティブを返します。Alexaがdrinkスロットを検証するのに必要です。そのため、バックエンドは完成しており、コードを更新する必要はありません。
コードに変換すると、StartedInProgressOrderIntentHandlerは次のようになります。
const StartedInProgressOrderIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "IntentRequest"
&& handlerInput.requestEnvelope.request.intent.name === "OrderIntent"
&& handlerInput.requestEnvelope.request.dialogState !== 'COMPLETED';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.addDelegateDirective()
.getResponse();
}
}
注: ダイアログモデルの検証はDialog.Delegateディレクティブのみをサポートしています。そのため、Dialog.ElicitSlotディレクティブが返されると、引き出されたスロットで検証が実行されません。たとえば、Dialog.ElicitSlotを使用してcoffeeRoastの値を受け取った後にフレーバーを引き出しているため、Dialog.ElicitSlotでは検証が実行されません。
この記事を最後まで読んでいただき、ありがとうございました。このテクニックや機能を応用して、ご自分のスキルで使ってみてください。オンラインのディスカッションも歓迎します。 Twitterのアカウントは@Toshimin8です。