# 没有评测,你就是凭感觉调参

评测 AI 系统的速成课。24 个概念——eval、golden set、eval criteria、faithfulness 与 correctness、LLM-as-judge、trajectory evaluation、离线与在线评测、drift、CI gate、古德哈特定律等——每个都配有英文名、一张图、一个例子和一张卡片。结尾附一页速查表,收齐所有概念。要点:你无法改进你不去度量的东西,而做到 95% 才是大部分的活儿。

- **Author:** Fedor Chishchin
- **Level:** intermediate
- **Reading time:** ~35 分钟阅读
- **Published:** 2026-06-13
- **Source:** https://fedorthinks.com/zh/learn/evals-express

---

## 1. 评测为何存在

普通代码可以做单元测试,因为同样的输入给出同样的输出。LLM 打破了这一点,所以你需要另一种测试——没有它,你就是在盲飞。

### 地图:七组共 24 个概念

> 一张地铁线路图:先看清整条线路,再一站一站地坐过去。

先是三个**基础**——评测是什么、为什么凭感觉调参行不通、为什么最后那 15% 的质量是大部分的活儿。然后是六组,每章一组:**该测什么**、**评测集**、**如何打分**、**agent**、**离线与在线**,以及**把它做好**。

后面的每个概念都是同一个样子:它的**英文名**(记住它——这就是术语)、一幅现实生活里的画面、一张**图**,以及一张带字段的**卡片**:_问题_、_思路_、_例子_、_代价_、*何时使用*和*关联*。

_Diagram: 上面是基础;下面是六组——第 2–7 章按它们展开。_

### Eval——给「猜测者」的测试

> 给一篇作文评分,不像核对一道加法题——没有唯一正确的字符串可以去对照,而且同一个提示词每次产出的作文都略有不同。

普通测试断言的是 `output === expected`。LLM 是**非确定性**且开放式的:同一个提示词给出变化的文本,而「正确」往往是一种质量,不是某个精确的字符串。所以断言这套模型就失效了。**评测(eval)**取而代之:一组输入,每个都配有一种方法去*评分*输出有多好,反复运行——为一个「不会两次返回同样东西」的组件而生的测试。

_Diagram: 普通代码:一个输入,一个输出,断言。LLM:一个输入,不同的回答——所以你要给它们打分,而不是去匹配某个字符串。_

#### Eval (AI 系统评测)

- **问题:** LLM 是非确定性的:`output === expected` 会失败,而「正确」是一种质量。
- **思路:** 一组输入 + 给每个输出打分的方法 + 每次改动都跑一遍。
- **例子:** 给客服机器人准备一百个问题,每个都有好答案的标志;结果:「84% 通过」。
- **代价:** 收集用例、搭建打分方法要花时间。
- **何时使用:** 任何链条里有 LLM 的功能。
- **关联:** 建立在 **golden set** 之上,由 **grader** 打分,在 **CI gate** 里运行。

### Tuning by Vibes——凭感觉调参的陷阱

> 一个从不尝菜、只是反复改配方然后碰运气的厨师——他根本分不清昨晚的改动是帮了忙,还是悄悄毁了这道菜。

没有评测,你就**凭感觉**调提示词:试点什么,瞄一眼几条输出,觉得更好了就发布。陷阱在于你看不见**回退**——一个修好了某个用例的改动,常常会弄坏你没回头去查的另外三个。评测把「感觉更好了」变成「打了 84 分对 79 分」,这就是工程与猜测之间的区别。

_Diagram: 新提示词修好了你看过的那个用例,却悄悄弄坏了另外三个。靠眼睛瞄是看不出来的。_

#### Tuning by Vibes (凭感觉调参)

- **是什么:** 改提示词,瞄几条输出,觉得「更好了」就发布。
- **为何糟糕:** 回退是看不见的:修好一个用例,弄坏三个。
- **例子:** 用「看着好点了」代替「84% 对 79%」。
- **解药:** 哪怕是很小的 **eval**,在改动前后各跑一遍。
- **关联:** **Eval-driven Development** 的反面。

### The Last Mile——80% 很快,95% 才是整个项目

> 任何东西的初稿都出得很快。把一份粗糙的草稿变成可靠的东西,时间才真正花在这里。

评测要处理的就是这条残酷的事实:一个**80% 情况下正确的 demo 一个下午就能做出来;从那里一路磨到 95%,才是大部分的活儿。**最后这一段,即**最后一英里(last mile)**,要一个用例一个用例地找——边缘输入、罕见失败——而且只有你在度量时,才能找到并修好它们。评测就是让这段漫长攀登变得可见的仪器。

_Diagram: 到 80% 是一个下午的快速攀升。从 80% 到 95% 是漫长的活儿,一个用例一个用例地来。_

#### The Last Mile (80% → 95%)

