カスタマイズした対話に動的エンティティを使用する



カスタマイズした対話に動的エンティティを使用する

動的エンティティを使用すると、スキルが実行時に新しいエンティティを動的に作成できるため、スキルの定義済み静的カタログを拡張できます。動的エンティティを使用しない場合、エンティティはビルド時に解決され、スキルを更新するまでは変わりません。ユーザーやダイアログターンごとにエンティティをカスタマイズすることはできません。動的エンティティを使用すると、パーソナライズされた音声エクスペリエンスを作ることができ、会話やユーザーコンテキストに基づいて値を動的に有効化したり無効化したりすることができます。動的エンティティを使用することで、新たにロードされたスロット値に基づいてAlexaのモデルを動的にバイアスすることができるため、音声認識、自然言語理解、エンティティ解決の精度が向上します。

動的エンティティを使用して、スキルのユーザーのセッション内でパーソナライズされたエクスペリエンスを開発することができます。たとえば、マイリストスキルという名前のリストスキルがあり、ユーザーがリストに牛乳を追加したいとします。

ユーザー: アレクサ、マイリストスキルを開いて

ユーザー: アレクサ、マイリストスキルでショッピングカートに牛乳を追加して

Alexaはマイリストスキルでのユーザーの好みと買い物パターンに基づいて、「牛乳」を「SomeBrand 2%有機牛乳」に解決します。スキルは、マイリストスキルでのユーザーの好みと買い物パターンに基づいて、ユーザーのパーソナルカタログからスロット値をアップロードし、「牛乳」を「SomeBrand 2%有機牛乳」に解決します。

スロット値は必ずしも静的ではありません。時間や場所によって異なる場合があります。動的エンティティを使用すると、スキルが実行時にエンティティをロードするので、スロット値の動的な性質に対応できます。ネット食品宅配企業向けのマイフードオーダーというスキルがあるとします。

ユーザー: アレクサ、マイフードオーダーを開いて

ユーザー: アレクサ、マイフードオーダーでクールレストランに食事を注文して

ユーザーが「アレクサ、マイフードオーダーでクールレストランに食事を注文して」と言うと、マイフードオーダースキルがクールレストランの今日のメニューをロードします。

この機能により、パーソナライズされた動的エンティティ解決をとおしてスロット値を動的に有効化または無効化できるため、精度が向上します。Alexaスキルはロードされたカタログに基づくスロット値にバイアスされるため、高い精度の音声認識とエンティティ認識を作成することができます。

動的エンティティが役立つ例を紹介します。

  • レストランスキルで日替わりランチを提供し、その日のメニュー商品に解決する場合。
  • ショッピングスキルでパーソナライズされたお気に入り商品リストと照合して、エンティティを解決する場合。
  • コミュニケーションスキルで連絡先リストを実行時にロードし、相手の名前を連絡先リストのエンティティに解決する場合。たとえば、太郎というユーザーが「花子に電話して」と発話すると、「花子」は太郎の連絡先リストにある「花子」に解決します。
  • ゲームスキルでユーザーのゲームのステータスに基づいて異なるアイテムドロップを指定する場合。

動的エンティティを使用すると、エンティティ解決の有用性を高めることができます。静的エンティティ解決では、スロット値の同義語と、ユーザーの発話を明確にするための同義語の静的リストを作成できます。しかし、これらの同義語は各ユーザーに対してカスタマイズされておらず、動的に応答することができません。動的エンティティでは、スキルが起動したときに動的にスロット値と同義語を指定でき、以降の発話に合わせてそれらを変化させることができるので、より正確で状況に合ったエンティティ解決を活用できます。

動的エンティティのしくみ

エンティティとは、発話からのスロットを開発者が提供するスロット値のリストと照合して解決した結果です。フライトスキルでは、「福岡へのフライトを予約して」という発話の場合は、福岡(スロット: AirportName)が次のように解決されます。

