Agent Platform 评估 SDK 模式实战:从单轮评测到托管 Agent 评估的 8 大代码范式
2026/9/13 11:33:34 网站建设 项目流程

Agent Platform 评估 SDK 模式实战:从单轮评测到托管 Agent 评估的 8 大代码范式

【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills

本篇技术指南围绕 Google Cloud Agent Platform GenAI 评估 SDK(agentplatform)的常用编码模式展开,系统梳理了单轮评测、多轮 Agent 轨迹评测、冷启动合成数据生成、自定义 LLM 裁判、代码执行度量、成对模型对比与结果解析等 8 大实战范式,并覆盖初始化、错误处理等关键环节。读完本文,你将能够基于 sdk_patterns.md 所定义的 API 形态,独立搭建从数据集构造到评估结果落盘的完整评测流程,并接入 Quality Flywheel(质量飞轮)的迭代优化闭环。

前置准备:SDK 初始化与依赖安装

安装依赖

评估脚本依赖agentplatform(基于google-cloud-aiplatform[evaluation])、google-genaipandasrequests。仓库 SKILL.md 建议不要创建虚拟环境——空虚拟环境会隐藏环境中已装好的包,导致冗余安装。正确做法是先探测再补装缺失的包:

python3 -c "import vertexai, google.genai, pandas, requests" \ || pip install 'google-cloud-aiplatform[evaluation]>=1.163.0' 'google-genai>=1.0.0'

注意:版本号约束必须加引号,未加引号时 bash 会把>=1.163.0当作重定向,静默写出一个空文件而非约束安装版本。

客户端初始化

import agentplatform from agentplatform import types from google.genai import types as genai_types client = agentplatform.Client(project="{PROJECT_ID}", location="{LOCATION}")

初始化前需确认环境变量GOOGLE_CLOUD_PROJECTGOOGLE_CLOUD_LOCATION已配置;对于 Gemini 3+ 模型,应使用location="global"。新版本的 Gemini 模型通常也建议location="global"

一个极易踩坑的关键约定

EvalCaseprompt/reference/response值都是Content 对象,而非纯字符串。必须使用genai_types.UserContent(str)/genai_types.ModelContent(str)包装——它们会把字符串包进一个 Part 并设置正确的角色。直接传字符串会触发pydantic.ValidationError(快速失败),这是构造数据集时最常见的错误之一(详见 dataset_schema.md 的 Core Types 说明)。

SDK 入口的正确形态

评估相关操作统一挂在client.evals下:

client.evals.run_inference(model=..., src=...) client.evals.evaluate(dataset=..., metrics=...) client.evals.generate_conversation_scenarios(...)

两个看起来合理但不可用的导入形态(来自 SKILL.md):

  • from agentplatform.types import evals——会抛ModuleNotFoundErrortypes是模块而非包,应使用from agentplatform import types
  • from vertexai.evaluation import PointwiseMetric, EvalTask——这是已被取代的旧 SDK,其类参数不同(如PointwiseMetric没有system_instruction),按旧 API 写的代码会以TypeError而非导入错误失败。

Pattern 1:单轮评测——最简单的起点

单轮评测适用于 QA、摘要等 prompt/response 对评估。构造EvaluationDataset并在metrics中同时混用预定义 rubric 度量与计算型度量:

dataset = types.EvaluationDataset(eval_cases=[ types.EvalCase( prompt=genai_types.UserContent("What causes rain?"), responses=[types.ResponseCandidate( response=genai_types.ModelContent( "Rain is caused by water evaporating..."))], reference=types.ResponseCandidate( response=genai_types.ModelContent( "Rain forms when water vapor condenses...")), ), ]) result = client.evals.evaluate( dataset=dataset, metrics=[ types.RubricMetric.GENERAL_QUALITY, types.Metric(name="rouge_l_sum"), ], )

注意三点细节:

  • responses复数列表,不存在单数的response=参数。由于EvalCase设置了extra="allow",误写response=不会报错,而是被静默存储、永不读取,候选响应按缺失计分——这是典型的"静默失败"陷阱;
  • referenceResponseCandidate对象而非字符串;
  • types.Metric(name="rouge_l_sum")走的是确定性计算路径,无需 LLM 裁判。

如果觉得直接构造EvalCase过于冗长易错,可以改用 pandas DataFrame 形式,转换器会自动用字符串列包装成 Content 对象(推荐):

import pandas as pd from agentplatform import types df = pd.DataFrame({ "prompt": ["What is 2+2?", "Capital of France?"], "response": ["4", "Paris"], "reference": ["4", "Paris"], }) dataset = types.EvaluationDataset(eval_dataset_df=df)