- **是什么:** 前 80% 的质量来得很快;剩下的 15% 是大部分的活儿。
- **为什么:** 剩下的是边缘输入和罕见失败,只能一个一个地找。
- **例子:** 一个下午的 demo 能跑;在它之上做出产品要几周。
- **后果:** 没有度量,这段攀登是看不见、也管不住的。
- **关联:** 靠 **eval**、**hard cases** 和 **slicing** 变得可见。

### 评测是你的回退防护网,也是你的规格说明

> 安全绳让攀岩者敢于尝试难度大的动作,因为失手不会致命——它让大胆的改动变得安全。

一旦有了评测,你就可以改提示词、换模型或重构流水线,并且**立刻看出是帮了忙还是添了乱。**它在用户之前抓住回退,还悄悄成为你这个功能「好是什么样」的真正**规格说明**。没有它,每次改动都是一场赌博;有了它,改进就成了一个你真能跑起来的循环。

_Diagram: 任何改动——提示词、模型、流水线——都过同一套评测,立刻显示是帮了忙还是添了乱。_

> **核心问题:** 「当我改这个提示词或模型时,我怎么知道——靠一个数字,而不是靠感觉——它变好了还是变差了?」

> 你没法给非确定性组件做单元测试。评测改为给它打分——而没有评测,每次改动都是猜。

## 2. 该测什么

「它好吗?」是没法度量的。评测的第一项真正工作,是把这个含糊的问题变成你能真正打分的具体事项——并且要与你这个功能的任务相匹配。

### Eval Criteria——把「好」变成具体的检查

> 驾照考试不会问「你是个好司机吗?」——它给具体的事项打分:打转向灯了吗、保持在车道里了吗、完全停稳了吗、停进线内了吗。

「质量」太含糊,没法优化。把它拆成**可度量的属性——评测标准(eval criteria)**:答案对不对、是否有来源依据、格式是否有效、是否调用了正确的工具、长度和语气是否合适?每一项都是你能打分的东西。关键功夫在于:挑出对*你的*任务真正重要的那几项,而不是什么都去测。

_Diagram: 含糊的「它好吗?」拆成具体的检查,每项各有自己的分数。_

#### Eval Criteria (可度量的属性)

- **问题:** 「它好吗?」既没法度量,也没法优化。
- **思路:** 把质量拆成属性:正确性、依据、格式、工具使用、长度和语气。
- **例子:** 「JSON 符合 schema」、「答案依赖检索到的文档」。
- **代价:** 你必须决定什么重要——并诚实地舍弃其余的。
- **关联:** 选标准就是 **task-specific metrics**;由 **grader** 去检查。

### Task-specific Metrics——让指标与任务相匹配

> 评价译者看忠实与流畅,评价收银员看速度与准确——量尺用错了,评价就没用。

不同的功能需要不同的**指标**。**RAG** 系统:检索到的片段对不对,答案是否忠实于它们?**分类器**:对照标签的准确率。**agent**:选对工具了吗,达成目标了吗?**摘要**:忠实、完整、简洁。挑那些对应你的任务里「失败究竟意味着什么」的指标,否则你优化的就是一个不重要的数字。

_Diagram: 功能的类型决定指标:RAG、分类器、agent 和摘要各需要不同的量尺。_

#### Task-specific Metrics (与任务匹配的指标)

- **问题:** 一刀切的指标,测的并不是真正会坏的东西。
- **思路:** 指标反映「失败」对这个具体功能意味着什么。
- **例子:** RAG——片段是否正确与忠实度;分类器——准确率;agent——工具与目标。
- **代价:** 你得针对每个功能把指标想清楚。
- **关联:** 让 **eval criteria** 落到实处;agent 再加上 **trajectory**。

### Faithfulness vs Correctness——两件不同的事

> 学生可以写出论证漂亮但错误的答案,也可以写出笨拙但正确的答案。文采和真相是分开的两项分数。

最重要的两个属性常被混为一谈。**正确性(correctness)**是答案究竟对不对;**忠实性(faithfulness)**是它是否有所给上下文的支持、没有凭空编造。一个有依据的系统可以是忠实的(用了来源)却是错的(来源本身就错了),也可以是正确的却不忠实(蒙对了,而不是出自上下文)。把二者分开度量,才能告诉你失败出在*哪里*。

_Diagram: 两条轴给出四种结果。每种指向不同的修复位置:检索、依据,或两者都要。_

#### Faithfulness vs Correctness (有依据 vs 答得对)

- **是什么:** Correctness——答案是对的。Faithfulness——它出自所给的上下文,没有编造。
- **为何重要:** 不同的失败要在不同的地方修。
- **例子:** 忠实但错误——修数据或检索。答对了但不忠实——修依据。
- **坑:** 一个笼统的「质量」总分把两者混在一起,掩盖了原因。
- **关联:** **RAG** 的关键指标对;常由 **LLM-as-judge** 打分。

