会話言語理解のベスト プラクティス

会話言語理解で可能な限り最適なプロジェクトを作成するには、次のガイドラインのようにしてください。

一貫性のあるスキーマを選択する

スキーマは、意図とエンティティの定義です。 意図とエンティティでは、作成する必要があるものを定義するときに使用できるアプローチが異なります。 次のように自問してみてください。

  • ユーザーからどのようなアクションやクエリをキャプチャしようとしているのか?
  • 各アクションにはどのような情報が関連するのか?

通常、アクションとクエリは "意図" と考えることができ、それらのクエリを実行するために必要な情報は "エンティティ" です。

たとえば、顧客がチャットボットを通じて、提供されているさまざまな製品のサブスクリプションを取り消すことができるようにする必要があるとします。 "Contoso サービスを取り消します" や "Fabrikam サブスクリプションの課金を停止します" などのさまざまな例を使用して、"取り消す" という意図を作成できます。この場合、ユーザーの意図は "取り消す" ことであり、"Contoso サービス" や "Fabrikam サブスクリプション" は、ユーザーが取り消したいサブスクリプションです。

先に進むには、"サブスクリプション" のエンティティを作成します。 その後、プロジェクト全体をモデル化して、アクションを意図としてキャプチャし、エンティティを使用してそれらのアクションを入力できます。 このアプローチを使用すると、エンティティとして定義したすべてのもの (他の製品など) を取り消すことができます。 その後、すべての "サブスクリプション" や他のエンティティを使用するサインアップ、更新、アップグレードの意図を作成できます。

上記のスキーマ設計を使用すると、新しいエンティティを作成して、既存の機能 (取り消し、アップグレード、またはサインアップ) を新しいターゲットに簡単に拡張できます。

もう 1 つのアプローチは、"情報" を意図、"アクション" をエンティティとしてモデル化することです。 顧客がチャットボットを通じてサブスクリプションを取り消すことができるようにする同じ例を取り上げることにしましょう。

"Contoso を取り消します"、"Contoso サービスの課金を停止します"、"Contoso サブスクリプションをキャンセルします" などの発話を使用して、Contoso など、使用できる各サブスクリプションに対する意図を作成できます。その後、"取り消す" アクションをキャプチャするエンティティを作成します。 アクションごとに異なるエンティティを定義するか、リスト コンポーネントを使ってアクションを 1 つのエンティティとして統合し、異なるキーでアクションを区別することができます。

このスキーマ設計を使うと、新しいアクション エンティティまたはエンティティ コンポーネントを追加することで、新しいアクションを既存のターゲットに簡単に拡張できます。

すべての概念を意図にまとめようとしないでください。 たとえば、特定の 1 つのアクションのみを目的とする "Contoso を取り消します" などの意図を作成しようとしないでください。 意図とエンティティが連携して、顧客から必要なすべての情報をキャプチャする必要があります。

また、異なるスキーマ設計を混在させるのを避ける必要もあります。 アクションを意図としてアプリケーションの半分をビルドし、残りの半分を、情報を意図としてビルドしないでください。 考えられる結果を得るには、一貫性を確保します。

トレーニング データのバランスを取る

トレーニング データに関しては、スキーマのバランスを保つようにします。 ある意図を大量に含め、別の意図をほとんど含めない場合、特定の意図に偏ったモデルになります。

このシナリオに対処するために、トレーニング セットをダウンサンプリングするか、 または追加することが必要になる場合があります。 ダウンサンプリングは、次のいずれかの方法で行うことができます。

  • 一定の割合のトレーニング データをランダムに取り除きます。
  • データセットを分析し、過剰な重複エントリを削除します。この方法の方がより体系的です。

トレーニング セットを追加するには、Language Studio の [データのラベル付け] タブで、[発話の提案] を選択します。 会話言語理解から Azure OpenAI に呼び出しが送信され、同様の発話が生成されます。

Language Studio の [発話の提案] を示すスクリーンショット。