这一推荐路径在 dataset_schema.md 中有完整说明。

Pattern 2:多轮 Agent 评测——带工具调用的完整轨迹

要评估一个完整的多轮 Agent 对话轨迹(含工具调用),需要使用AgentData类型层级:AgentDataConversationTurnAgentEvent。每个AgentEvent通过author区分发言者,content按角色区分消息类型:

agent_data = types.evals.AgentData( agents={ "my_agent": types.evals.AgentConfig( agent_id="my_agent", instruction="You are a helpful assistant.", tools=[genai_types.Tool(function_declarations=[ genai_types.FunctionDeclaration( name="search", description="Search the web", parameters=genai_types.Schema( type="OBJECT", properties={"query": genai_types.Schema(type="STRING")}, ), ), ])], ), }, turns=[ types.evals.ConversationTurn(turn_index=0, events=[ types.evals.AgentEvent( author="user", content=genai_types.Content(role="user", parts=[genai_types.Part(text="Find me the weather in NYC")]), ), types.evals.AgentEvent( author="my_agent", content=genai_types.Content(role="model", parts=[genai_types.Part(function_call=genai_types.FunctionCall( name="search", args={"query": "NYC weather"}))]), ), types.evals.AgentEvent( author="my_agent", content=genai_types.Content(role="tool", parts=[genai_types.Part(function_response=genai_types.FunctionResponse( name="search", response={"result": "72F, sunny"}))]), ), types.evals.AgentEvent( author="my_agent", content=genai_types.Content(role="model", parts=[genai_types.Part(text="It's 72F and sunny in NYC.")]), ), ]), ], ) result = client.evals.evaluate( dataset=types.EvaluationDataset(eval_cases=[ types.EvalCase(agent_data=agent_data), ]), metrics=[ types.RubricMetric.MULTI_TURN_TRAJECTORY_QUALITY, types.RubricMetric.MULTI_TURN_TASK_SUCCESS, ], )

轨迹构造的硬性约定

仓库中的 validate_dataset.py 脚本会对这些约束做自动化校验,其校验逻辑揭示了以下规则:

  • 角色必须是user/model/tool,使用role="assistant"会被判为错误(Agent Platform 约定用model);
  • turn_index必须是从 0 开始连续递增的序号,非顺序索引会触发 WARNING;
  • 工具响应必须用genai_types.FunctionResponse包装,且parts不能为空;
  • 每个EvalCase只能使用prompt(单轮)或agent_data(多轮)二选一,混用会被标记。

另外,若你的轨迹来自 ADK(Agent Development Kit)会话导出,无需手写转换逻辑,直接使用仓库脚本python scripts/parse_adk_traces.py --input session.json --output dataset.json(详见 parse_adk_traces.py)。

Pattern 3:冷启动合成数据生成——没有评估数据时怎么办

当评估数据集为空、无从谈起评测时,可以用"生成场景 → 模拟推理 → 评估"三步走的冷启动流程:

# Step 1: Generate scenarios scenarios = client.evals.generate_conversation_scenarios( agents={ "agent": types.evals.AgentConfig( agent_id="agent", instruction="You are a customer support agent for an airline.", ), }, root_agent_id="agent", user_scenario_generation_config=types.evals.UserScenarioGenerationConfig( user_scenario_count=10, simulation_instruction="Simulate customers with flight booking issues.", environment_data="Flights available: NYC-LAX, NYC-SFO. Cancellation policy: free within 24h.", model_name="gemini-2.5-flash", ), ) # Step 2: Run inference with user simulation dataset_with_responses = client.evals.run_inference( agent=my_agent, # Your callable agent src=scenarios, config={ "user_simulator_config": { "model_name": "gemini-2.5-flash", "max_turn": 5, }, }, ) # Step 3: Evaluate result = client.evals.evaluate( dataset=dataset_with_responses, metrics=[types.RubricMetric.MULTI_TURN_GENERAL_QUALITY, types.RubricMetric.SAFETY], )

冷启动 API 的三个易错点

SKILL.md 明确标注了该 API 的坑:

  • 参数名是agentagent_info不是agents(Pattern 2 构造数据集时才是agents),且config为必填;
  • 配置类全名是types.evals.UserScenarioGenerationConfig,不是types.UserScenarioGenerationConfig
  • 必须设置user_scenario_count(取值范围 1–100)。它默认是None,客户端会照单全收,然后服务端以400 INVALID_ARGUMENT拒绝调用;注意count是另一个独立字段,不能替代它。