### Slicing——一个数字隐藏得太多

> 「舒适」的平均气温,可能掩盖了一间冻人的屋子和一间闷热的屋子。汇总会抹掉你最需要看到的那些情况。

单一的总分是起点,不是全貌。把结果拆开——**切片(slicing)**——按**类别和难度**:简单与困难、每种问题类型、每种失败模式——因为一个平平的 85% 可能是简单用例 100%、关键用例 40%。评测的价值在于这种拆解,它告诉你下一步该瞄准哪里。

_Diagram: 总体 85% 看着不错,一切片就变了:简单用例 100%,关键用例 40%。_

#### Slicing (按分段拆解)

- **问题:** 平均值抹掉了系统真正出错的那些用例。
- **思路:** 按类别、难度和失败模式分别打分。
- **例子:** 总体 85% = 简单 100% + 困难 40%。
- **代价:** 集合里的用例需要带类别标签。
- **关联:** 指出 **last mile** 该往哪走;依赖带标签的 **golden set**。

> **度量问题:** 「在这里,哪些具体、可打分的属性定义了一个好输出——它们真的对应失败给我的用户带来的代价吗?」

> 「它好吗?」不是指标。把质量拆成为你的任务挑选的具体、可打分的属性——并且永远不要相信单一的汇总数字。

## 3. 构建评测集

评测的诚实程度,取决于里面的样例。数据集——输入及其已知为好的结果——才是真正的资产,大部分用心都花在这里。

### Golden Set——带有已知为好结果的输入

> 老师的标准答案——题目与「正确回答是什么样」配成对,这样评分才一致,而不是看心情。

评测的核心是 **golden set**:一批有代表性的输入,每个都配有已知为好的答案,或对成功的清晰定义。你就是对着它打分。建它是实打实的活儿——正是在这里你才确定「正确」对你的功能究竟意味着什么——它也是让今后每次改动都可度量的资产。

_Diagram: golden set 就是一张表:一个真实输入和它已知为好的结果。每次改动都对着它打分。_

#### Golden Set (评测数据集)

- **问题:** 没有参照,输出就按心情评分。
- **思路:** 有代表性的输入,每个配一个好答案或清晰的成功标准。
- **例子:** 「取消我的订阅」→ 必须调用 `cancel_subscription`;「asdf??」→ 一个澄清问题。
- **代价:** 实打实的活儿:为每个用例决定「正确」是什么。
- **关联:** 由 **hard cases** 和 **production sampling** 充实;由**离线评测**运行。

### Hard Cases——覆盖边缘和已知的失败

> 桥梁要用最重的卡车和最糟的风暴来做压力测试,而不只是晴天里的一辆普通轿车。

只有简单、典型输入的集合,会给你一个好看却没用的分数。要刻意放进**困难用例(hard cases)**:含糊的问题、**边缘用例**、**对抗性提示词**,尤其是你已经见过的那些失败。每当有 bug 进了生产环境,就把它作为**回归用例(regression case)**加进评测,让它永远不能悄悄回来。集合应当集中在系统最可能出问题的地方。

_Diagram: 好看的集合只有典型输入。诚实的集合还加上含糊的、边缘的、对抗性的和过去 bug 的用例。_

#### Hard Cases (边缘用例、对抗用例、回归用例)

- **问题:** 一堆简单用例给出的是好看却没用的分数。
- **思路:** 刻意加入含糊的、边缘的、对抗性的,以及所有已经坏过的。
- **例子:** 一个 bug 进了生产环境 → 它的输入成为集合里的永久用例。
- **代价:** 分数会掉——但变得诚实了。
- **关联:** **golden set** 的一部分;来源是 **production sampling**。

### Production Sampling——采集真实样例

> 最好的考题来自学生真正考过的那场考试,而不是老师想象他们会问什么。

评测用例最丰富的来源是**真实使用**:用户实际问了什么,尤其是问了却出了错的。从日志和反馈里挖出真实输入,并入集合。凭空编的样例反映的是你*以为*会发生什么;生产里的样例反映的是*真正*发生了什么,包括你绝对想不到的那些凌乱措辞和古怪请求。

_Diagram: 用户 → 日志与反馈 → 挑选用例,尤其是失败 → golden set。_

#### Production Sampling (来自真实使用的用例)

- **问题:** 编出来的样例反映的是你的想法,而不是现实。
- **思路:** 从日志和反馈里取输入,尤其是出过问题的地方。
- **例子:** 用户那种你永远想不出来的凌乱措辞。
- **代价:** 你需要有日志,而且用户数据必须先清除个人信息。
- **关联:** 喂给 **golden set**;信号来自 **user feedback**。

### 小而锋利,胜过大而陈旧

> 五十个精心挑选、直戳真实弱点的问题,比一千个你从不细看的随机问题教给你的更多。