また、トレーニング セットで意図しない "パターン" を探す必要もあります。 たとえば、特定の意図のトレーニング セットがすべて小文字であるかどうか、または特定の語句で始まるかどうかを確認します。 このような場合、トレーニングするモデルは、一般化することができず、トレーニング セットでこのような意図しない偏りを学習する可能性があります。

トレーニング セットには、大文字と小文字の区別と、句読点の多様性を導入することをお勧めします。 バリエーションの処理を想定しているモデルの場合は、必ずその多様性も反映するトレーニング セットを用意してください。 たとえば、大文字と小文字を適切に区別する発話だけでなく、すべて小文字の発話も含めます。

発話に明確にラベルを付ける

  • エンティティが参照する概念が明確に定義され、分離可能であることを確かめます。 確実に違いを簡単に特定できるかどうかを確認します。 できない場合、この区別がないことは、学習済みコンポーネントでも困難であることを示している可能性があります。

  • エンティティ間に類似点がある場合は必ず、それらの間の違いを示すシグナルを提供する何らかの側面をデータに含めるようにします。

    たとえば、フライトを予約するモデルを構築した場合、ユーザーは "ボストン発、シアトル行きの便が必要です" のような発話を使用する可能性があります。このような発話の "出発都市" と "到着都市" は類似していることが予想されます。 "出発都市" を区別するシグナルは、多くの場合、その前に from という単語が付けられている可能性があります。

  • 必ず、トレーニングとテスト データの両方で、各エンティティのすべてのインスタンスにラベルを付けてください。 1 つの方法は、検索機能を使用して、データ内の単語または語句のすべてのインスタンスを見つけ、正しいラベルが付けられているかどうかを確認することです。

  • 学習済みコンポーネントがないエンティティのテスト データだけでなく、それがあるエンティティのテスト データにもラベルを付けます。 このプラクティスは、評価メトリックの精度を確保するのに役立ちます。

高度なトレーニングの前に標準トレーニングを使用する

標準トレーニングは無料で、高度なトレーニングよりも高速です。 これは、モデルの構築中にトレーニング セットやスキーマを変更した効果をすばやく理解するのに役立ちます。 スキーマに問題がなければ、高度なトレーニングを使用してモデルから最適な AIQ を取得することを検討します。

評価機能を使用する

アプリを構築するときは、エラーを早い段階で見つけると役に立つことがよくあります。 通常は、アプリのビルド時にテスト セットを追加することをお勧めします。 トレーニングと評価の結果は、スキーマのエラーや問題を特定するのに役立ちます。

機械学習のコンポーネントと構成

詳細については、「コンポーネントの種類」を参照してください。

"none" スコアしきい値の使用

コンテキストから外れた発話が有効な意図としてマークされるなど、擬陽性が多すぎる場合、それが推論に与える影響の詳細について、信頼度のしきい値に関する記事を参照してください。

  • リストや正規表現などの機械学習されていないエンティティ コンポーネントは、定義上コンテキストではありません。 意図しない場所にリスト エンティティまたは正規表現エンティティが表示される場合は、機械学習コンポーネントとしてリスト同意語にラベルを付けてみてください。
  • エンティティの場合、学習済みのコンポーネントを必須コンポーネントとして使用して、構成済みエンティティを起動するタイミングを制限できます。

たとえば、"明日のカイロ行きのチケットを 2 枚予約します" などの発話に対して、フライトを予約するために予約する必要があるチケットの枚数を抽出しようとする チケット数量 というエンティティがあるとします。

通常、Quantity.Number の事前構築済みのコンポーネントを追加します。これは、発話内のすべての数値を既に抽出しています。 ただし、エンティティがこの事前構築済みのコンポーネントでのみ定義されている場合、他の数値もチケット数量 エンティティの一部として抽出されます。たとえば、"明日の午後 3 時のカイロ行きのチケットを 2 枚予約します" などの場合です。

この問題を解決するには、トレーニング データで、チケット数量を意味するすべての数値に学習済みコンポーネントのラベルを付けます。 エンティティには、次の 2 つのコンポーネントが含まれるようになりました:

  • すべての数値を解釈できる事前構築済みコンポーネント。
  • 文内のチケット数量の位置を予測する学習済みコンポーネント。