在推理阶段,run_inference对不同类型的被评测对象形态不同(SKILL.md Stage 2):

  • Agent 评测:传model=agent_callable(包装用户 ADK Agent/App 的可调用对象);
  • 模型评测:直接传模型 ID,如model="gemini-2.5-flash"
  • 合成场景:让模拟器驱动,加user_simulator_config=UserSimulatorConfig(max_turn=10)
  • DataFrame 也可直接作为src=,无需包EvalCase

Pattern 4:用 MetricPromptBuilder 构建自定义 LLM 裁判

领域特定评估(如医疗、金融、客服质量)没有现成的内置度量时,可以用LLMMetric+MetricPromptBuilder构建结构化评分裁判。与手写prompt_template字符串相比,MetricPromptBuilder更适合复杂评分卡:

metric = types.LLMMetric( name="domain_expertise", prompt_template=types.MetricPromptBuilder( metric_definition="Evaluates domain expertise in the response.", criteria={ "Accuracy": "Claims are factually correct for the domain", "Depth": "Response shows understanding beyond surface level", "Actionability": "Advice is specific and actionable", }, rating_scores={ "1": "Incorrect or misleading information", "2": "Partially correct but superficial", "3": "Correct and shows reasonable understanding", "4": "Accurate with good depth", "5": "Expert-level accuracy, depth, and actionability", }, ), judge_model="gemini-2.5-flash", judge_model_sampling_count=3, )

使用 LLM 裁判的硬性规则

  • criteriarating_scores两者都必填,只提供一个会抛ValidationError: Both 'criteria' and 'rating_scores' are required to construct the LLM-based metric prompt template text(见 metric_registry.md);
  • 必须显式设置judge_model。它默认是None,此时每个评测用例都会以400 INVALID_ARGUMENT: Error parsing JSON失败;
  • judge_model_sampling_count默认 1、上限 32,值过高会导致评测超时(见 failure_patterns.md)。

若只是基于固定 prompt 模板而非结构化评分卡,也可以直接使用types.LLMMetric(name=..., prompt_template="...", judge_model=...)形态,甚至支持从 YAML/JSON 文件加载(types.LLMMetric.load("path/to/metric_config.yaml"))。

Pattern 5:CodeExecutionMetric 结构化校验——超越文本对比

当需要程序化校验(如 JSON 结构、正则、字段完整性)时,用CodeExecutionMetric在远程沙箱中执行 Python 函数。函数必须命名为evaluate(instance: dict) -> dict,返回{"score": ..., "explanation": ...}

# Validate JSON output structure json_validator = types.CodeExecutionMetric( name="json_structure_check", custom_function=''' import json def evaluate(instance: dict) -> dict: try: data = json.loads(instance.get("response", "")) required_keys = {"name", "status", "result"} missing = required_keys - set(data.keys()) if missing: return {"score": 0.0, "explanation": f"Missing keys: {missing}"} return {"score": 1.0, "explanation": "All required keys present"} except json.JSONDecodeError as e: return {"score": 0.0, "explanation": f"Invalid JSON: {e}"} ''', )

本地函数与远程沙箱的选择

metric_registry.md 区分了两种自定义代码度量:

  • 本地自定义函数types.Metric(name=..., custom_function=<callable>)):客户端执行、迭代最快、无 API 调用,但以调用进程的权限运行,只可用于可信代码
  • 远程沙箱执行CodeExecutionMetriccustom_function字符串):在 Agent Platform 沙箱中运行,适合不可信代码。

SDK 内部的度量处理器按固定顺序分派(Handler Dispatch Order):先匹配CodeExecutionMetric的字符串函数,再匹配本地Callable、注册度量资源名、计算型度量(bleu/rouge_1等)、翻译度量(comet/metricx)、API 预定义度量,最后才是LLMMetricprompt_template。理解这个顺序有助于排查"自定义度量没生效"的问题。

注意:在 Agent 轨迹数据集的instance字典里,顶层标准字段是agent_data(结构化的 turns/events 对象),最终回复嵌在其中;扁平占位符{response}只在 DataFrame 评测路径下可用。自定义函数应始终用.get()带默认值(见 failure_patterns.md 的 KeyError 故障说明)。

Pattern 6:成对模型对比——用 calculate_win_rates 计算胜率

对比两个模型时,SDK 没有PairwiseMetric类。正确做法是:对同一数据集分别跑两个模型的评估,再用calculate_win_rates()计算胜率:

# Same dataset, two different model responses dataset_a = types.EvaluationDataset(eval_cases=[ types.EvalCase(prompt=genai_types.UserContent("Explain quantum computing"), responses=[types.ResponseCandidate( response=genai_types.ModelContent( "Model A response..."))]), ]) dataset_b = types.EvaluationDataset(eval_cases=[ types.EvalCase(prompt=genai_types.UserContent("Explain quantum computing"), responses=[types.ResponseCandidate( response=genai_types.ModelContent( "Model B response..."))]), ]) result_a = client.evals.evaluate(dataset=dataset_a, metrics=[types.RubricMetric.GENERAL_QUALITY]) result_b = client.evals.evaluate(dataset=dataset_b, metrics=[types.RubricMetric.GENERAL_QUALITY]) # Compare from agentplatform._genai._evals_metric_handlers import calculate_win_rates win_rates = calculate_win_rates(result_a, result_b)

该方法与 metric_registry.md 中 "Pairwise Comparison" 一节的用法一致。注意calculate_win_rates来自 SDK 内部模块_evals_metric_handlers,这是文档中唯一出现的内部导入路径,其余场景应尽量使用公开 API。

Pattern 7:结果解析——从摘要到逐条 rubric 判定

evaluate()返回的结果对象有清晰的层级,可按三种粒度解析:

result = client.evals.evaluate(dataset=dataset, metrics=metrics) # Interactive HTML report (recommended) result.show() # Summary level for summary in result.summary_metrics: print(f"{summary.metric_name}: mean={summary.mean_score}, pass_rate={summary.pass_rate}") # Per-case level for case in result.eval_case_results: for candidate in case.response_candidate_results: for metric_name, metric_result in candidate.metric_results.items(): print(f" {metric_name}: score={metric_result.score}") print(f" explanation: {metric_result.explanation}") # Rubric verdicts (for rubric-based metrics) if metric_result.rubric_verdicts: for v in metric_result.rubric_verdicts: print(f" rubric {v.evaluated_rubric.rubric_id}: " f"{'PASS' if v.verdict else 'FAIL'} - {v.reasoning}")

持久化结果:JSON + HTML 双份落盘

结果字段路径很深(eval_case_results[].response_candidate_results),建议落盘保存供后续分析与对比。仓库 SKILL.md Stage 3 给出了标准做法——JSON(机器可读、可 diff)与 HTML(人类可读、可分享)各存一份:

import datetime from pathlib import Path from agentplatform._genai import _evals_visualization out_dir = Path("artifacts/grade_results") out_dir.mkdir(parents=True, exist_ok=True) ts = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") # fallback=str, or a DataFrame-backed dataset raises PydanticSerializationError. result_json = result.model_dump_json(fallback=str) (out_dir / f"results_{ts}.json").write_text(result_json) html = _evals_visualization.get_evaluation_html(result_json) (out_dir / f"results_{ts}.html").write_text(str(html))

之后可以用仓库配套脚本快速渲染与筛选(inspect_results.py):

python scripts/inspect_results.py --result result.json # 摘要 + 逐用例分数 python scripts/inspect_results.py --result result.json --failing-only # 只看失败用例 (score < 1.0) python scripts/inspect_results.py --result result.json --metric multi_turn_task_success python scripts/inspect_results.py --result result.json --save-html report.html

在迭代优化阶段,用 compare_results.py 对比修复前后两个结果文件,确认目标指标提升且无回归:

python scripts/compare_results.py --baseline baseline.json --candidate candidate.json python scripts/compare_results.py -b baseline.json -c candidate.json --threshold 0.05 --json

该脚本按metric_name对齐两文件的summary_metrics,输出均值与通过率的增量;任一指标下降超过阈值(默认 0.0,即任何下降都算回归)时退出码为 1。

Pattern 8:托管 Agent 评估(Gemini Agents API)

对于使用 Managed Agents API 构建的 Agent,可以只凭其资源名完成"生成场景 → 推理 → 评估"的完整工作流,无需自己包装可调用对象:

import agentplatform from agentplatform import types client = agentplatform.Client(project="PROJECT_ID", location="global") AGENT_RESOURCE = "projects/PROJECT_ID/locations/global/agents/AGENT_ID" # Step 1: Generate conversation scenarios from the agent's configuration. scenarios = client.evals.generate_conversation_scenarios( agent=AGENT_RESOURCE, config={ "user_scenario_count": 5, "simulation_instruction": "Create agent scenarios", }, ) scenarios.show() # Step 2: Run inference, execute the agent against each scenario. inference_results = client.evals.run_inference( agent=AGENT_RESOURCE, src=scenarios, config={"user_simulator_config": {"max_turn": 3}}, ) inference_results.show() # Step 3: Evaluate the conversation traces. result = client.evals.evaluate( dataset=inference_results, metrics=[types.RubricMetric.MULTI_TURN_TASK_SUCCESS], agent=AGENT_RESOURCE, ) result.show()