起步不需要成千上万个用例——几十个**精心挑选**的,覆盖主要行为和已知的失败模式,就足以抓住大部分回退并指导调参。从小处开始,保持诚实,随着你了解系统在哪里出问题再让它长大。一个你真会去跑的评测,胜过一个庞大却不去跑的。

> **数据集问题:** 「我的评测集里有没有那些困难的、怪异的、以前坏过的用例——还是只有那些抬高分数的简单用例?」

> golden set 就是资产。把真实输入与已知为好的结果配对,集中在困难的和坏过的上面,并随着你的了解让它长大。

## 4. 如何打分

有了输入和预期之后,你需要一种给每个输出打分的方法。这些方法从廉价精确到灵活易错一字排开——你要选能满足需要的最便宜的那个。

### Code-based Graders——精确的、基于规则的检查

> 批改选择题不需要判断力——答案要么对要么错,机器瞬间就能打分。

当输出受到约束时,用代码做**确定性**的打分——**基于代码的 grader(code-based grader)**:分类用精确匹配,格式用正则或 schema 检查,agent 看是否调用了正确的工具,抽取看数字是否正确。这些检查便宜、快速、无可争辩。要尽可能多地把你的评测放进这一类——它是最可靠的打分方式。

_Diagram: grader 阶梯:左边廉价而精确,右边灵活、昂贵而易错。选能满足需要的最低一级。_

#### Code-based Grader (确定性检查、精确匹配)

- **问题:** 明明可以直接比对,却用了昂贵且有争议的判断。
- **思路:** 用代码检查输出:匹配、正则、schema、正确的调用。
- **例子:** 类别标签匹配;JSON 通过 schema;agent 调用了正确的工具。
- **代价:** 只适用于受约束的输出——你没法这样给一篇作文打分。
- **关联:** 阶梯的第一级;模糊的输出用 **LLM-as-judge**;agent 用**步骤级检查(step-level checks)**。

### LLM-as-Judge——让模型给模糊的东西打分

> 一篇作文请来第二位考官,拿着清晰的评分细则——是判断,但有明确标准做引导,所以是一致的。

对开放式输出——这个摘要忠实吗?这个回答有用吗?——没有精确匹配可用,所以你用一个模型来打分,即 **LLM-as-judge**:把输出、上下文和一份清晰的**评分细则(rubric)**交给第二个模型,让它打分。它能把接近人的判断扩展到成千上万个用例。对于你没法用规则检查的质量,它是标准工具——但也有需要注意的地方。

_Diagram: judge 拿到输出、上下文和评分细则——返回一个分数和一句简短的理由。_

#### LLM-as-Judge (用模型当评分员)

- **问题:** 开放式输出没法做字符串匹配,而人力没法扩展到成千上万个。
- **思路:** 第二个模型对照上下文和明确的评分细则给输出打分。
- **例子:** 「摘要忠实于来源吗?打 1–5 分,并用一句话解释。」
- **代价:** judge 自己也会出错、也有偏见——必须检验它。
- **关联:** 没有 **judge validation** 就不可信;常用来度量 **faithfulness**。

### Judge Validation——judge 也得被评判

> 第二位裁判也可能有偏见——偏爱更长的答案,或听起来更自信的那个——所以你在信任他之前,先拿几个人工判定来检验这位裁判。

LLM judge 有它的失败模式:它可能偏好冗长的答案(**verbosity bias**),被自信的语气左右,或偏离你的本意。所以要在一个样本上**对照人工打分来验证 judge**,给它一份带例子的锐利细则,并保持简单。一个你没检验过的 judge,不过是又一个没被度量的模型——在确认它的分数确实跟着你真正在乎的东西走之前,别信它。

_Diagram: 人和 judge 给同一个样本打分。若一致,judge 就可信。留意它常见的偏见。_

#### Judge Validation (用人工检验 judge)

- **问题:** judge 喜欢又长又自信的答案,还可能偏离你的本意。
- **思路:** 在信任它之前,先在样本上把 judge 的分数和人工分数做比较。
- **例子:** 几十个用例由人来打分;judge 与之一致——所以可以信任它。
- **代价:** 要做一些人工标注,而且每当 judge 或细则变了,就得重新检验。
- **关联:** **LLM-as-judge** 的必备搭档;用到**人工复核(human review)**。

### Human Review——人在回路,小剂量

> 即便有自动打分,厨师依然要尝尝菜——快速抽查一下仪器有没有悄悄出错。

自动打分能规模化,但要定期**亲自去读真实的输出——人工复核(human review)。**抽查一个样本,重点看那些失败,并核对你的指标是否仍然反映真实的质量。人工复核没法覆盖每个用例,但小而定期的一剂,能抓住你的自动分数漏掉的东西——并避免你去优化一个已经偏离现实的数字。

