Microsoft Foundry SDK を使用して会話をシミュレートする

シナリオの説明からシミュレートされた会話を生成し、会話レベルで評価します。 このシナリオを使用して、デプロイ前に制御された状況でエージェントの動作をテストします。 サービスは、シナリオの説明に基づいて現実的な会話を生成し、それらを評価します。

前提条件

  • クラウド評価の前提条件とクライアントのセットアップを完了します。
  • ユーザーをシミュレートするモデル デプロイ。
  • 評価するエージェントターゲット。
  • シミュレートする相互作用を記述するシナリオ データ。

この例では、「SDK クライアントのセットアップ」で構成された SDK クライアントを使用します。

会話シミュレーションを理解する

この方法は、次の場合に役立ちます。

  • デプロイ前テスト: 実際のユーザー トラフィックなしで、さまざまなシナリオでエージェントの動作を検証します。
  • エッジ ケース カバレッジ: 自然にはほとんど発生しないが、適切に処理することが重要なシナリオをテストします。
  • 回帰テスト: 既知のシナリオでエージェントの更新によってパフォーマンスが低下しないようにします。
  • スケール テスト: ストレス テスト エージェントの機能に対して多くの会話をすばやく生成します。

会話シミュレーションは、次の手順に従います。

  1. シナリオの説明は、JSONL データまたは厳密に型指定されたインライン テスト ケースとして提供します。 各テスト ケースでは、シミュレートされたユーザーが実行しようとする状況について説明します。
  2. このサービスでは、シミュレーター モデルを使用してユーザーの役割を果たし、シナリオに基づいてエージェントと対話します。
  3. 各シナリオでは、1 つ以上の完全な会話が生成されます。
  4. 会話レベルのエバリュエーターは、生成された会話を評価します。
  5. プロジェクトには評価結果が格納されます。 必要に応じて、生成されたすべての会話をバージョン管理された Foundry データセットとして保持できます。

この実行では、 azure_ai_user_conversation_simulation データ ソースが使用されます。 すべてのテスト ケースに適用される設定を default_simulation_configurationに配置します。 テスト ケースでは、 simulation_configurationの個々の会話設定をオーバーライドできます。オーバーライドしない設定では、実行の既定値が引き続き使用されます。

シナリオ データを準備する

ヒント

シナリオを手動で作成する代わりに、 シミュレーション シード (複数ターン) タスクの種類を使用して生成します。 この API で既存の生成されたデータセットを使用する前に、 id を正規化して test_case_id し、 desired_num_turns を simulation_configurationに移動します。 シミュレーション シード データセットの生成を参照してください。

次のいずれかのソースの種類を使用して、テスト ケースを提供します。

  • JSONL シナリオの場合は file_id または file_content。
  • inline_user_conversation_simulation 実行要求で厳密に型指定されたテスト ケースの場合。 少なくとも 1 つのテスト ケースを含めます。

JSONL の場合は、次の例に示す標準プロパティ名を使用します。 ユーザーの目標、コンテキスト、および動作の制約を test_case_descriptionに含めます。 説明には、1 ~ 2,500 文字を含めることができます。

{"test_case_id":"contoso_refund_timeline","test_case_description":"Customer returned an item five days ago and wants to know when the refund will arrive.","simulation_configuration":{"desired_num_turns":10}}
{"test_case_id":"contoso_store_hours_lookup","test_case_description":"Customer wants today's closing time and might need to clarify the store location.","simulation_configuration":{"desired_num_turns":3,"conversation_repetitions":2}}

JSONL データでこれらの正規名を使用する場合は、 data_mappingを省略します。 異なる名前を使用する場合は、それらの属性を test_case_id、 test_case_description、および simulation_configurationにマップします。 inline_user_conversation_simulation ソースでdata_mappingを使用しないでください。

各インラインまたは JSONL テスト ケースでは、次のプロパティがサポートされています。

プロパティ 説明
test_case_id 省略可能な識別子。 サービスでは、省略すると識別子が生成されます。
test_case_description シミュレートされた会話をガイドするシナリオ、ユーザーの目標、および動作の制約。
simulation_configuration 対応する実行をオーバーライドするオプションの設定は、このテスト ケースの既定値です。

シミュレートされたユーザーを構成する

model_configuration オブジェクトを使用して、シミュレートされたユーザーを再生するモデルを構成します。 このモデルは、評価対象の target モデルまたはエージェントとは別です。

プロパティ 必須 説明
model はい {connectionName}/{modelDeploymentName}形式のシミュレーターのデプロイ。 モデル ルーターはシミュレーター モデルとしてサポートされていません。これは評価対象に限定できます。
sampling_params いいえ シミュレーターがユーザー ターンを生成するときに適用されるサンプリング パラメーター。
voice_model いいえ シミュレートされたユーザー テキストを Voice Live エンドポイントを介して音声に変換します。 テキストのみのシミュレーションでは、このプロパティを省略します。