学習済みコンポーネントを必須にすると、学習済みコンポーネントによって適切なコンテキストでチケット数量が予測されたときにのみ、それが返されるようになります。 事前構築済みコンポーネントも必須にすると、返されるチケット数量エンティティが数値であり、かつ正しい位置にあることを保証できます。

モデルの不整合に対処する

モデルが、大文字と小文字の区別や分音記号など、文法の小さな変更に過敏に反応する場合、Language Studio で直接データセットを体系的に操作できます。 これらの機能を使用するには、左側のペインで [設定] タブを選択し、[プロジェクトの詳細設定] セクションを見つけます。

[プロジェクトの詳細設定] の例を示すスクリーンショット。

まず、[大文字と小文字の区別のデータ変換を有効にする] の設定をオンにします。これにより、モデルのトレーニング、テスト、実装時に発話の大文字と小文字の区別が正規化されます。 LUIS から移行した場合、LUIS が既定でこの正規化を行ったことがわかる場合があります。 API を使用してこの機能を利用するには、normalizeCasing パラメーターを true に設定します。 次の例を参照してください。

{
  "projectFileVersion": "2022-10-01-preview",
    ...
    "settings": {
      ...
      "normalizeCasing": true
      ...
    }
...

次に、[文音記号のデータ拡張を有効にする] の設定もオンにして、自然言語で使用される可能性のある文音記号のバリエーションのトレーニング データのバリエーションを生成します。 この機能は、すべての言語で使用でき、 ゲルマン語とスラブ語では特に便利です。これらの言語では、ユーザーは正しい文字ではなく、英語の古典的な文字を使用して単語を書く場合が多いためです。 たとえば、"スポーツ チャンネルに移動します" という語句は、フランス語では "Accédez à la chaîne sportive" です。この機能を有効にすると、"Accedez a la chaine sportive" (分音記号なし) というフレーズもトレーニング データセットに含まれます。

この機能を有効にすると、トレーニング セットの発話数が増加します。 このため、トレーニング データのサイズを適宜調整することが必要になる場合があります。 拡張後の現在の最大発話数は 25,000 です。 API を使用してこの機能を利用するには、augmentDiacritics パラメーターを true に設定します。 次の例を参照してください。

{
  "projectFileVersion": "2022-10-01-preview",
    ...
    "settings": {
      ...
      "augmentDiacritics": true
      ...
    }
...

モデルの過信に対処する

モデルが過信して誤った予測を行っている場合、顧客は LoraNorm レシピ バージョンを使用できます。 この動作の例としては、次のようなシナリオがあります。この場合、モデルは 100% の信頼度で、間違った意図を予測します。 このスコアにより、プロジェクト設定の信頼度のしきい値は使用できなくなります。

Text 予測された意図 信頼度スコア
"Who built the Eiffel Tower?" (エッフェル塔を建てたのは誰?) Sports 1.00
"Do I look good to you today?" (今日の私はいい感じに見える?) QueryWeather 1.00
"I hope you have a good evening." (よい夜を過ごせるよう願っています。) Alarm 1.00

このシナリオに対処するには、信頼度スコアを正規化する 2023-04-15 構成バージョンを使用します。 その後、信頼度しきい値プロジェクト設定を調整して、目的の結果を得ることができます。

curl --location 'https://<your-resource>.cognitiveservices.azure.com/language/authoring/analyze-conversations/projects/<your-project>/:train?api-version=2022-10-01-preview' \
--header 'Ocp-Apim-Subscription-Key: <your subscription key>' \
--header 'Content-Type: application/json' \
--data '{
      "modelLabel": "<modelLabel>",
      "trainingMode": "advanced",
      "trainingConfigVersion": "2023-04-15",
      "evaluationOptions": {
            "kind": "percentage",
            "testingSplitPercentage": 0,
            "trainingSplitPercentage": 100
      }
}

要求が送信されたら、通常どおり Language Studio でトレーニング ジョブの進行状況を追跡できます。

Note

confidenceThreshold プロジェクト設定を更新した後、モデルを再トレーニングする必要があります。 その後、アプリを再発行して、新しいしきい値を有効にする必要があります。

モデル バージョン 2023-04-15 での正規化

モデル バージョン 2023-04-15 では、会話言語理解によって、トレーニングに影響を与えない推論レイヤーで正規化が提供されます。

正規化レイヤーでは、分類の信頼度スコアが制限された範囲に正規化されます。 現在選択されている範囲は [-a,a] であり、"a" は意図の数の平方根です。 その結果、正規化はアプリ内の意図の数に依存します。 意図の数が少ない場合、正規化レイヤーが機能する範囲は小さくなります。 意図の数が多い場合は、正規化の効果は高くなります。

この正規化を使用しても、信頼度しきい値を使用してスコープ外の発話をフィルター処理できる程度にスコープ外の意図が改善されていないと思われる場合は、アプリ内のインテントの数に関係している可能性があります。 より多くの意図をアプリに追加することを検討します。 または、調整されたアーキテクチャを使用している場合、同じドメインに属するアプリをマージしてまとめることを検討します。

構成済みエンティティをデバッグする

エンティティは、関連付けられた型を持つ入力のスパンを出力する関数です。 1 つ以上のコンポーネントで関数を定義します。 必要に応じてコンポーネントをマークし、[コンポーネントの結合] 設定を有効にするかどうかを決定できます。 コンポーネントを結合すると、重複するすべてのスパンが 1 つのスパンにマージされます。 この設定を使用しない場合、個々のコンポーネントのスパンが出力されます。

個々のコンポーネントのパフォーマンスをより深く理解するには、この設定を無効にし、各コンポーネントを [不要] に設定できます。 この設定により、出力される個々のスパンを検査し、問題のあるコンポーネントのみが生成されるようにコンポーネントの削除を試すことができます。

複数のテスト セットを使用してモデルを評価する

会話言語理解プロジェクトのデータには、2 つのデータ セット (テスト セットとトレーニング セット) を含めることができます。 複数のテスト セットを使ってモデルを評価したい場合は、次のようにします:

  • テスト セットに異なる名前を付けます ("test1" や "test2" など)。
  • プロジェクトをエクスポートして、パラメーターと構成を含む JSON ファイルを取得します。
  • JSON を使用して、新しいプロジェクトをインポートします。 2 番目の目的のテスト セットを "test" という名前に変更します。
  • 2 番目のテスト セットを使用して、評価を実行するようにモデルをトレーニングします。

ターゲット アプリと子アプリのカスタム パラメーター

調整されたアプリを使用している場合、さまざまな子アプリに対してカスタム パラメーターのオーバーライドを送信することが必要な場合があります。 targetProjectParameters フィールドを使用すると、ユーザーは各ターゲット プロジェクトのパラメーターを表す辞書を送信できます。 たとえば、CLU1 という名前の会話言語理解アプリと CQA1 という名前のカスタム質問応答アプリの間でオーケストレーションを行う Orchestrator という名前のオーケストレーター アプリについて考えます。 質問応答アプリに "top" という名前のパラメーターを送信する場合は、前述のパラメーターを使用できます。

curl --request POST \
   --url 'https://<your-language-resource>.cognitiveservices.azure.com/language/:analyze-conversations?api-version=2022-10-01-preview' \
   --header 'ocp-apim-subscription-key: <your subscription key>' \
   --data '{
     "kind": "Conversation",
     "analysisInput": {
         "conversationItem": {
             "id": "1",
             "text": "Turn down the volume",
             "modality": "text",
             "language": "en-us",
             "participantId": "1"
         }
     },
     "parameters": {
         "projectName": "Orchestrator",
         "verbose": true,
         "deploymentName": "std",
         "stringIndexType": "TextElement_V8",
"targetProjectParameters": {
            "CQA1": {
                "targetProjectKind": "QuestionAnswering",
                "callingOptions": {
                    "top": 1
                }
             }
         }
     }
 }'