#### Human Review (人工抽查)

- **问题:** 自动分数可能悄悄偏离真实质量。
- **思路:** 定期读一个真实输出的样本,尤其是失败的那些。
- **例子:** 每周一次,读那些分数掉了的用例,看看你是否同意。
- **代价:** 人的时间——所以小剂量,不是每个用例都做。
- **关联:** grader 阶梯的最后一级;**judge validation** 的基础。

> **打分问题:** 「每项检查,对它所度量的东西来说,是不是最便宜的可靠方法——而如果由模型当 judge,我有没有拿人工判定验证过这个 judge?」

> 能确定性打分的地方就确定性打分,其余模糊的交给 LLM judge——并且要验证 judge,因为一个没检验过的评分员不过是又一个猜测。

## 5. 面向 agent 的步骤级评测

agent 需要的不只是对最终答案的一个分数,因为它们可能经由一个有问题的过程,得出一个干净的答案。要信任一个 agent,你得度量旅程,而不只是终点。

### 干净的最终答案,可能藏着一个坏掉的中间

> 只按最终数字评分的数学考试,会让那个靠两个相互抵消的错误得到结果的学生过关——你对到底发生了什么一无所知。

在多步骤的 agent 里,**中间的错误可以通过最终输出的检查**,同时却污染了整个过程——它检索到了正确的来源,中途把一个事实张冠李戴,然后写出一份干净却是错的摘要。只给最终答案打分,你就把它放行了。你最需要抓住的那些失败,恰恰是只看终点的检查最看不见的。

_Diagram: 错误出在「Extract」那一步,但摘要读起来很顺——只看最终结果的检查会放它过去。_

### Trajectory Evaluation——给路径打分

> 驾考官会看整段驾驶——每次打灯、每次看后视镜、每次变道——而不只是看你有没有到达那个地址。

对 agent 你要评估它的**轨迹(trajectory)**:每一步,它是否选对了工具、传对了参数、检索到了正确的上下文、推理是否站得住?这能抓住只看最终结果漏掉的坏中间,还能告诉你是*哪一步*出了问题——比只知道结尾错了要有用得多。agent 的可靠性,正是在这些步骤里建成或丢掉的。

_Diagram: 检查每一步,就能看出究竟是哪里坏的。只看最终结果的检查只能看到最后一个框。_

#### Trajectory Evaluation (给 agent 的路径打分)

- **问题:** 正确的结尾可能藏着错误的步骤。
- **思路:** 给每一步打分:工具、参数、检索到的上下文、推理。
- **例子:** 第 1–2 步对;第 3 步 agent 取错了上下文——评测点出了第 3 步。
- **代价:** 你得记录并标注每一步,而不只是答案。
- **关联:** 由**步骤级检查(step-level checks)**构成;由 **operational metrics** 补充。

### Step-level Checks——直接检查工具调用和检索

> 审计一位研究助理,就是检查他实际调取了哪些来源、发出了哪些调用——而不只是读他最后的备忘录。

agent 的很多行为是具体的,不用判断就能打分:该调用 `send_email` 时它调用了吗,收件人对吗?它检索到相关文档了吗?它是否守在自己的工具权限之内?这些就是**对步骤的确定性检查——步骤级检查(step-level checks)**,廉价而精确,能精确定位很大一部分 agent 的失败。

#### Step-level Checks (工具调用检查)

- **是什么:** 对 agent 具体步骤的代码检查,不需要 judge。
- **怎么做:** 核对调用了哪个工具、用了哪些参数、检索到了哪份文档。
- **例子:** 调用了 `send_email`,收件人正确,没有超出任何权限。
- **好处:** 便宜、精确,并且直指出问题的那一步。
- **关联:** 应用在 **trajectory** 上的 **code-based graders**。

### Operational Metrics——也要度量那些乏味的真相

> 评价一家快递,不只看包裹到没到,还要看用了多久、试了几次、花了多少钱。

除了正确性,还要追踪 agent 的**运行指标(operational metrics)**:它走了多少步、多频繁地陷入循环或重试、**延迟(latency)**,以及每个任务的**成本**。一个循环用二十个昂贵的步骤得出正确答案,而三步就够了,这是一个可靠性与成本的问题,你的最终答案分数是显示不出来的。这些数字揭示出那些能跑、却撑不过生产环境的 agent。

_Diagram: 两次运行都得到了正确答案。但一次用了三步,另一次用了二十步,还带着循环和重试。_

#### Operational Metrics (步数、循环、延迟、成本)

- **问题:** 最终答案的分数看不到这个答案花了什么代价。
- **思路:** 统计每个任务的步数、循环和重试、延迟与成本。
- **例子:** 三步就够的地方,用 20 个昂贵的步骤得出正确答案。
- **代价:** 每次运行都需要做追踪。
- **关联:** 补充 **trajectory evaluation**;在生产中由**在线评测**盯着。