音声シミュレーションの場合、 voice_model.type は azure-standardする必要があります。 nameをAzure標準ニューラル音声名に設定します。 temperatureを 0 から 1 まで設定することもできます。省略すると、基になる音声モデルの既定値が適用されます。

会話を構成する

default_simulation_configurationで実行全体の値を設定します。 会話コントロール max_num_turns、 conversation_repetitions、 desired_num_turns、 audio_effects、 user_behavior もテスト ケースの simulation_configuration に表示され、対応する実行の既定値をオーバーライドできます。 データセット生成プロパティ enable_conversation_dataset_generation と output_conversation_dataset_name は、 default_simulation_configuration でのみ有効であり、テスト ケースごとにオーバーライドすることはできません。

プロパティ Scope Default 説明
max_num_turns 実行またはテスト ケース 20 各会話におけるターン数の上限。 1 以上を指定してください。
conversation_repetitions 実行またはテスト ケース 1 テスト ケースごとに生成された独立した会話の数。 1 以上を指定してください。
desired_num_turns 実行またはテスト ケース None 目標の会話の長さ。 有効な max_num_turnsを超えることはできません。 省略すると、シミュレーターによってシナリオの長さが決まります。
audio_effects 実行またはテスト ケース None 音声シミュレーションに適用される効果。 テキストのみのシミュレーションでは無視されます。
user_behavior 実行またはテスト ケース None 中断などのシミュレートされたユーザーの動作。
enable_conversation_dataset_generation 実行のみ false 生成されたすべての会話を、バージョン管理された Foundry データセットに保持します。
output_conversation_dataset_name 実行のみ サービスによって生成される 会話データセットの生成が有効な場合に使用されるデータセット名。

音声条件と中断を構成する

audio_effectsとuser_behaviorをdefault_simulation_configuration内に配置して、すべてのテスト ケースに適用します。 1 つのテスト ケースに対していずれかの設定をオーバーライドするには、代わりにそのテスト ケースの simulation_configuration 内に配置します。

audio_effectsを使用して、現実的なリスニング条件下でのターゲットのパフォーマンスをテストします。 1 つ以上の効果 ( street_traffic、 crowd_chatter、 background_tv、 metro_station、または telephonic_voice) を追加します。 volume_percentageを 1 から 100 に設定して、結合されたボリュームを制御します。 既定値は 15 です。 テキストのみのシミュレーションでは、オーディオ効果は無視されます。

user_behavior.interruptionを使用して、ターゲットが応答している間にユーザーが話す方法をテストします。 その type を default に設定して、シミュレートされた中断を有効にします。 中断がテストの一部でない場合は、 interruption を省略します。

{
  "default_simulation_configuration": {
    "audio_effects": {
      "effects": ["street_traffic", "telephonic_voice"],
      "volume_percentage": 20
    },
    "user_behavior": {
      "interruption": {
        "type": "default"
      }
    }
  }
}

エバリュエーターの定義

会話レベルの評価用に設計されたエバリュエーターを選択します。 シミュレートされた会話は、エバリュエーターに自動的にマップされます。

import os
from openai.types.eval_create_params import DataSourceConfigCustom
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import TestingCriterionAzureAIEvaluator, PromptAgentDefinition

endpoint = os.environ["AZURE_AI_PROJECT_ENDPOINT"]
model_deployment_name = os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"]
simulator_model = os.environ["AZURE_AI_SIMULATOR_MODEL"]
agent_name = os.environ.get("FOUNDRY_AGENT_NAME", "")