{"id":"‘FUK" , "name":"福岡空港"}

動的エンティティは、静的カタログと同じようにスロット値の解決に使用します。

Alexaは、動的カタログと静的カタログの両方からのエンティティ解決の結果を返します。その後、スキルがどちらを使用するかを選択します。動的カタログがER_NO_MATCHを返した場合、代わりに静的カタログの結果をデフォルトとして使用するように、スキルのサービスコードを記述できます。

Alexaは次の順序でカタログ値を優先します。

  1. 動的エンティティを使用したカスタムスロットタイプ
  2. 動的エンティティを使用した拡張ビルトイン
  3. 動的エンティティを使用しないカスタムスロットタイプ
  4. 動的エンティティを使用しない拡張ビルトイン

Dialog.UpdateDynamicEntitiesディレクティブを使用してエンティティのリストを更新する

動的エンティティを使用するには、定義済みのスロットタイプとスロット名を持つ静的カタログがスキルにある必要があります。動的エンティティは既存のスロットタイプを変更することのみを行います。スキルがダイアログディレクティブの要件を満たしていることを確認してください。動的エンティティでは、既存のスロットタイプをスロット値と同義語を追加して「拡張」できます。

動的エンティティは、ダイアログ管理機能と組み合わせて使用することも個別に使用することもできます。Dialog.UpdateDynamicEntitiesディレクティブを使用するために、Dialog.Delegateディレクティブ、スロット入力、そのほかのダイアログ管理機能を使用する必要はありません。

ユーザーがスキルを呼び出すと、Alexaはインテントの応答をスキルのLambda関数に送信します。この応答は、スキルがセッション中にアクセスする動的エンティティカタログを取り込むために使用できます。静的カタログと同様に、すべての動的エンティティにIDと同義語をアップロードできます。

次のインテントの応答例は、空港を参照して「Airport」という既存のスロットタイプを使用するトラベルスキルのインテントの応答で動的エンティティを取り込む方法を示しています。簡潔にするため、ここでは福岡空港と大阪国際空港を表す2つの動的エンティティのみを記載しています。複数のスロットタイプを含めることもできますが、すべてのスロットタイプ全体の動的エンティティの合計数は、同義語も含めて100を超えてはいけません。

後に続くインテントの応答で別のエンティティカタログをアップロードすることができます。しかし、新しい動的エンティティカタログは前の動的エンティティカタログを上書きします。

1つのインテントの応答でロードするエンティティの数が100を超えていると403エラーが返され、これらの動的エンティティは一切ロードされません。ただし、標準の静的カタログは引き続き使用できます。

動的エンティティカタログはカスタマーIDごとにロードされるため、ユーザーごとにパーソナライズできます。

目的の動的エンティティカタログを更新するために、1つのインテントの応答の中でそのカタログと共にDialog.UpdateDynamicEntitiesディレクティブを使用します。現在、updateBehaviorでサポートされている値は「REPLACE」と「CLEAR」です。

例:「REPLACE」を使用して動的エンティティを更新する

簡潔にするため、次の例ではインテントの応答のdirectivesの部分だけを示します。

"directives": [
        {
            "type": "Dialog.UpdateDynamicEntities",
            "updateBehavior": "REPLACE",
            "types": [
                {
                    "name": "AirportSlotType",
                    "values": [
                        {
                            "id": "FUK",
                            "name": {
                                "value": "福岡空港",
                                "synonyms": [
                                    "福岡"
                                ]
                            }
                        },
                        {
                            "id": "ITM",
                            "name": {
                                "value": "大阪国際空港",
                                "synonyms": [
                                    "伊丹"
                                ]
                            }
                        }
                    ]
                }
            ]
        }
    ]

以下の例は、Alexa Skills Kit SDK for Node.jsまたはAlexa Skills Kit SDK v2 for Javaのいずれかを使って動的エンティティを更新する方法です。

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Node.js(v2)を使用しています。