> **步骤级问题:** 「我检查的是这个 agent 是怎么得出答案的——工具、检索、步骤——还是只看最终输出看起来对不对?」

> agent 可能经由一个坏掉的过程,得出一个干净的答案。给轨迹打分——工具、检索、步骤——而不只是终点。

## 6. 离线与在线

评测有两种,各干不同的活儿:发布之前跑的测试套件,和在生产里持续运行的度量。两者你都需要,因为世界并不等于你的测试集。

### Offline Eval——发布之前的闸门

> 一条试车道,让一辆车在载上第一位乘客之前先经受考验——受控、可重复、在发布前运行。

**离线评测(offline eval)**就是在改动发布之前,拿你的 golden set 去跑:这个新提示词或新模型,在你精心挑选的那些用例上得分更高吗?它受控且可重复,是你抓回退、安全地比较各种方案的地方。这是你要接进开发循环的评测——最好做成 **CI 里的闸门**,这样任何让分数下降的东西都发布不出去。

_Diagram: 发布线的左边——离线:golden set、对照基线打分、闸门。右边——在线:真实流量、抽样、仪表盘。_

#### Offline Eval (发布前评测)

- **问题:** 你需要在用户看到之前,就知道一个改动是安全的。
- **思路:** 在新版本上跑 golden set,并与基线比较。
- **例子:** 新提示词:84%,旧的是 79%——可以安全发布。
- **代价:** 它只能看到集合里有的东西——世界要宽广得多。
- **关联:** 在 **golden set** 上运行;由 **CI gate** 自动化;与**在线评测**配对。

### Online Eval——度量真实世界

> 不管试车道多好,车上了真实的路,你仍然要监控——因为真实的路上有试车道从没有过的坑洼。

生产环境的表现,没有哪个离线集合能完全预测:真实用户的措辞你想象不到,输入分布也会漂移。所以你也要**在线**度量——**在线评测(online eval)**:对线上输出抽样并打分,盯着质量指标,收集用户信号。离线集合证明一个改动可以安全发布;在线度量则告诉你,它上线之后实际在发生什么。

_Diagram: 线上输出经过抽样和打分,汇成你盯着的质量指标。_

#### Online Eval (生产环境的质量监控)

- **问题:** 真实的用户和输入与测试集并不一致。
- **思路:** 对线上输出抽样、打分,并盯着指标。
- **例子:** 一部分生产环境的回答交给 judge;结果显示在仪表盘上。
- **代价:** 生产环境里的打分基础设施,以及 judge 在流量上的成本。
- **关联:** 抓住 **drift**;收集 **user feedback**;发现新的 **hard cases**。

### User Feedback——免费的评测信号

> 一个点赞按钮和一个投诉邮箱,就是一份持续、免费的调查,告诉你这东西对使用它的人是否真的管用。

不管你收不收集,你的用户都在给你打分。把**用户反馈信号(user feedback signals)**——**点赞/点踩、修改、重试、放弃、转人工**——抓起来并喂回去。重试或点踩的突增是早期预警;那些具体的失败,会成为明天的评测用例。这就闭合了循环:生产环境教会评测集现实是什么样,评测集又保护下一次发布。

_Diagram: 一个闭环:生产环境给出信号,失败变成用例,集合保护下一次发布。_

#### User Feedback Signals (隐式与显式反馈)

- **是什么:** 点赞/点踩、修改、重试、放弃、转人工。
- **为什么:** 来自真正在用的人的、免费而持续的评分。
- **例子:** 发布后重试的突增,是早期预警。
- **坑:** 信号是有噪声的:是个该去看看的理由,而不是现成的分数。
- **关联:** **在线评测**的一部分;转化为 **golden set** 里的 **hard cases**。

### Drift——盯住缓慢的衰退

> 一台秤慢慢偏离校准——没有什么戏剧性,只是每次读数都多错一点,直到某天数字就错了。

一个曾经得分很高的系统,会**悄无声息地退化**——这就是 **drift**:模型提供方更新了,你的数据变了,使用模式变了。没有持续的在线度量,你是从愤怒的用户而不是从仪表盘那里得知的。随时间追踪质量,让 drift 显现为一个你能采取行动的趋势,而不是一个意外。评测不是一次性的闸门;它是你要持续读取的生命体征。

_Diagram: 在提供方更新和使用方式变化之后,质量悄悄下滑。一个阈值能赶在投诉之前抓住它。_

#### Drift (质量漂移)

- **是什么:** 在你这边没有任何改动的情况下,质量缓慢、悄悄地下降。
- **成因:** 提供方的模型更新、数据变化、新的使用模式。
- **例子:** 每周差一点——直到投诉比仪表盘先到。
- **解药:** 随时间追踪质量,并设一个告警阈值。
- **关联:** 由**在线评测**抓住;新的失败进入 **golden set**。

