View a markdown version of this page

使用者模擬 - Amazon Bedrock AgentCore

使用者模擬

使用者模擬使用 LLM 支援的演員來扮演最終使用者與代理程式互動的角色。您可以定義演員的設定檔和目標,而演員會推動與您的客服人員的多轉對話,直到達到目標或達到轉彎限制為止。

注意

使用者模擬會在 SDK 端叫用 Amazon Bedrock 模型,以產生演員的回應。這些呼叫需支付標準 Amazon Bedrock 模型調用費用。如需詳細資訊,請參閱 AgentCore 定價頁面

當您想要:

  • 以逼真的變化進行測試:演員會在每次執行時產生不同的措辭、後續問題和對話路徑,公開手寫案例遺漏的邊緣案例。

  • 評估開放式對話:對於處理自由格式對話的客服人員 (客戶支援、教學、諮詢),模擬案例比固定輪換序列更能反映實際使用者行為。

  • 擴展案例涵蓋範圍:使用不同的角色和目標來定義演員描述檔,並讓演員產生對話,而不是手動撰寫數十個多迴轉指令碼。

  • 具有多樣性的迴歸測試:多次執行相同的演員描述檔,以檢查您的代理程式是否處理相同意圖的不同表達式。

使用者模擬適用於隨需批次資料集執行器。

運作方式

執行器會透過對話迴圈處理每個模擬案例:

  1. 開始:執行器會先將案例input的欄位傳送給您的代理程式。

  2. 客服人員回應:您的客服人員會處理輸入並傳回回應。

  3. 演員評估:LLM 支援的演員會收到客服人員的回應,並根據其設定檔和目標決定接下來要做什麼。演員會產生結構式回應,其中包含:

    • 原因:演員回應的內部原因 (例如,「客服人員提供航班選項,但未要求我偏好的時間。 我應該指定我偏好上午航班。」)。這對於偵錯演員以特定方式行為的原因很有用。

    • 訊息:要傳送給客服人員的下一個訊息。

    • 停止訊號:布林值,指出演員是否將其目標視為已實現。

  4. 繼續或停止:如果演員發出目標完成訊號 (stop: true) 或輪換計數達到 max_turns,則對話會結束。否則,演員的下一個訊息會成為下一個回合的輸入。

  5. 評估:對話完成後,執行器會使用設定的評估器評估工作階段,與預先定義的案例相同。

演員描述檔

每個模擬案例都需要一個 ActorProfile,定義演員是誰及其想要實現的目標:

欄位 必要 描述

context

演員的背景資訊。描述情況和演員應該知道的任何相關詳細資訊。

goal

演員想要在對話中達成的目標。當動作者判斷目標已達成時,會發出完成訊號。

traits

描述演員特性的鍵值組 (例如,專業知識層級、溝通風格、耐心)。預設為空白。

{ "actor_profile": { "context": "A customer who purchased a laptop last week and it arrived with a cracked screen", "goal": "Get a replacement laptop shipped within 2 business days", "traits": { "expertise": "non-technical", "tone": "frustrated but polite", "patience": "low" } } }

模擬組態

SimulationConfig 控制演員的行為,並在執行器的評估組態上設定:

欄位 預設 說明

model_id

預設模型

用於演員 LLM 的 Amazon Bedrock 模型 ID。選擇可遵循複雜角色指示的模型。如果省略,則會使用預設模型。

from bedrock_agentcore.evaluation import SimulationConfig simulation_config = SimulationConfig( model_id="<model-id>", )

資料集結構描述

模擬案例使用 actor_profileinput而非 turns

{ "scenarios": [ { "scenario_id": "geography-student", "scenario_description": "A curious student asks geography questions", "actor_profile": { "traits": {"expertise": "novice", "tone": "curious"}, "context": "A student studying world geography who wants to learn about capitals", "goal": "Find out the capital cities of at least two different countries" }, "input": "Hi! I'm studying geography. Can you help me learn about world capitals?", "max_turns": 5, "assertions": [ "Agent provides accurate capital city information", "Agent is helpful and encouraging to the student" ] } ] }
欄位 必要 預設 說明

scenario_id

案例的唯一識別符。

scenario_description

""

描述案例的選用中繼資料。用於整理和識別結果中的案例。

actor_profile

演員的身分和目標。請參閱 演員描述檔

