agents-cli 用户模拟评测实战:用 eval dataset synthesize 驱动 ADK Agent 的动态多轮评测
【免费下载链接】agents-cliThe CLI and skills that turn any coding assistant into an expert at creating, evaluating, and deploying AI agents on Google Cloud.项目地址: https://gitcode.com/GitHub_Trending/ag/agents-cli
本文介绍 Google agents-cli 评测体系中的用户模拟(User Simulation)机制:当固定 prompt 无法覆盖 agent 的多种提问顺序与临场反应时,agents-cli eval dataset synthesize会调用 Vertex AI 评测服务从 agent 的工具与指令中生成用户场景(user scenario),再由 LLM 驱动的用户模拟器逐场景扮演用户完成多轮对话,产出的 trace 可跳过eval generate直接进入eval grade评分。读完后你将掌握该命令的全部 CLI 参数、输出文件结构、兼容指标的配置方式,以及其底层执行链路与适用限制。
框架限制(ADK 项目)。
agents-cli eval dataset synthesize通过 ADK 加载并运行 agent,因此仅适用于 ADK 项目;其余评测环节(eval generate、eval grade、指标体系、数据集 schema)是框架无关的。
何时使用用户模拟
固定的评测 prompt 在多轮 agent 上往往不够用:agent 可能以不同顺序向用户索要信息,也可能以未预期的方式应答。逐条手工录制每个 user/agent 轮次既低效又脆弱。用户模拟的思路是:让agents-cli eval dataset synthesize请求 Vertex AI 评测服务为你的 agent 生成用户场景,然后由一个 LLM 支撑的用户模拟器逐一"扮演用户"与 agent 对话,最终得到带完整agent_data.turns的 trace,直接投入agents-cli eval grade。
一个**用户场景(user scenario)**由两部分组成:
starting_prompt— 模拟用户的开场白;conversation_plan— 自由文本描述,规定模拟用户在后续对话中应如何行为。
在 agents-cli 流程中这些场景不需要你自己编写——eval dataset synthesize会根据 agent 的工具描述与指令自动生成。
确定性的手工评测用例(例如回归覆盖)请改用"已录轮次"格式:直接在数据集中写
agent_data.turns,再用agents-cli eval generate回放。参见 dataset_schema.md。注意agents-cli eval generate要求每个 case 具有顶层prompt或agent_data,它不会回放手工编写的user_scenariocase。
运行eval dataset synthesize
# 生成 3 个场景(默认值),模拟执行,trace 写入 artifacts/traces/traces_<ts>.json agents-cli eval dataset synthesize # 用 instruction 与环境上下文引导场景生成 agents-cli eval dataset synthesize \ -n 5 \ --max-turns 8 \ --instruction "Customer asking about refunds" \ --environment-context "E-commerce support; orders are visible by order_id" # 为场景生成指定自定义模型(默认:服务端默认模型) agents-cli eval dataset synthesize --model gemini-2.5-proagents-cli eval dataset synthesize暴露的 CLI 参数:
| 参数 | 作用 |
|---|---|
-n / --count | 生成的场景数量(默认 3,最小 1) |
--instruction | 引导场景生成的自然语言指令 |
--environment-context | 模拟器可以依赖的世界背景(例如可用数据) |
--model | 用于场景生成的模型(服务端调用,不是模拟用户所用的模型) |
--max-turns | 每个场景 user↔agent 轮次上限(默认 5,最小 1) |
-o / --output | 输出路径;默认artifacts/traces/traces_<ts>.json |
这些默认值在 CLI 源码中得到印证:cmd_dataset.py 中--count与--max-turns均声明为click.IntRange(min=1),默认分别为 3 和 5。
运行前提与环境变量行为:synthesize在本地运行你的 agent,并从 agent 的.env读取配置(读取整个文件——GOOGLE_GENAI_USE_VERTEXAI、GEMINI_API_KEY、GOOGLE_CLOUD_*以及应用自定义变量),没有--project/--region参数。在 Vertex AI 上,GOOGLE_CLOUD_LOCATION还会决定服务端场景生成调用的端点,而该调用只支持部分评测区域——除非确认所在区域受支持,否则保持global(scaffold 默认值)不变。
从源码结构看,命令的执行流程是(cmd_dataset.py):
- 通过
pyproject.toml定位项目根,并读取agents-cli-manifest.yaml中的agent_directory确定 agent 目录; - 执行
uv sync --dev --extra eval同步评测依赖; - 将内置 runner 脚本暂存到项目下的
.agents-cli-scripts/目录,并以uv run python在用户项目的虚拟环境中执行(脚本每次运行覆盖、结束后清理),整体超时 600 秒,超时错误会提示检查.env中的GOOGLE_CLOUD_LOCATION; - 参数以 JSON 传入 runner:
count、generation_instruction(来自--instruction)、environment_context、model_name(来自--model)。
模拟器内部不可从 agents-cli 配置。扮演用户一方的 LLM 模拟器运行在 _synthesize_runner.py 内,使用硬编码的 ADK 默认值(用户声音模型为gemini-2.5-flash、默认 thinking 配置、无custom_instructions)。只有--max-turns会传递到模拟器(作为LlmBackedUserSimulatorConfig.max_allowed_invocations)。不存在eval_config.yaml配置项、不存在--simulator-model参数,也无法在不直接编辑_synthesize_runner.py的情况下覆盖custom_instructions或model_configuration。
synthesize写出什么
输出是一个 JSONEvaluationDataset文件,位于-o指定路径。每个 case 包含:
eval_case_id— 服务端生成的 UUID;user_scenario— 生成的{starting_prompt, conversation_plan}(为可追溯性而保留);agent_data.turns— 完整模拟对话:用户事件、agent 应答、工具调用、工具响应。
由于agent_data.turns已完整填充,该文件本身就是可直接评分(graded-ready)的 trace。跳过eval generate,直接执行eval grade:
agents-cli eval dataset synthesize agents-cli eval grade # 默认读取 artifacts/traces/这一路径约定在 _paths.py 中有单一定义:stage-2 产物(已填充的 trace)位于artifacts/traces/traces_<ts>.json,由eval generate或eval dataset synthesize产生、供eval grade消费;--output若以/结尾或指向已有目录,则在其内部写入带时间戳的文件(resolve_output_path)。
部分场景失败不阻塞流程。如果某些场景模拟失败,这些 case 会以空的agent_data.turns留在输出文件中,并在 stderr 打印告警;其余成功 case 照常进入eval grade。对应实现在 runner 的模拟循环:每个场景的异常被单独捕获、invocations置空并计入failures,最终统一输出x/N scenarios failed during simulation; their agent_data will have empty turns.告警。
从 runner 源码还可确认 trace 的组装细节(_synthesize_runner.py):每次 ADKInvocation被转换为一个 turn(带turn_index、turn_id与events列表),事件序列依次为user_content(author=user)、中间调用事件/工具调用(来自invocation_events或tool_uses)、以及final_response(author=agent);同时通过_final_response_from_invocations从最后一个含文本的应答中抽取responses[0],保证LLMMetric与custom_function能读到instance.response而不报错。
兼容的评分指标
合成 trace 是多轮对话且没有标准答案(ground truth),因此只有三个多轮指标可用(其他内置指标在多轮 trace 上会返回 400,基于参考的指标也没有可匹配的参考内容):
| 指标 | 为什么适用 |
|---|---|
multi_turn_task_success | 自适应 rubric 判定模拟用户的目标是否达成 |
multi_turn_trajectory_quality | 自适应 rubric 评估跨轮次的 agent 推理 |
multi_turn_tool_use_quality | 自适应 rubric 评估跨轮次的工具调用 |
与 metrics-guide.md 中的指标参考一致:这三个指标在 Trace 列均标注为any;而multi_turn_general_quality、multi_turn_text_quality需要eval generate不产生的conversation_history字段,在 agent trace 上同样 400。
针对合成 trace 的tests/eval/eval_config.yaml示例:
metrics_to_run: - multi_turn_task_success - multi_turn_trajectory_quality - multi_turn_tool_use_quality执行:
agents-cli eval grade --config tests/eval/eval_config.yamleval_config.yaml会被eval run、eval grade、eval submit读取;eval dataset synthesize则忽略它。
实现链路:从 CLI 参数到 Vertex AI 调用
把文档描述与 runner 源码 对照,可以还原完整调用链:
- 加载 agent:通过 ADK 的
AgentLoader从agent_directory加载 agent,并先_load_agent_dotenv把项目.env全量注入os.environ(已有 OS 环境变量优先,override=False,与 ADK 的load_dotenv_for_agent行为一致); - 构建 AgentInfo:
types.evals.AgentInfo.load_from_agent(agent=agent)从 agent 提取指令与工具声明——这正是"场景质量完全取决于 agent 元数据"的出处。runner 内还有_safe_tool_declarations兜底:对无tools属性的 workflow agent(如SequentialAgent)返回空声明而非崩溃,对不可内省的 ADK toolset(如 MCP toolset)跳过;被跳过的 toolset 仍保留在真实 agent 上,其工具调用照常出现在 trace 中; - 服务端场景生成:调用
client.evals.generate_conversation_scenarios(agent_info=..., config=..., allow_cross_region_model=True),project/location取自.env的GOOGLE_CLOUD_PROJECT/GOOGLE_CLOUD_LOCATION。CLI 侧传入的count、generation_instruction、environment_context、model_name都进入config; - 本地用户模拟:对每个 case 构建
ConversationScenario(starting_prompt, conversation_plan)与LlmBackedUserSimulator(仅max_allowed_invocations=max_turns一项配置),由EvaluationGenerator._generate_inferences_from_root_agent驱动真实 agent 与模拟器对话,初始会话为app_name="user_simulation_app"、user_id="user_simulation_default_user",并传入 agent 的reset_data作为会话间重置钩子; - 落盘:所有 case 组成
EvaluationDataset,以model_dump_json(indent=2, exclude_none=True)写到输出路径。
配套测试也可以佐证 trace 契约的稳定性:test_eval_generate.py 中TestGradeContract明确"turn 必须带turn_index/turn_id、输出必须能被eval grade使用的EvaluationDataset模型解析",防止 trace 形状与服务端约定漂移。
实用注意事项
- 场景质量完全取决于 agent 元数据。
generate_conversation_scenarios读取 agent 的指令与工具描述来生成可信的用户行为。含糊的工具描述只会得到含糊的场景——在新 agent 上首次运行 synthesize 之前,先把工具 docstring 写精确。 --max-turns是硬上限。模拟用户可能提前停止(目标达成或放弃);--max-turns只是防止对话失控的保险丝,不是期望轮次。- 重跑 synthesize 会生成全新场景。没有 seed 参数——每次调用都产生新的场景集合。需要可重复的回归覆盖时,直接手写
agent_data.turns(见 dataset_schema.md),而不是依赖synthesize。 - 实验性命令。CLI 在每次执行时都会打印 "
eval dataset synthesizeis experimental and may change" 警告,行为与参数可能调整;agents-cli eval dataset synthesize --help输出的参数列表才是当前版本的权威来源。
小结
用户模拟是 agents-cli 评测飞轮中"准备数据"阶段的关键加速器:没有现成对话数据时,eval dataset synthesize从 agent 自身元数据合成多轮场景并本地跑通模拟器,输出带完整agent_data.turns与保留user_scenario的 trace 文件,直接对接eval grade与三个多轮自适应 rubric 指标。使用时的核心约束有三条:仅支持 ADK 项目、模拟器内部参数不可配置(只能调--max-turns)、场景不可复现(无 seed)——确定性回归应始终落到手写agent_data.turns上。更完整的命令与指标说明见 SKILL.md、metrics-guide.md 与原文档 user-simulation.md。
【免费下载链接】agents-cliThe CLI and skills that turn any coding assistant into an expert at creating, evaluating, and deploying AI agents on Google Cloud.项目地址: https://gitcode.com/GitHub_Trending/ag/agents-cli
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考