> **在线问题:** 「一旦上线,如果它在真实世界里的质量下降了,我会怎么知道——是靠我盯着的某个指标,还是靠客户的投诉?」

> 离线评测把守发布;在线评测盯着现实。前者证明一个改动是安全的,后者告诉你实际在发生什么。

## 7. 把它做好

评测是一种实践,不是一次性的事。功夫在于:在你觉得准备好之前就开始,把度量接进循环,并且不让那个数字变成一个对你撒谎的目标。

### Eval-driven Development——先写评测,再调参

> 你得先校准温度计,再去调烤箱——否则每次调整都是披着进步外衣的猜测。

常见的错误是无休止地调提示词,到后来也许才去建评测。把它倒过来:**在优化之前先写一个小评测**,让每次改动从一开始就被度量——这就是 **eval-driven development**。哪怕十个用例也胜过零个。没有评测的调参感觉很有成效,其实多半没有——你在挪动你看不见的数字。

#### Eval-driven Development (先写评测,再调参)

- **问题:** 提示词被调了几周;评测是「以后再说,也许」。
- **思路:** 在第一次优化之前先有个小评测;每次改动都被度量。
- **例子:** 今天十个用例,每次改提示词前都跑一遍。
- **代价:** 起步花一小时,而那时一切还「不能用」。
- **关联:** **tuning by vibes** 的解药;会长成 **CI gate**。

### CI Gate——把评测做成 CI 里的闸门

> 测试不通过,代码就不能合并——同样的纪律,也能防止一个悄悄变差的提示词到达用户手里。

有了评测,就**在每次改动时自动运行它**,分数跌破门槛就拦住发布——这就是 **CI gate**。它把评测从「想起来才做的事」变成一道始终开着的护栏——AI 版的「测试套件全绿」。「没有评测就不发布」是值得坚持的标准:对 AI 功能做一个没被度量的改动,就是一次没测过的部署。

_Diagram: 每次改动都跑评测。分数达到或高于门槛——发布;下降了——被拦住。_

#### CI Gate (CI 里的评测闸门)

- **问题:** 「谁想起来才跑」的评测,抓不住一个悄悄变差的提示词。
- **思路:** 每次改动都跑;分数低于门槛就拦住发布。
- **例子:** 改了提示词的 PR,评测通过之前不能合并。
- **代价:** 每个 PR 都跑一遍集合要花时间和钱。
- **关联:** 让**离线评测**自动化;在生产之前抓住回退。

### Goodhart's Law——别让指标变成目标

> 只为考试而教,会教出考试拿高分却干不了活的学生——分数上去了,它所衡量的东西却没有。

