在传统软件里,测试写在代码后面;在大语言模型(LLM)应用里,顺序正在被倒过来——先写评测,再写应用。Braintrust 在 2026 年 2 月的博客 What is eval-driven development 里给这套做法起了正式名字:评测驱动开发(Eval-Driven Development,EDD)。它的核心主张只有一句话:先把"什么是好输出"写成可执行的评测集,再动手改提示词、换模型。
本站此前的《AI Agent 开发》系列用 30 篇解决"搭骨架",《上下文工程》系列用 18 篇解决"供血液",本系列是第三根支柱:EDD 负责"验健康",也是六大新系列里的第二个。作为系列第 1 篇,本文不重复 Agent 系列第 27 篇讲过的 LangSmith 工具入门,专注方法论本身:先讲 EDD 与 TDD 的血缘与分野,再展开 eval-as-oracle 模式、八步工作流闭环与评测四象限,最后给出后续 13 篇的路线图。
1、从 TDD 到 EDD
每个工程师都熟悉 TDD(Test-Driven Development,测试驱动开发)的红绿重构:先写一个失败的测试(红),用最小实现让它通过(绿),再在不弄灭绿灯的前提下重构。EDD 直接继承了这个骨架,只是每一环都换成了概率世界的对应物。
两者的映射关系如下:
| TDD | EDD | 含义 |
|---|---|---|
| 红:先写失败测试 | 先建评测集 | 定义"好"的标准 |
| 绿:最小实现通过 | 迭代提示词与模型 | 让指标过线 |
| 重构:保持绿灯 | 重构:指标不劣化 | 安全地改结构 |
| 测试套件防回归 | 回归门禁防劣化 | 概率版的"绿灯" |
真正的分野在确定性。TDD 的前提是被测函数是确定性的:同一个输入永远得到同一个输出,绿灯一旦亮起就不再熄灭。LLM 恰恰相反——temperature 大于 0、采样随机、底层模型还在被供应商悄悄更新,同一个问句问三遍可能得到三个答案。
TDD 的绿是一种状态,EDD 的绿是一个统计量。
所以 EDD 里没有 100% 绿:判定从布尔值变成分数与通过率,assertEqual 变成"相关性得分不低于 0.8";跑一次通过不算数,还要看多次运行的稳定性。接受了这一点,后面所有流程与工具的设计逻辑都会顺理成章。
2、LLM 应用的三重失控
为什么普通 Web 应用不需要 EDD,LLM 应用却离不开?因为在三个方向上,LLM 应用同时失去了传统软件的安全网。
第一重失控:提示词改动等于全系统改动。提示词就是源代码,却运行在一个没有编译器、没有类型系统、没有 lint 的环境里。改一个词,没有任何工具能告诉你影响了哪条路径;500 行的 system prompt 是全项目最大的隐式全局变量,牵一词而动全身。
第二重失控:模型升级是隐性行为变更。模型版本是锁不住的外部依赖:供应商静默更新、旧版本弃用、同名模型行为漂移,都是家常便饭。传统软件升级依赖,看 changelog 加测试套件就够;LLM 应用唯一能依靠的,是一套可随时全量重跑的评测集。
第三重失控:"感觉更好"是反科学的。改完提示词,随手试三条,变好了,上线——样本量为一,没有对照组,还叠加确认偏误。Hamel Husain 在广被引用的评估入门长文里反复强调:没有评测的迭代等于蒙眼开枪。更麻烦的是,LLM 应用的失败多是软失败:不抛异常、不返回 500,而是输出一段"看起来对"的错误答案,错误率与延迟监控全绿,质量却在劣化。
三重失控的共同解法,是把"感觉"换成"测量"。这正是 EDD 的全部动机。
3、评测即规格
3.1、先写应用再补评测
多数团队的真实路径长这样:想法 → 提示词 → demo 一鸣惊人 → 上线 → 用户抱怨 → 想复现问题,却发现没有评测集,无法判断"到底改好没有" → 临时拼 20 条测试 → 修好 A 场景,悄悄弄坏 B 场景。
补出来的评测集只覆盖已经翻车的案例,本质是一份亡羊补牢清单:它只能防住已知的坏,定义不了什么是好。
3.2、先写评测再写应用
Braintrust 给出的模式叫 eval-as-oracle:评测集就是你的规格说明书。oracle 借自软件测试理论,test oracle 指判定"输出对不对"的机制;传统软件的 oracle 是一行断言,而 LLM 应用没有唯一正确输出,oracle 便升级为"一个评测集加一组评估器",成为应用的工作规格(working specification)。
DeepEval 在 2026 年 10 月的实践博客里把 EDD 落成三步:准备数据集、定义指标、迭代与回归。学术侧也有呼应:CSIRO Data61 团队的EDDOps 论文(arXiv 2411.13768)给出了把评测嵌入设计、开发、运维全生命周期的过程模型与参考架构。
一条最小评测长这样,基于 DeepEval:
from deepeval import assert_test
from deepeval.metrics import AnswerRelevancyMetric
from deepeval.test_case import LLMTestCase
def test_refund_flow():
metric = AnswerRelevancyMetric(threshold=0.8) # 过线分数,而非布尔断言
case = LLMTestCase(
input="退货流程是什么?",
actual_output=bot.answer("退货流程是什么?"), # 被测系统
expected_output="给出 7 天无理由退货的操作步骤",
)
assert_test(case, [metric])
这段代码没有一行应用逻辑,却已经完整定义了"好":输入是什么、期望覆盖什么、几分算过线。assert_test 的角色与 pytest 的普通断言相同,只是断言对象从"相等"换成了"分数过线"。真实项目里,你会把几十条这样的用例组织成 golden set,覆盖常见、边界与对抗场景。
运行方式与普通测试无异:
deepeval test run tests/evals/ --minimum-pass-rate 0.75
输出不再是绿点,而是带分数的报告:
Test: test_order_status
answer relevancy | score 0.92 | threshold 0.8 | PASS
Test: test_refund_flow
answer relevancy | score 0.61 | threshold 0.8 | FAIL
Overall pass rate: 50.0% (minimum 75.0%) -> exit 1
两个细节值得注意:判定单位是分数而非布尔值;通过率低于下限时命令以非零退出码结束,这正是 CI(持续集成)回归门禁的雏形。一句话对比两种姿势:先评测后应用,评测集是设计工具,逼你在写第一行提示词前回答"好输出长什么样";先应用后评测,评测集只是道歉工具。
4、EDD 工作流全景
把 EDD 摊开,是一条八步闭环,全貌如下:
八个步骤各有要点:
- 1 定义任务:一句话任务定义,加好输出的验收标准
- 2 建评测集:golden set 起步 30~100 条,覆盖边界场景
- 3 实现:提示词、检索、工具编排
- 4 评测:看分数分布,不只看均值
- 5 分析失败:聚类失败样本,找模式而非逐条 hack
- 6 迭代:针对失败类别改提示词、加示例、换检索
- 7 回归门禁:CI 全量重跑,设通过率下限
- 8 线上监控:漂移检测,坏例回流评测集
第 7 步落到工程上,就是一段 CI 配置:
name: evals
on: [pull_request]
jobs:
regression:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install deepeval
- name: run regression evals
run: deepeval test run tests/evals/ --minimum-pass-rate 0.9
从此,任何提示词改动、模型升级、依赖更新都必须先过这道回归门禁才能合并。再看一眼图里第 8 步的回流箭头:评测集是活文档,线上新出现的坏例不断补进去,评测集随产品一起生长——这是 EDD 与"一次性测试"最本质的区别。
5、评测体系的四象限
评测不是单一活动。按时机场(离线/在线)与判定方式(自动/人工)切两刀,得到四象限:
| 自动判定 | 人工判定 | |
|---|---|---|
| 离线 | 组件级评测、端到端评测 | 人工标注、团队评审会 |
| 在线 | A/B 实验、指标与漂移监控 | 点赞点踩、投诉、抽检 |
离线自动是主力,也是 CI 门禁的唯一对象。它分两层:组件级类似单元测试,单独测检索命中率、工具选择准确率;端到端类似集成测试,评判整条回答乃至完整轨迹的质量。
离线人工最贵,却是全体系的地基:人工标注的 golden set 是 judge 校准的燃料,没有它,自动评估器的分数无从取信。在线自动看真实业务指标与漂移;在线人工是最真实的信号,也是最慢的信号。
四象限不是孤岛,而是互相喂养:线上点踩回流进离线评测集,经过人工标注校准的 judge 反过来承担线上抽检。成熟的团队四个象限都有布点,起步团队优先把左上角做扎实。
6、与上下文工程的衔接
把三个系列放回一张图:《AI Agent 开发》搭骨架,让系统会规划、会调工具;《上下文工程》供血液,让每一步喂给模型的信息又准又省;《评测驱动开发》验健康,量出这套系统到底行不行。
上下文工程系列第 15 篇已经把"上下文质量"从直觉变成可评测的对象。本系列是那个思路的放大:上下文质量只是众多被测维度之一,EDD 提供"定义、测量、迭代、回归"的外循环,上下文工程优化的是循环里的被测对象。反过来,评测本身也是上下文工程——judge 的提示词怎么写、评测集怎么构造,本质仍是"喂给模型什么"的问题。两个系列互为表里。
7、系列路线图
本系列规划 14 篇,本篇之后按"数据、度量、过程、门禁、线上、安全"推进:
| 板块 | 篇数 | 覆盖内容 |
|---|---|---|
| 评测数据集 | 2 | golden set 构造、真实流量采样 |
| 评估器 | 2 | 规则校验、语义相似度、指标设计 |
| LLM-as-a-Judge | 2 | judge 提示词、偏差治理、与人工对齐 |
| 轨迹评测 | 2 | 多步任务、工具调用、过程质量 |
| CI 与门禁 | 2 | 回归流水线、失败聚类分析 |
| 线上评测 | 2 | 漂移检测、A/B 实验、反馈回流 |
| 红队与安全 | 1 | 对抗样本、提示注入与越狱 |
工具层面会横跨 DeepEval、LangSmith 文档 与 Braintrust。LangSmith 的界面操作 Agent 系列第 27 篇已经讲过,本系列不再重复工具教程,专注方法论与选型判断。
8、总结
EDD 的全部内容可以压成四句话:评测当规格,先定义好输出再写应用;迭代当开发,分数不过线就不合并;回归当门禁,每次改动全量重跑;监控当哨兵,线上坏例回流评测集。并且永远记住:概率世界里没有 100% 绿,只有"分数不劣化"。
行动建议有三条。对于已在维护 LLM 应用的团队,建议本周就从线上日志挑 30 条真实请求,人工标注好坏,跑出第一个基线分数——它会立刻告诉你当前版本的真实水平,通常并不乐观。对于正要立项的团队,建议把"建评测集"写进里程碑,并排在"写提示词"之前。对于个人开发者,建议现在就装上 DeepEval,把本文的 test_refund_flow 抄进项目跑通——体验一次分数化的绿,你就回不去了。