const FlightDetailsHandler = {
  // ...

  handle (handlerInput) {
    // AirportSlotTypeタイプに実行時に追加されるスロット値です。
    // このスロットタイプが静的カタログに存在する必要があります。
    let replaceEntityDirective = {
      type: 'Dialog.UpdateDynamicEntities',
      updateBehavior: 'REPLACE',
      types: [
        {
          name: 'AirportSlotType',
          values: [
            {
              id: 'KIX',
              name: {
                value: '関西国際空港',
                synonyms: ['関空', 'KIX']
              }
            },
            {
              id: 'CTS',
              name: {
                value: '新千歳空港',
                synonyms: ['札幌', 'CTS']
              }
            },
            {
              id: 'FUK',
              name: {
                value: '福岡空港',
                synonyms: ['福岡', '北九州', 'ハブ', '博多']
              }
            }
          ]
        }
      ]
    };

    const repeat = 'どちらの空港から出発しますか?';
    const speech = 'ご利用いただきありがとうございます。' + repeat;

    return handlerInput.responseBuilder
      .speak(speech)
      .reprompt(repeat)
      .addDirective(replaceEntityDirective)
      .getResponse();
  }
};

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Javaを使用しています。

public class FlightDetails implements RequestHandler {
        // ...

        public static Optional<Response> generateQuestion(HandlerInput handerInput) {
                // これはスロット値に1つの動的エンティティを追加する基本的な例です。
                List<Entity> entities = new ArrayList<>();
                ArrayList<String> synonyms = new ArrayList<String>();

                // エンティティに同義語を追加する例
                synonyms.add("大阪");
                synonyms.add("ITM");

                // エンティティのスロットID、スロット値、同義語
                Entity entity = Entity.builder()
                                .withId("ITM")
                                .withName(EntityValueAndSynonyms.builder()
                                        .withValue("大阪国際空港")
                                        .withSynonyms(synonyms)
                                        .build())
                                .build();

                // 1つのエンティティリストに複数のエンティティ/スロット値を追加します。               
                entities.add(entity);

                // 動的エンティティディレクティブを作成してスロットタイプを指定します
                // (AirportSlotType)。このスロットは対話モデル内に既に存在している必要があります。
                // 新しいエンティティを追加するときの更新の動作はREPLACEです。
                DynamicEntitiesDirective replaceEntityDirective = DynamicEntitiesDirective
                                .builder()
                                .addTypesItem(EntityListItem.builder()
                                                .withName("AirportSlotType")
                                                .withValues(entities)
                                                .build())
                                .withUpdateBehavior(UpdateBehavior.REPLACE)
                                .build();

                String question = "どちらの空港から出発しますか?";
                String speech = "ご利用いただきありがとうございます。" + question;

                return handlerInput.getResponseBuilder()
                        .withSpeech(speech)
                        .withReprompt(question)
                        .addDirective(replaceEntityDirective)
                        .withShouldEndSession(false)
                        .build();
        }
}

インテントの応答で動的エンティティを使用する

ユーザーがリクエストし、スキルがインテントの応答で応えるとき、応答にはエンティティ解決の結果が含まれます。「エンティティ解決」を参照してください。ユーザーが買い物リストスキルを利用して、「牛乳を追加して」と発話したとします。動的エンティティカタログが既に設定されている場合、インテントの応答は一般的には次の例のようになります。1番目のresolutionsPerAuthority配列要素と2番目のresolutionsPerAuthority配列要素に示された標準のエンティティ解決は、取り込まれたカタログに基づく動的エンティティ解決を表します。

簡潔にするため、ここではインテントの応答のslots部のみを示します。この例では、スロットタイプはtoDrinkで、このスロットタイプがスキルのダイアログモデル内に既に存在している必要があります。