当一个度量变成目标,它就不再是一个好的度量——这就是**古德哈特定律(Goodhart's law)。**你可能把提示词对你那些具体的评测用例**过拟合(overfit)**,眼看着分数上升而真实质量原地不动。要防范:留出一部分用例**不参与调参(held out)**,用新的生产失败刷新集合,并记住评测只是用户价值的一个*代理*,而不是价值本身。一个在涨、而用户却没有感觉的数字,是个警告,不是胜利。

_Diagram: 评测分数随每次迭代上升,真实价值却已停滞。这个差距就是对集合的过拟合。_

#### Goodhart's Law (度量变成目标)

- **是什么:** 当一个度量变成目标,它就不再是一个好的度量。
- **表现:** 提示词被拟合到评测用例上:分数上升,质量不涨。
- **例子:** 在集合上涨了 10 分,而用户感觉不到任何差别。
- **防范:** 留出不参与调参的用例、新鲜的生产失败、记住分数只是个代理。
- **关联:** 由 **production sampling** 和 **human review** 来制衡。

### 从小处开始,随失败而成长

> 好的测试套件不是一次写成的——它是积累出来的,一个 bug 一个用例,直到悄悄覆盖了所有出过错的地方。

别等一个完美、全面的评测——那样你永远发布不了。先为核心行为准备一把用例,然后**每次有东西坏了就加一个。**久而久之,集合恰好沿着你的系统真正出错的轮廓长大,而这正是你想要覆盖的地方。评测随产品一起成熟,它永远不算真正完成。

### 这些概念如何连在一起

> 一只不断转动的轮子:每转一圈,集合就更诚实,发布就更安全。

这门课里的一切都属于同一个循环。**criteria** 说明测什么;**golden set** 说明拿什么来测;**grader**(代码、judge、人)给出分数。带 **CI gate** 的**离线评测**把守发布,**在线评测**盯着现实——反馈和 drift——它发现的失败变成**新用例**,回到集合里。对 agent,你给**轨迹**打分,而 **Goodhart 定律**提醒你:分数只是个代理。

_Diagram: 评测循环:标准 → 集合 → grader → 闸门 → 在线 → 新用例 → 回到集合。_

#### 发布 AI 功能之前

- **到底有没有评测**——一组带有给输出打分方法的输入?
- **指标是否与任务匹配**,按难度和失败类型拆开,而不是一个平平的总分?
- **集合里是否包含**那些困难的、怪异的、以前坏过的用例,并且取自真实使用?
- **打分用的是不是最便宜的可靠方法**——能确定性的就确定性,不能的就用经过验证的 judge?
- **对 agent,是否给步骤打分了**,而不只是最终答案?
- **它是否在 CI 里运行**,上线之后你又怎么度量质量?

#### 说明你在盲飞的信号

- 靠**读几条输出**来调提示词,觉得更好了就发布。
- 只有**一个汇总分数**,没有按用例类型或难度的拆分。
- 评测集只有**简单、典型**的输入——没有边缘用例,没有过去的失败。
- 一个**从没拿人工打分验证过的 LLM judge**。
- **没有生产监控**——质量下降你只会从一封投诉里得知。

#### 说明你做好了的信号

- 一个由真实输入和已知为好的结果构成的 **golden set**,集中在困难用例上。
- **与任务匹配**的指标,用最便宜的可靠方法打分,并且做了拆分。
- 对 agent 做**步骤级打分**,对模糊的部分用**经过验证的 judge**。
- 评测是一个 **CI gate**,回退会新增一个用例,而不是溜过去。
- **在线度量和用户反馈**把新的失败喂回集合。

## 速查表:全部 24 个概念

### 基础

- **Eval** (评测): 输入 + 给输出打分的方法 + 每次改动都跑一遍。
- **Tuning by Vibes** (凭感觉调参): 瞄几条输出就发布。回退依然看不见。
- **The Last Mile** (80% → 95%): 80% 一个下午;95% 是大部分的活儿,一个用例一个用例地来。

### 该测什么

- **Eval Criteria** (可度量的属性): 把「好」拆成具体、可检查的属性。
- **Task-specific Metrics** (与任务匹配的指标): RAG、分类器、agent、摘要——各有各的量尺。
- **Faithfulness vs Correctness** (有依据 vs 答得对): 是出自上下文吗——又对不对?分开度量。
- **Slicing** (拆解): 按类别和难度打分:平均值会藏住失败。

### 评测集

- **Golden Set** (评测数据集): 真实输入加已知为好的结果。核心资产。
- **Hard Cases** (边缘、对抗、回归): 困难的、怪异的、已经坏过的——特意放进集合里。
- **Production Sampling** (来自生产的用例): 来自日志和反馈的输入,尤其是失败。

### 如何打分

- **Code-based Grader** (确定性检查): 匹配、正则、schema、正确的调用。便宜而精确。
- **LLM-as-Judge** (用模型当评分员): 第二个模型对照细则给模糊的东西打分。
- **Judge Validation** (检验 judge): 信任 judge 之前,先把它与人比一比。
- **Human Review** (人工抽查): 小而定期的一剂:读真实的输出。

### Agent

- **Trajectory Evaluation** (给路径打分): 给每一步打分,而不只是最终答案。
- **Step-level Checks** (工具调用检查): 对工具调用、参数和检索的代码检查。
- **Operational Metrics** (步数、延迟、成本): 一个任务花了多少步、循环、秒数和美元。

### 离线与在线

- **Offline Eval** (发布前): 在新版本上跑 golden set——发布前的闸门。
- **Online Eval** (在生产中): 对线上输出抽样、打分,盯着质量指标。
- **User Feedback Signals** (用户信号): 点赞、修改、重试、放弃——免费的评测信号。
- **Drift** (质量漂移): 质量随时间悄悄下降。只有监控能抓住它。

### 把它做好

- **Eval-driven Development** (先写评测): 在第一次优化之前先有个小评测。
- **CI Gate** (CI 里的评测): 每次改动都跑评测;分数下降——发布被拦住。
- **Goodhart's Law** (度量变成目标): 变成目标的度量就不再度量。分数只是个代理。

> 评测不是一次性的测试。它是那个循环——度量、找出失败、把它们叠回去——把一个非确定性组件变成你能信任并能改进的东西。

速成课结束 · 7 章 · 24 个概念

接下来是实践:今天就挑一个 AI 功能,给它写十个评测用例——真实的输入、已知为好的结果、给每个打分的方法——并在你下一次改提示词之前把它们跑一遍。然后每当有东西坏掉就加一个用例。但有一个念头要高于其余:那个跑一次就行的 demo,是容易的那 80%。一切让它成为一个你能信任的产品的东西——爬到 95%、抓住的那些回退、看见的那些漂移——只有在你度量时才有可能。没有评测,你就是凭感觉调参;有了它,改进就成了一个你能跑起来的循环。