input

傳送給客服人員以開始對話的第一個訊息。

max_turns

10

對話停止前的轉彎次數上限。必須至少為 1。

assertions

有關預期行為的自然語言聲明。供工作階段層級評估者使用,例如 Builtin.GoalSuccessRate

注意

模擬案例不支援expected_trajectory或迴轉,expected_response因為對話流程無法事先得知。將 assertions用於模擬案例的 Ground Truth。

FileDatasetProvider 從 JSON 結構自動偵測案例類型:具有 actor_profile 欄位 (且無turns欄位) 的案例會載入為 SimulatedScenario

搭配批次資料集執行器使用

下列範例使用批次資料集執行器執行模擬案例評估。在 simulation_config上設定 ,BatchEvaluationRunConfig並在 資料集中包含SimulatedScenario執行個體:

import boto3 import json from bedrock_agentcore.evaluation import ( BatchEvaluationRunner, BatchEvaluationRunConfig, BatchEvaluatorConfig, CloudWatchDataSourceConfig, SimulationConfig, AgentInvokerInput, AgentInvokerOutput, Dataset, SimulatedScenario, ActorProfile, ) AGENT_ARN = "arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/MyAgent-abc123" # Replace with your agent runtime ARN REGION = "us-west-2" # Replace with your region RUNTIME_ID = AGENT_ARN.split("/")[-1] AGENT_NAME = RUNTIME_ID.rsplit("-", 1)[0] ENDPOINT_NAME = "DEFAULT" LOG_GROUP = f"/aws/bedrock-agentcore/runtimes/{RUNTIME_ID}-{ENDPOINT_NAME}" SERVICE_NAME = f"{AGENT_NAME}.{ENDPOINT_NAME}" ACTOR_MODEL_ID = "global.anthropic.claude-haiku-4-5-20251001-v1:0" # Replace with your preferred model # Define the dataset with simulated scenarios dataset = Dataset( scenarios=[ SimulatedScenario( scenario_id="support-frustrated-customer", scenario_description="A frustrated customer with a defective product", actor_profile=ActorProfile( traits={"expertise": "non-technical", "tone": "frustrated but polite"}, context="Purchased a laptop last week that arrived with a cracked screen", goal="Get a replacement laptop shipped within 2 business days", ), input="I received my laptop and the screen is cracked. I need help.", max_turns=8, assertions=[ "Agent acknowledges the issue and apologizes", "Agent offers a replacement or refund", "Agent provides a timeline for resolution", ], ), SimulatedScenario( scenario_id="support-billing-question", scenario_description="A customer with a billing discrepancy", actor_profile=ActorProfile( traits={"expertise": "moderate", "tone": "calm"}, context="Noticed a double charge on the last credit card statement", goal="Get the duplicate charge reversed and confirmation of the refund", ), input="I see two charges for the same order on my statement. Can you look into this?", max_turns=6, assertions=[ "Agent investigates the billing issue", "Agent confirms whether a duplicate charge exists", ], ), ] ) # Configure the evaluation config = BatchEvaluationRunConfig( batch_evaluation_name="simulated-support-eval", evaluator_config=BatchEvaluatorConfig( evaluator_ids=[ "Builtin.GoalSuccessRate", "Builtin.Helpfulness", ], ), data_source=CloudWatchDataSourceConfig( service_names=[SERVICE_NAME], log_group_names=[LOG_GROUP], ingestion_delay_seconds=180, ), simulation_config=SimulationConfig( model_id=ACTOR_MODEL_ID, ), polling_timeout_seconds=1800, polling_interval_seconds=30, ) # Define the agent invoker agentcore_client = boto3.client("bedrock-agentcore", region_name=REGION) def agent_invoker(inp: AgentInvokerInput) -> AgentInvokerOutput: payload = inp.payload if isinstance(payload, str): raw_bytes = json.dumps({"prompt": payload}).encode() elif isinstance(payload, dict): raw_bytes = json.dumps(payload).encode() else: raw_bytes = json.dumps({"prompt": str(payload)}).encode() print(f"[{inp.session_id}] > sending payload: {raw_bytes.decode()}") response = agentcore_client.invoke_agent_runtime( agentRuntimeArn=AGENT_ARN, runtimeSessionId=inp.session_id, payload=raw_bytes, ) response_body = response["response"].read() print(f"[{inp.session_id}] < received response: {response_body.decode()}") return AgentInvokerOutput(agent_output=json.loads(response_body)) # Run the evaluation runner = BatchEvaluationRunner(region=REGION) result = runner.run_dataset_evaluation( config=config, dataset=dataset, agent_invoker=agent_invoker, ) # Display results print(f"Status: {result.status}") if result.evaluation_results: er = result.evaluation_results print(f"Sessions completed: {er.number_of_sessions_completed}") print(f"Sessions failed: {er.number_of_sessions_failed}") for summary in er.evaluator_summaries or []: avg = summary.statistics.average_score if summary.statistics else None print(f" {summary.evaluator_id}: avg={avg}")