注意这里generate_conversation_scenariosrun_inferenceagent参数直接接受资源名(形如projects/.../locations/global/agents/...),并且location固定为global

评估已记录的交互(Interactions API)

如果交互已通过 Interactions API 记录,可以跳过推理直接评估,避免重复运行:

interactions_dataset = types.EvaluationDataset( eval_cases=[ types.EvalCase( interactions_data_source=types.InteractionsDataSource( interaction="projects/PROJECT_ID/locations/global/interactions/INTERACTION_ID", gemini_agent_config=types.GeminiAgentConfig( gemini_agent=AGENT_RESOURCE, ), ), ), ] ) result = client.evals.evaluate( dataset=interactions_dataset, metrics=[types.RubricMetric.MULTI_TURN_TASK_SUCCESS], agent=AGENT_RESOURCE, ) result.show()

错误处理:区分权限、参数与配额问题

evaluate()调用失败时,根据异常类型快速定位问题类别:

try: result = client.evals.evaluate(dataset=dataset, metrics=metrics) except Exception as e: error_type = type(e).__name__ if "PermissionDenied" in error_type: print("Check: GCP project permissions, API enabled, billing active") elif "InvalidArgument" in error_type: print("Check: dataset format, metric compatibility with data type") elif "ResourceExhausted" in error_type: print("Check: API quota, reduce dataset size or add delay") else: raise

结合 failure_patterns.md 的故障排查清单,这三类错误的常见根因分别是:

  • PermissionDenied:GCP 项目权限不足、API 未启用、结算未激活;
  • InvalidArgument:数据集格式错误(如prompt传了字符串)、度量与数据类型不匹配(如对单轮数据用了multi_turn_*度量)、judge_model未设置;
  • ResourceExhausted:API 配额耗尽,可减小数据集或增加延迟。

另需留意is_infra_error: true的结构性失败(配额、超时、端点不可用)与评测超时问题——超时通常源于数据集过大、自定义度量代码过慢或judge_model_sampling_count过高,可分批评测并降低采样数。

接入 Quality Flywheel:五个阶段如何落地

以上模式是 agent-platform-eval-flywheel 这套 Skill 的技术底座。在实战中,它们服务于"质量飞轮"的五个阶段:

  1. 准备数据(Prepare Data):按 Pattern 1/2 构造数据集(EvalCase、DataFrame 或agent_data),或用 Pattern 3 冷启动生成,提交前用scripts/validate_dataset.py校验;
  2. 运行推理(Run Inference):用run_inference填充响应,已有完整轨迹(如生产日志回放)时跳过;
  3. 评分(Grade,必做):按 Pattern 1/4/5 选择度量并执行evaluate(),按 Pattern 7 落盘 JSON + HTML;度量选择参考 metric_registry.md 的分类(Agent 度量优先multi_turn_task_success/multi_turn_trajectory_quality/multi_turn_tool_use_quality,静态 rubric 关注hallucination/grounding/safety);
  4. 分析失败(Analyze Failures):用 Pattern 7 解析 rubric verdicts,配合scripts/inspect_results.py --failing-only定位失败用例;同一指标 10+ 失败时可用 Error Analysis 服务(client.evals.generate_loss_clusters)聚类失败主题;
  5. 优化迭代(Optimize & Iterate):针对失败指标修复 Agent 或提示词,重跑后用scripts/compare_results.py确认目标提升且无回归。

每个失败用例通常需要 5–10+ 次迭代。需要特别提醒的是:评测结果必须来自真实的result对象,绝不可编造分数;无法产出证据(SDK 调用失败、结果截断、度量不支持)时应当明确说明,而不是掩盖缺口——这是该 Skill 反复强调的"Proving your work"原则。

延伸阅读

  • sdk_patterns.md:本文所依据的模式定义原文
  • dataset_schema.md:EvaluationDataset/EvalCase/AgentData完整类型层级与字段说明
  • metric_registry.md:全部预定义、计算型、翻译、多模态与自定义度量的目录与选择指南
  • failure_patterns.md:常见失败模式到根因与修复方案的映射
  • SKILL.md:Quality Flywheel 完整方法论与安全确认层级
  • validate_dataset.py:评测数据集结构校验脚本
  • parse_adk_traces.py:ADK 会话轨迹转规范数据集脚本
  • inspect_results.py:结果摘要与逐用例分数渲染脚本
  • compare_results.py:基线 vs 候选结果对比与回归检测脚本

【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询