with (
    DefaultAzureCredential() as credential,
    AIProjectClient(endpoint=endpoint, credential=credential) as project_client,
    project_client.get_openai_client() as openai_client,
):
    # Simulation uses the same "custom" eval group type as dataset evaluation (S1),
    # since the generated conversations follow the same messages schema.
    data_source_config = DataSourceConfigCustom(
        type="custom",
        item_schema={
            "type": "object",
            "properties": {
                "messages": {"type": "array"},
                "tool_definitions": {"type": "array"},
            },
            "required": ["messages"],
        },
        include_sample_schema=False,
    )

    testing_criteria = [
        TestingCriterionAzureAIEvaluator(
            type="azure_ai_evaluator",
            name="output_quality",
            evaluator_name="builtin.output_quality",
            initialization_parameters={"model": model_deployment_name},
            data_mapping={
                "messages": "{{item.messages}}",
                "tool_definitions": "{{item.tool_definitions}}",
            },
        ),
        TestingCriterionAzureAIEvaluator(
            type="azure_ai_evaluator",
            name="tool_use_quality",
            evaluator_name="builtin.tool_use_quality",
            initialization_parameters={"model": model_deployment_name},
            data_mapping={
                "messages": "{{item.messages}}",
                "tool_definitions": "{{item.tool_definitions}}",
            },
        ),
        TestingCriterionAzureAIEvaluator(
            type="azure_ai_evaluator",
            name="deflection_rate",
            evaluator_name="builtin.deflection_rate",
            initialization_parameters={"model": model_deployment_name},
            data_mapping={
                "messages": "{{item.messages}}",
                "tool_definitions": "{{item.tool_definitions}}",
            },
        ),
        TestingCriterionAzureAIEvaluator(
            type="azure_ai_evaluator",
            name="customer_satisfaction",
            evaluator_name="builtin.customer_satisfaction",
            initialization_parameters={"model": model_deployment_name},
            data_mapping={"messages": "{{item.messages}}"},
        ),
        TestingCriterionAzureAIEvaluator(
            type="azure_ai_evaluator",
            name="task_completion",
            evaluator_name="builtin.task_completion",
            initialization_parameters={"model": model_deployment_name},
            data_mapping={"messages": "{{item.messages}}"},
        ),
        TestingCriterionAzureAIEvaluator(
            type="azure_ai_evaluator",
            name="coherence",
            evaluator_name="builtin.coherence",
            initialization_parameters={"model": model_deployment_name},
            data_mapping={"messages": "{{item.messages}}"},
        ),
        TestingCriterionAzureAIEvaluator(
            type="azure_ai_evaluator",
            name="groundedness",
            evaluator_name="builtin.groundedness",
            initialization_parameters={"model": model_deployment_name},
            data_mapping={"messages": "{{item.messages}}"},
        ),
    ]

評価を作成して実行する

シナリオ データの準備から正規の JSONL 行をsimulation_scenarios.jsonlとして保存します。

# Create (or update) an agent to simulate against
agent = project_client.agents.create_version(
    agent_name=agent_name,
    definition=PromptAgentDefinition(
        model=model_deployment_name,
        instructions="You are a helpful customer service agent. Be empathetic and solution-oriented.",
    ),
)

# Upload scenario data
scenarios_id = project_client.datasets.upload_file(
    name="simulation-scenarios",
    version="1",
    file_path="./simulation_scenarios.jsonl",
).id

# Create the evaluation
eval_object = openai_client.evals.create(
    name="Multi-turn Conversation Simulation",
    data_source_config=data_source_config,
    testing_criteria=testing_criteria,
)

# Create a simulation run. AZURE_AI_SIMULATOR_MODEL uses the format
# {connectionName}/{modelDeploymentName}.
eval_run = openai_client.evals.runs.create(
    eval_id=eval_object.id,
    name="conversation-simulation-run",
    data_source={
        "type": "azure_ai_user_conversation_simulation",
        "source": {
            "type": "file_id",
            "id": scenarios_id,
        },
        "target": {
            "type": "azure_ai_agent",
            "name": agent.name,
            "version": agent.version,
        },
        "model_configuration": {
            "model": simulator_model,
            "sampling_params": {
                "temperature": 0.7,
                "top_p": 1.0,
                "max_completion_tokens": 800,
            },
        },
        "default_simulation_configuration": {
            "max_num_turns": 8,
            "conversation_repetitions": 2,
            "desired_num_turns": 5,
            "enable_conversation_dataset_generation": True,
            "output_conversation_dataset_name": "support-simulations",
        },
    },
    extra_body={"evaluation_level": "conversation"},
)

インラインテストケースを使用する

実行要求で直接シナリオを定義するには、 data_source.source を inline_user_conversation_simulation ソースに設定します。 インライン ソースには少なくとも 1 つのテスト ケースが必要であり、 data_mappingは使用しません。

inline_source = {
    "type": "inline_user_conversation_simulation",
    "test_cases": [
        {
            "test_case_id": "refund-delay",
            "test_case_description": "A frustrated customer wants an update on a delayed refund.",
            "simulation_configuration": {
                "desired_num_turns": 6,
            },
        }
    ],
}

# In the run request:
# data_source={..., "source": inline_source}

生成された会話を取得する

クラウド評価結果の取得に関するページの説明に従って、実行が終了状態になるまでポーリングします。 enable_conversation_dataset_generationがtrueされると、完了した実行には次のようなoutput_datasetsエントリが含まれます。

{
  "type": "simulated_user_conversations",
  "dataset": {
    "id": "dataset_123",
    "name": "support-simulations",
    "version": "1"
  }
}

返されたデータセット id、 name、および version を使用して、生成された会話を取得または再利用します。 データセットの生成が無効になっている場合、 output_datasets は省略されます。


次のステップ