搭配隨需資料集執行器使用

隨需資料集執行器遵循相同的模式。在 simulation_config上設定 ,EvaluationRunConfig並在 資料集中包含SimulatedScenario執行個體:

注意

隨需評估會根據使用量收費。如需詳細資訊,請參閱 AgentCore 定價頁面

from bedrock_agentcore.evaluation import ( OnDemandEvaluationDatasetRunner, EvaluationRunConfig, EvaluatorConfig, CloudWatchAgentSpanCollector, SimulationConfig, FileDatasetProvider, ) AGENT_ARN = "arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/MyAgent-abc123" # Replace with your agent runtime ARN REGION = "us-west-2" # Replace with your region RUNTIME_ID = AGENT_ARN.split("/")[-1] ENDPOINT_NAME = "DEFAULT" LOG_GROUP = f"/aws/bedrock-agentcore/runtimes/{RUNTIME_ID}-{ENDPOINT_NAME}" ACTOR_MODEL_ID = "global.anthropic.claude-haiku-4-5-20251001-v1:0" # Replace with your preferred model # Load dataset (auto-detects simulated scenarios from actor_profile field) dataset = FileDatasetProvider("simulated_dataset.json").get_dataset() # Create span collector span_collector = CloudWatchAgentSpanCollector( log_group_name=LOG_GROUP, region=REGION, ) # Configure with simulation support config = EvaluationRunConfig( evaluator_config=EvaluatorConfig( evaluator_ids=["Builtin.GoalSuccessRate", "Builtin.Helpfulness"], ), evaluation_delay_seconds=180, max_concurrent_scenarios=5, simulation_config=SimulationConfig( model_id=ACTOR_MODEL_ID, ), ) # Run runner = OnDemandEvaluationDatasetRunner(region=REGION) result = runner.run( agent_invoker=agent_invoker, dataset=dataset, span_collector=span_collector, config=config, ) for scenario in result.scenario_results: print(f"Scenario: {scenario.scenario_id} ({scenario.status})") for evaluator in scenario.evaluator_results: for r in evaluator.results: print(f" {evaluator.evaluator_id}: {r.get('value')} ({r.get('label')})")

停止條件

模擬對話會在符合下列任一條件時結束:

  1. 目標完成:演員判斷其目標已達成,並發出 訊號stop: true。這是預期的結果。

  2. 達到轉彎上限:對話達到max_turns限制。這可做為安全停止。如果您的案例經常達到轉彎限制,請考慮增加max_turns或簡化演員的目標。

  3. 未產生訊息:演員不會產生下一個訊息,但不會明確發出停止訊號。這被視為隱含目標完成。

有效模擬案例的提示

  • 在目標中具體化:「對話」等模糊目標會導致不專注的互動。像是「取得訂單 #12345 的退款」的特定目標為演員提供了明確的端點。

  • 使用特徵來控制困難:具有 的演員"expertise": "expert"詢問比具有 的更硬的問題"expertise": "novice"。使用特徵來測試不同使用者區段的代理程式。

  • 設定逼真的輪換限制:大多數客戶支援對話會在 5 到 10 輪內解決。設定max_turns過高的浪費運算;設定過低可能會在達到目標之前中斷對話。

  • 對基本事實使用聲明:由於對話流程是動態的,expected_response因此無法按次使用。撰寫描述您預期結果的聲明,無論採取的特定路徑為何。

  • 選擇適當的演員模型:演員模型應足以跨回合維持一致的角色。較小的模型適用於簡單的角色;具有細微目標的複雜角色受益於更強大的模型。