言語リソース間でプロジェクトをコピーする

多くの場合、Language Studio の [コピー] ボタンを使用すると、会話言語理解プロジェクトをあるリソースから別のリソースにコピーできます。 場合によっては、API を使用する方が簡単にプロジェクトをコピーできることもあります。

まず、次の情報を特定します。

  • ソース プロジェクト名。
  • ターゲット プロジェクト名。
  • ソース言語リソース。
  • コピー先となるターゲット言語リソース。

API を呼び出してコピー アクションを承認し、後で実際にコピー操作を行うための accessTokens を取得します。

curl --request POST \ 
  --url 'https://<target-language-resource>.cognitiveservices.azure.com//language/authoring/analyze-conversations/projects/<source-project-name>/:authorize-copy?api-version=2023-04-15-preview' \ 
  --header 'Content-Type: application/json' \ 
  --header 'Ocp-Apim-Subscription-Key: <Your-Subscription-Key>' \ 
  --data '{"projectKind":"Conversation","allowOverwrite":false}' 

API を呼び出してコピー操作を完了します。 前に取得した応答をペイロードとして使用します。

curl --request POST \ 
  --url 'https://<source-language-resource>.cognitiveservices.azure.com/language/authoring/analyze-conversations/projects/<source-project-name>/:copy?api-version=2023-04-15-preview' \ 
  --header 'Content-Type: application/json' \ 
  --header 'Ocp-Apim-Subscription-Key: <Your-Subscription-Key>\ 
  --data '{ 