{
    "slots": {
        "toDrink": {
            "name": "product",
            "value": "milk",
            "resolutions": {
                "resolutionsPerAuthority": [
                    {
                        "authority": "amzn1.er-authority.echo-sdk.amzn1.ask.skill.72455255-7c82-4bdf-b0e1-4bc299be200d.ProductName",
                        "status": {
                            "code": "ER_SUCCESS_MATCH"
                        },
                        "values": [
                            {
                                "value": {
                                    "name": "ノーブランドの牛乳",
                                    "id": "1234"
                                }
                            }
                        ]
                    },
                     {
                        "authority": "amzn1.er-authority.echo-sdk.dynamic.amzn1.ask.skill.72455255-7c82-4bdf-b0e1-4bc299be200d.ProductName",
                        "status": {
                            "code": "ER_SUCCESS_MATCH"
                        },
                        "values": [
                            {
                                "value": {
                                    "name": "BestCows 2%牧草飼育牛乳",
                                    "id": "4567"
                                }
                            }
                        ]
                    }
                ]
            },
            "confirmationStatus": "NONE"
        }
    }
}

セッションの終了時に動的エンティティを有効期限切れにする

動的エンティティは30分間保持され、ユーザーのスキルセッションはそれより短い場合があります。しかし、動的エンティティをセッションの終了時に「有効期限切れ」にして削除されるようにするのがベストプラクティスです。動的エンティティを削除するには、ユーザーがスキルを終了するときにDialog.DynamicEntityDirective CLEAR関数を呼び出して、そのユーザーに対する動的エンティティをすべて消去します。それを示したのが次の例です。

セッションは、ユーザーがスキルを呼び出したときに定義され、ユーザーがスキルを終了するまで続きます。ユーザーが「終了」と言うか、スキルがタイムアウトすると、セッションが終了したと見なされます。アップロードされた動的エンティティは30分後にタイムアウトします。したがって、この30分が経過する前にユーザーがスキルをもう一度呼び出すと、動的エンティティは維持されます。ただし、動的エンティティの有効期限がまだ切れていなくても、セッションのたびにインテントの応答に動的エンティティカタログを取り込み直すのがベストプラクティスです。

例:「CLEAR」を使用して動的エンティティを有効期限切れにする

簡潔にするため、次の例では応答のdirectivesの部分だけを示します。

"directives": [
    {
        "type": "Dialog.UpdateDynamicEntities",
        "updateBehavior": "CLEAR"
    }
]

以下の例は、Alexa Skills Kit SDK for Node.jsまたはAlexa Skills Kit SDK v2 for Javaのいずれかを使って動的エンティティを更新する方法です。

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Node.js(v2)を使用しています。

const ClearBookingHandler = {
  // ...

  handle (handlerInput) {
    // このインテントは動的エンティティが不要になったときに
    // ユーザーのフライトデータを消去します。
    const clearEntitiesDirective = {
      type: 'Dialog.UpdateDynamicEntities',
      updateBehavior: 'CLEAR'
    };

    return handlerInput.responseBuilder
      .speak('リクエストを消去します。ご用件は何ですか?')
      .reprompt('ご用件は何ですか?')
      .addDirective(clearEntitiesDirective)
      .getResponse();
  }
};

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Javaを使用しています。

public class FlightDetails implements RequestHandler {
    // ...

    public static Optional<Response> resetDynamicEntities(HandlerInput handlerInput) {
        // CLEAR動作だけのディレクティブをビルド
        DynamicEntitiesDirective clearEntityDirective = DynamicEntitiesDirective.builder()
                .withUpdateBehavior(UpdateBehavior.CLEAR)
                .build();

        String question = "ご用件は何ですか?";
        String speech = "リクエストを消去します。" + question;
        return handlerInput.getResponseBuilder()
                .withSpeech(speech)
                .withReprompt(question)
                .addDirective(clearEntityDirective)
                .withShouldEndSession(false)
                .build();
    }
}

例:動的エンティティとインテント処理

動的エンティティとインテント処理を説明するこのNode.jsサンプルをダウンロードしてください。