09. 工程落地 Playbook
读完本章,你应该能:
本章回答:怎样把 eval 从一次性分析变成持续运行的工程系统。
学习目标
读完本章,你应该能:
- 设计一个最小可用 eval stack。
- 区分 offline eval、online eval、CI gate 和 human review。
- 选择适合你阶段的工具和数据结构。
- 为 prompt、tool、model、harness、runtime 改动建立回归保护。
本章导读
如果前面的章节是在讲“什么是好的 eval”,这一章关心的是“怎样让好的 eval 留在团队日常里”。很多 eval 工作失败,不是因为第一次分析不精彩,而是因为它没有进入工程流程。报告写完了,bug 修了几个,过两周 prompt 一改,旧问题又回来了;线上出现新失败,没人把它加回数据集;judge prompt 更新了,却没有重新校准。
eval 真正产生复利,是从它变成基础设施开始的。基础设施不一定复杂,它可以是一组 JSONL、几个 pytest、一个 GitHub Action 和一份每周错误分析表。关键是:每个重要失败都能留下回归样本,每次改动都能跑同一套检查,每次线上新问题都能回到离线数据集。这样,系统不是靠记忆变好,而是靠机制变好。
本章的重点不是推荐某个工具,而是梳理这些机制应该如何连接。工具可以换,流程不能断:记录 trace,维护 dataset,版本化 scorer,比较实验,阻断高风险回归,监控线上漂移,再把新失败带回下一轮。
工程落地的核心原则
Eval 工程不是为了追求平台复杂度,而是为了让反馈更快、更可信、更可复现。一个小团队可以从 CSV、JSONL、pytest 和 promptfoo 起步;一个成熟团队可以引入 Braintrust、Langfuse、Phoenix、MLflow、Inspect AI、Weave 等平台。工具选择不是关键,关键是系统必须闭环:
trace logging -> dataset -> scorer -> experiment -> analysis -> fix -> regression -> monitoring如果其中任何一环缺失,eval 都会退化成一次性报告。
想象一次普通 PR:工程师改了报销 agent 的 system prompt,让它“尽量减少追问,提高处理效率”。如果没有 eval 基础设施,这个改动可能只经过几条手工 demo;如果有一套闭环,它会自动跑 golden set、回归集和高风险 policy cases,记录每条 trace,比较是否更少追问但更多错误提交,并在超预算报销 case 失败时阻断合并。工程落地的意义就在这里:把抽象的“质量担忧”变成每次改动都会触发的证据。
最小可用 eval stack
1. Logging / tracing
至少记录:
- request id / user id hash / session id。
- input、context、retrieved docs。
- model、prompt version、tool version。
- tool calls、arguments、observations、errors。
- final output。
- final environment state 或 state diff。
- latency、token、cost。
- human feedback 或人工标签。
没有 trace,就无法做错误分析;没有版本号,就无法解释回归。
日志不是为了事后追责,而是为了让失败可学习。一个 eval run 只记录“case 失败”几乎没有用;你需要知道失败时用了哪个 prompt、检索到了哪份政策、调用了哪个工具、工具返回了什么、最终状态怎么变了。没有这些字段,团队会在失败面前重新回到猜测:是模型问题、工具问题、数据问题,还是 scorer 问题?
2. Dataset
建议把 eval cases 放在 repo 中,使用 JSONL/YAML/CSV:
{
"id": "expense_project_code_001",
"source": "production_trace",
"task": "prepare_expense_report",
"input": "帮我把上周上海出差的高铁和酒店报销掉",
"context": {
"channel": "internal_chat",
"employee_id": "E1024",
"project_code": null,
"hotel_amount": 1280,
"hotel_limit": 900
},
"expected": {
"must_ask_for": ["project_code", "over_budget_explanation"],
"must_not_call": ["submit_expense"]
},
"tags": ["expense", "policy", "regression"],
"severity": 4
}数据集要版本化。每条 case 应该能追溯来源和原因。
版本化的核心不是形式,而是可解释性。两周前通过率 91%,今天 86%,到底是模型退步、prompt 变化、数据集新增了难例,还是 scorer 更严格了?如果 dataset、scorer、prompt 和 runtime 没有版本,数字变化就无法被解释,也无法支撑决策。
3. Scorers
Scorer 应以代码或配置管理。常见组合:
assert_valid_json(output)assert_required_expense_fields(trace, output)assert_no_submit_without_confirmation(trace)assert_state_diff(before, after)judge_should_escalate_policy_risk(trace)judge_grounded_answer(input, context, output)
每个 scorer 要有:
- 名称。
- 版本。
- 输入字段。
- 失败解释。
- 适用 case tags。
- 校准报告,如果是 LLM judge。
4. Experiment runner
runner 负责:
- 加载 dataset。
- 调用系统。
- 隔离环境。
- 记录 trace。
- 运行 scorers。
- 输出 per-case results 和 aggregate metrics。
结果至少包含:
{
"run_id": "2026-06-28-agent-v3",
"git_sha": "abc123",
"model": "MODEL_NAME",
"prompt_version": "2026-06-28",
"dataset_version": "golden-2026-06-28",
"metrics": {
"pass_rate": 0.91,
"policy_violation_rate": 0.01,
"cost_per_success": 0.18
},
"failures": [
{
"case_id": "expense_over_budget_009",
"scorer": "expense_policy_judge@v3",
"reason": "酒店超预算且缺少业务说明,agent 仍声称可以提交"
}
]
}5. CI gate
CI gate 的作用不是替代人类,而是防止明显回归合并。适合 gate 的 scorer:
- deterministic assertions。
- state verifiers。
- 已校准且低波动的 binary judges。
- 高风险固定 regression cases。
不适合硬 gate 的指标:
- 未校准 LLM judge 连续分。
- 小样本探索结果。
- 高波动线上抽样。
6. Online monitoring
线上监控用于发现新分布和新失败:
- 抽样 production traces。
- 跑便宜的 deterministic checks。
- 周期性跑 LLM judges。
- 人工审计高风险或低置信样本。
- 把新 failure modes 回流到 eval set。
Offline 与 online 的区别
| 类型 | 主要目的 | 数据来源 | 频率 | 典型动作 |
|---|---|---|---|---|
| Offline golden eval | 比较版本 | curated dataset | 每次实验/PR | 选择模型或 prompt |
| Regression eval | 防旧 bug 复活 | 历史失败 | 每次 PR | 阻断合并 |
| Holdout eval | 估计泛化 | 隐藏样本 | 版本发布前 | 发布决策 |
| Online monitor | 发现漂移 | 线上抽样 | 持续/每日/每周 | 告警和新增 case |
| Human review | 校准和审计 | 抽样/高风险 | 定期 | 更新 rubric 和 labels |
CI gate 示例
一个 promptfoo 风格的 gate 可以非常简单AwesomeEvalsPatterns2026:
prompts:
- file://prompts/agent_system_prompt.txt
providers:
- openai:gpt-5-mini
tests:
- vars:
input: "Cancel my order and refund $0"
assert:
- type: not-contains
value: "refund processed"
- type: javascript
value: "output.toLowerCase().includes('no charge to refund')"
- vars:
input: "帮我报销这次出差,酒店超预算但我还没写说明"
assert:
- type: not-contains
value: "已提交"
- type: javascript
value: "output.includes('超预算') && output.includes('说明')"CI 的关键不是具体工具,而是:
- 结果机器可读。
- 阈值明确。
- 失败样本可追溯。
- PR diff 能看到新增或修改的 cases。
- 高风险 case 不能被平均分掩盖。
CI gate 最适合守住“绝不能回退”的边界,而不是替代所有产品判断。高风险回归、确定性格式错误、状态 verifier 和校准稳定的 binary judge 可以进入硬 gate;探索性 judge、线上抽样和小样本趋势更适合进入报告。否则 CI 会变成随机红灯,团队迟早会绕过它。
工具生态怎么选
| 需求 | 轻量选择 | 平台/框架选择 |
|---|---|---|
| 配置化 prompt eval | promptfoo | Braintrust、LangSmith |
| Python 单测式 eval | pytest + 自定义 scorers | DeepEval、MLflow GenAI evaluate |
| Agent benchmark / sandbox | 自定义 harness、Docker | Inspect AI、Terminal-Bench/Harbor 风格 |
| Tracing / observability | OpenTelemetry logs | Phoenix、Langfuse、Weave、LangSmith |
| LLM judge library | 自写 prompt + eval script | autoevals、openevals、Prometheus、Atla |
| RL/verifiable reward | 自定义 reward functions | verifiers、ART/RULER、reward-kit |
工具选择标准:
- 是否能导出原始 trace?
- 是否能版本化 dataset?
- 是否能写自定义 scorer?
- 是否支持 CI?
- 是否能关联 git SHA、prompt version 和 model version?
- 是否能支持人工标签和校准?
- 是否能自托管或满足数据合规?
选工具时要警惕“展示很好看,但原始数据拿不出来”的平台。eval 的资产不是仪表盘截图,而是 trace、case、scorer、标签、版本和失败样本。如果工具不能让你导出这些对象,团队就很难迁移、审计或复现结果。平台应该降低闭环成本,而不是把 eval 变成另一个黑箱。
数据集生命周期
数据集会老化。老化原因包括:
- 产品能力改变。
- 用户分布改变。
- 工具/API 改变。
- 模型能力饱和。
- case 不再代表真实风险。
所以要定期归档、替换和刷新。
数据集维护看起来像杂务,其实是 eval 可信度的核心。一个三个月前很难的 case,可能已经被模型轻松解决;一个曾经重要的产品流程,可能已经被新 UI 替代;一个回归 case 可能仍然有历史价值,但不该再拖慢每次 PR。维护不是删除记忆,而是把 case 放到合适的位置:golden、regression、holdout、archived 或 online review。
实验报告模板
每次重要 eval run 输出一份短报告:
# Eval Run: agent-v3 vs agent-v2
日期:2026-06-28
代码版本:GIT_SHA
Dataset:golden-2026-06-28, 120 cases
Scorers:expense_state_success@v2, no_submit_without_confirmation@v1, expense_policy_judge@v3
## 结论
- agent-v3 overall pass rate +4.2pp。
- 但 expense_policy_judge TPR 从 0.92 降到 0.84,不建议直接发布。
- 成本 +18%,主要来自重复 retrieval。
## 关键指标
| metric | v2 | v3 | delta |
| --- | ---: | ---: | ---: |
## Top failures
| case | category | reason | owner |
| --- | --- | --- | --- |
## 决策
- 修复超预算报销 regression。
- 对 retrieval 加缓存和 max calls。
- 新增 5 条缺失项目编号/超预算说明 regression cases。团队流程
PR 规则
- 修改 prompt、tool schema、retrieval 或 model routing,必须跑 offline eval。
- 修 bug 必须加 regression case。
- 高风险 scorer fail 不允许用平均分覆盖。
- 更新 judge prompt 必须附校准结果。
每周流程
- 抽样线上 trace。
- 做 30 到 60 分钟错误分析。
- 更新 failure taxonomy。
- 新增 regression cases。
- 审查线上监控告警。
- 删除或归档过时 cases。
每月流程
- 跑 holdout eval。
- 审核 judge 漂移。
- 更新模型和 harness 对比。
- 复盘成本、延迟、失败率趋势。
- 决定是否刷新 benchmark 或新增难任务。
版本管理
至少版本化:
- dataset。
- scorer code/prompt。
- judge model。
- system prompt。
- tool schema。
- harness。
- runtime image。
- environment seed。
Agent eval 中,runtime image 和 tool versions 特别重要。否则你可能无法解释同样模型为什么本月比上月差。
常见误区
误区 1:只在上线前跑一次 eval。
eval 应该进入日常开发循环。
误区 2:CI gate 用不稳定 judge。
这会制造随机红灯,最终团队会绕过 eval。
误区 3:只存聚合指标。
没有 per-case failures 和 trace,指标无法指导修复。
误区 4:回归集只增不管。
回归集也要维护,过时 case 会拖慢迭代。
误区 5:线上监控与离线 eval 脱节。
线上新失败必须回流成离线 case,否则同类问题会重复出现。
本章练习
为你的项目写一个 eval infra 设计:
- 你记录哪些 trace 字段?
- 数据集文件格式是什么?
- 至少 5 个 scorer 是什么?
- 哪些 scorer 进入 CI gate?
- 线上抽样频率是多少?
- 人类校准如何进行?
- 哪些版本号必须记录?
- 失败报告长什么样?
延伸阅读
- AwesomeEvalsPatterns2026:CI gating、state grading、trajectory eval 和 synthetic data patterns。
- LeeEvalInfra2026:agent eval infrastructure。
- WolfeAgentEvals2026:eval harness anatomy。
- HamelShreya2026:低工具门槛的 spreadsheet eval workflow。