"projectKind": "Conversation", 
"targetProjectName": "<target-project-name>", 
"accessToken": "<access-token>", 
"expiresAt": "<expiry-date>", 
"targetResourceId": "<target-resource-id>", 
"targetResourceRegion": "<target-region>" 
}'

ドメイン外の発話に対処する

ドメイン外発話に関するモデルの AIQ が不十分な場合、顧客は新しいレシピ バージョン 2024-06-01-preview を使用できます。 既定のレシピを使用したこのシナリオの例は次の例のようになります。この場合、モデルには 3 つの意図 (SportsQueryWeatherAlarm) があります。 テスト発話はドメイン外の発話であり、モデルによって、信頼度スコアが比較的高い InDomain として分類されます。

Text 予測された意図 信頼度スコア
"Who built the Eiffel Tower?" (エッフェル塔を建てたのは誰?) Sports 0.90
"Do I look good to you today?" (今日の私はいい感じに見える?) QueryWeather 1.00
"I hope you have a good evening." (よい夜を過ごせるよう願っています。) Alarm 0.80

このシナリオに対処するには、InDomain 発話に適した品質を維持しながら、この問題に対処するために特別に構築された 2024-06-01-preview 構成バージョンを使用します。

curl --location 'https://<your-resource>.cognitiveservices.azure.com/language/authoring/analyze-conversations/projects/<your-project>/:train?api-version=2022-10-01-preview' \
--header 'Ocp-Apim-Subscription-Key: <your subscription key>' \
--header 'Content-Type: application/json' \
--data '{
      "modelLabel": "<modelLabel>",
      "trainingMode": "advanced",
      "trainingConfigVersion": "2024-06-01-preview",
      "evaluationOptions": {
            "kind": "percentage",
            "testingSplitPercentage": 0,
            "trainingSplitPercentage": 100
      }
}

要求が送信されたら、通常どおり Language Studio でトレーニング ジョブの進行状況を追跡できます。

注意事項:

  • このレシピを使用する場合、アプリの None スコアしきい値 (topIntentNone としてマークされている信頼度しきい値) を 0 に設定する必要があります。 この設定を使用するのは、この新しいレシピではドメイン内の確率の一定部分がドメイン外に帰属するため、モデルが過信してドメイン内の発話について誤った予測をすることがないためです。 その結果、ユーザーには、prod レシピと比較してわずかに低いドメイン発話の信頼度スコアが表示される可能性があります。
  • このレシピは、たとえば、2 つの意図 (IntentANone など) のみがあるアプリには推奨されません。
  • このレシピは、意図あたりの発話の数が少ないアプリには推奨されません。 意図あたりの発話数を少なくとも 25 個にすることを強くお勧めします。