给 AI Agent 装上"裁判眼":buddyMe Eval 系统从零到落地的完整实录
给 AI Agent 装上"裁判眼"
buddyMe Eval 系统从零到落地的完整实录——Schema 设计、真实执行验证、独立上下文注入和全链路测试
01 起因:为什么 Agent 需要评估
如果 Agent 的表现只能靠主观感觉判断,那迭代就是盲人摸象。
OpenAI 在 Evals 方法论中明确提出:Agent 的可靠性不是靠一次 prompt 写好,而是靠持续评估和迭代。 可评估的指标包括任务完成率、工具调用准确率、幻觉率、错误恢复能力、平均完成轮数、成本与延迟。
buddyMe v0.2.1 在 task pipeline、tool system、memory management 上已有成熟实现,但缺少一个关键的闭环——对自身执行结果的评估。这次更新就是补上这个缺口。
02 三个核心设计问题
在动手写代码之前,需要回答三个关键问题:
解法:独立的 LLM 客户端 —
_eval_client = _create_client(model_name)
解法:六维度评估 Schema,每个维度有权重、有 rubric、有 evidence。
解法:三层 JSON 提取 + 结构校验 + 服务端强制重算加权分。
参考框架对比
| 框架 | 核心思路 | buddyMe 借鉴点 |
|---|---|---|
| OpenAI Evals | Traces + Graders + Datasets | 全链路 Trace 采集 |
| DeepEval | Task Completion + Tool Correctness | 维度拆分 + rubric 评分 |
| Braintrust | Multi-step reasoning testing | 多阶段执行路径追踪 |
| AgentHallu | 幻觉归因分类 | truthfulness 维度的评分标准 |
03 架构设计
task_plan(分解步骤) · sub_results(子任务结果) · used_tools(工具调用)written_files(生成文件) · token_in/out(资源消耗) · agent_final_output
- 隔离性:_eval_client 独立于 _client 和 _sub_client,三个客户端互不干扰
- 防御性:不信任 LLM 的计算——加权总分由代码强制重算
- 可降级:LLM 不可用时回退到规则兜底报告
- 可验证:评估前先真实执行生成的代码,将运行结果纳入评估依据
04 六维度评估 Schema
| 维度 | 权重 | 评估什么 | 评分标准 |
|---|---|---|---|
task_completion | 0.30 | 是否完整解决了用户需求 | 1.0=完全满足;0.6=部分满足;0.0=方向错误 |
truthfulness | 0.20 | 输出是否基于真实数据,无幻觉 | 1.0=全部真实;0.4=明显编造;0.0=完全捏造 |
tool_accuracy | 0.15 | 工具选择是否合理、参数是否正确 | 1.0=全部精准;0.6=1-2次不当;0.0=完全错误 |
output_quality | 0.15 | 生成文件的可读性/完整性/可运行性 | 1.0=可直接使用;0.6=需微调;0.0=完全无效 |
error_recovery | 0.10 | 遇到错误时的恢复能力 | 1.0=完美恢复;0.4=尝试但失败;0.0=连锁失败 |
efficiency | 0.10 | 步骤是否精简,无冗余 | 1.0=无冗余;0.4=可减少30%+;0.0=效率极低 |
权重总和 1.00,加权分映射到等级:A >= 0.9, B >= 0.8, C >= 0.7, D >= 0.6, F < 0.6
05 严格 JSON 输出的五重保障
LLM-as-a-Judge 技术最大的痛点是输出格式不可控。我们设计了五重保障:
LLM 负责打分和写证据,加权总分由代码根据权重强制计算。
# 不信任 LLM 的计算——加权总分由代码强制重算 weighted_score = 0.0 for dim_name, dim_info in EVAL_DIMENSIONS.items(): score = report.get(dim_name, {}).get("score", 0.5) weighted_score += score * dim_info["weight"] # 代码计算,非 LLM 输出 grade = "A" if weighted_score >= 0.9 else ...
06 真实执行验证
评估不能只看代码"写了什么",还要看"跑起来是什么"。这是 buddyMe Eval 区别于纯 LLM-as-Judge 的核心特性。
入口文件检测(五阶段优先级)
执行引擎
python "{path}"捕获 stdout/stderr/exit_code
5 项检查
bash "{path}"捕获 stdout/stderr/exit_code
所有执行都有超时保护(30 秒),超时自动 kill。验证结果被标记为"最高优先级证据",放在 eval prompt 的最前面。
07 完整执行流程图
_execute_file() / _validate_html() — 真实执行或结构验证
08 真实测试:北京游览导览
| 项目 | 值 |
|---|---|
| 查询 | 5月17日北京游览导览,生成html格式给我 |
| 模型 | deepseek (deepseek-v4-pro) |
| 子任务模型 | glm-4.7 (sub_agent_code_plan) |
| 评估模型 | deepseek (独立客户端) |
| 总耗时 | ~26 分钟 |
任务分解(6 步)
工具调用统计
baidu_search × 13, write_file × 3, edit_file × 5, read_file × 4, glob × 1, invoke_skill × 3 (frontend-design)
生成文件:beijing_guide_20260517.html — 28,768 bytes / 1,041 行,故宫朱红 × 现代杂志 editorial 美学。
EvalAgent 评估报告
等级: B
任务完成度高,输出质量优秀,但执行效率因冗余步骤而降低
HTML结构验证(5/5): DOCTYPE=Y HTML=Y HEAD=Y BODY=Y 闭合=Y
1. 减少重复搜索,首次搜索后直接使用结果
2. 避免编辑阶段重写整个文件,应使用增量编辑
09 代码改动清单
| 文件 | 改动 | 说明 |
|---|---|---|
agent_moudle/verify.py | 新建 ~975 行 | 评估引擎(Schema + 真实执行验证 + JSON 提取 + 格式化) |
session/state.py | +4 行 | 新增 task_plan、sub_results 字段 |
agent_moudle/task_runner.py | +2 行 | 写入 state.task_plan 和 state.sub_results |
agent_moudle/agent.py | +28 行 | 新增 _eval_client + _evaluator,invoke() 中集成评估 |
initspace/brain/AGENT.md | +45 行 | 新增第 7 节「任务交付与评估」 |
10 踩坑记录
_sub_client 做评估,发现评估 prompt 影响子任务后续调用。解法:
_eval_client = _create_client(model_name),完全独立的客户端实例。
plans 和 sub_results 是 TaskRunner.run() 的局部变量,invoke() 拿不到。解法:在 SessionState 新增
task_plan 和 sub_results 字段。
解法:三层提取——直接解析 → markdown 去包 → 括号配对。成功率从 ~60% → ~95%。
解法:完全不让 LLM 算。
_compute_overall() 由代码强制计算。
11 后续规划
失败案例转 instruction(guardrails)
HTML 截图验证(无头浏览器)
多模型交叉评估(减少单模型偏见)
人工介入率追踪
回归测试集(持续评估)
A/B 测试框架(策略/模型对比)