AIPA 长文#1:从 recall@k 到生产级 evals
2025 下半年开始,"会写 evals"从一个隐性的工程加分项,变成了 AI 产品岗位的显式职责。OpenAI 的 CPO 在一次公开访谈里直接说,"PM 最重要的技能是写 evals"(2025-08);Hamel Husain 与 Shreya Shankar 的《AI Evals For Engineers & PMs》在 Maven 上累计训练了 2000+ 工程师与 PM,他们把这套方
从 recall@k 到生产级 evals:一个 RAG/AML agent 的评测体系演进
日期:2026-07-11 AIPA-120 长文#1 · 方法论 · 本文是一篇"从原型 tripwire 到生产质量门"的工程演进记录,配套代码均在本仓库
src/agent/eval/与src/aml/可运行。
1. 引言:evals 是 AI 产品经理/架构师的第一硬技能
2025 下半年开始,"会写 evals"从一个隐性的工程加分项,变成了 AI 产品岗位的显式职责。OpenAI 的 CPO 在一次公开访谈里直接说,"PM 最重要的技能是写 evals"(2025-08);Hamel Husain 与 Shreya Shankar 的《AI Evals For Engineers & PMs》在 Maven 上累计训练了 2000+ 工程师与 PM,他们把这套方法论系统化成"人工错误分析 → 开放编码 → 轴向编码 → LLM-as-judge → 代码型检查"的流水线(Lenny's Newsletter,2025-09)。到 2026-01-15,两人把课程沉淀成一篇长 FAQ《LLM Evals: Everything You Need to Know》,明确把"错误分析"称为 evals 里最重要的活动——大多数团队的错误恰恰是跳过它,直接去写 judge 或搭 dashboard(hamel.dev,2026-01)。
为什么这件事对 PM/架构师而非只对模型工程师重要?因为在 LLM 产品里,"需求是否被满足"不再能靠功能勾选清单判断,而要靠一组可量化、可回归的评测来界定。Aman Khan 把这句话浓缩成"Evals are the new PRDs"(2025-06 首发,2026-04 更新版):PRD 描述"应该是什么样",eval 把它变成"可被自动判定的样"。Anthropic、LangChain 等公司的 Solutions Architect / Forward-Deployed 岗位 JD 已经把"为客户设计并维护 eval 套件"写进显式职责。换句话说,evals 是把模糊的产品意图翻译成工程可执行契约的那层胶水,谁掌握它,谁就握住了 AI 产品质量的方向盘。
本文不写空泛方法论。它以本仓库两个真实可运行的子系统为标本——一个是 RAG 检索评测(src/agent/eval/),一个是 AML 反洗钱 Copilot 的规则基线评测(src/aml/)——讲清楚一条评测体系从原型到生产级应该怎么演进,以及每一步诚实的局限在哪里。
2. recall@k 原型的局限:一个诚实的起点
本仓库最早的检索评测就一个文件 src/agent/eval/retrievalGolden.ts 加一个 runner runRetrievalEval.ts。它的逻辑朴素到极致:23 条 golden query,每条标注"top-k 结果路径里应该出现哪些子串",命中即算 hit,最后算 recall = hits / total。比如:
{ query: 'How does Raft elect a leader?', expect: ['raft'] },
{ query: 'Multi-head latent attention in DeepSeek', expect: ['mla'] },
这套东西在 CI 里跑得飞快、纯离线、不需要 embedding key,作为回归 tripwire 是合格的。但它有一个必须诚实说出来的根本局限,我把它直接写进了源码注释:
大多数 query 把目标主题的 slug 直接嵌进了问题里("Raft" → expect
'raft'),所以在当前 BM25-only 索引上,这是一个词法基线(BM25 拿主题词去匹配文件名/标题),而不是语义检索指标——这里 recall 高,主要是结构性的。
这意味着什么?意味着如果我拿这个 0.9+ 的 recall 去简历上写"我的 RAG 系统检索召回率 90%",那是自欺。真正的语义检索要测的是:"用户问 'how do databases avoid lost updates',系统能不能把没有 'MVCC' 字面词的 MVCC 笔记捞出来"。当 query 与目标文档共享字面 token 时,BM25 几乎必中,这道题根本没考到向量召回。它要变成有意义的检索指标,需要两个前置条件同时满足:(a)真实向量 embedding 上线,让 RRF(Reciprocal Rank Fusion)真的在融合两路信号;(b)query 被改写成避开 slug 的语义改写(paraphrase)。在那之前,正确的读法是"回归绊线,不是分数"。
这个诚实判断是整篇文章的起点:一个跑得过、数字漂亮的 eval,未必在测你以为它在测的东西。 评测体系的演进,本质是不断逼近"测的就是用户真正在乎的失败"。
3. 错误分析方法论:Hamel/Shreya 的五步
要让 eval 测到真正的失败,不能靠拍脑袋设计指标,得先看数据。Hamel 与 Shreya 给出的方法论(hamel.dev,2026-01)核心是一句话:在搭任何基础设施之前,先花 30 分钟人工读 20–50 条输出。完整五步:
- 构造代表性 trace 数据集。trace 是从单次用户 query 到最终响应之间,所有动作、消息、工具调用、检索结果的完整记录。先有一批真实(或贴近真实)的 trace。
- 开放编码(open coding)。人类标注者对每条 trace 写开放式备注——不预设分类,纯描述"这里哪儿不对"。
- 轴向编码(axial coding)。把散落的备注归并成 5–6 个失败类别,形成 taxonomy。
- 迭代到理论饱和。继续读新 trace,直到大约 20 条不再冒出新类别,就可以停。
- 一个"仁慈独裁者"。用一位最懂用户的领域专家做质量裁决者,保证标注口径一致,而不是委员会投票稀释判断。
样本量上他们给了可操作的启发式:初次错误分析至少读 100 条 trace;上生产后每 2–4 周再抽 100+ 条新鲜 trace,外加每周 10–20 条异常 trace 的轻量复审。这套节奏的关键洞察是:失败的分布会漂移,一次性的错误分析会过期,evals 必须是持续工程而非一锤子买卖。
对照本仓库,AML 子系统其实已经隐含走了这条路:generator.ts 合成出 66 个案件,但它们不是随机噪声——每个案件按真实反洗钱**类型学(typology)**构造(structuring 拆分存款 / layering 分层转移 / mule_network 洗钱骡网络),这等价于"先做错误分析,把领域专家知道的失败模式编码进数据"。taxonomy 不是事后归纳,而是先验注入。这是用合成数据走错误分析捷径的一种合法做法,前提是 taxonomy 本身来自领域真知。
4. failure taxonomy 驱动 eval 设计
错误分析的产物是一张 failure taxonomy,而 eval 套件应该是这张表的逐行翻译。这就是 Aman Khan 三类 evals 分工的用武之地——不是先选工具,而是先看每一类失败最便宜的可靠判定方式是什么。下面这张表是我对本仓库两个子系统的失败模式做的映射:
表 1:failure taxonomy → eval 类型映射
| 失败模式(来自错误分析) | 子系统 | 这类失败用哪种 eval 最划算 | 本仓库现状 |
|---|---|---|---|
| 该捞的笔记没进 top-k | RAG | 代码型(recall@k 断言) | ✅ 已有,但为词法基线 |
| 捞回的笔记主题对但片段答非所问 | RAG | LLM-judge(相关性四段式) | ❌ 待建(需语义 query 重写) |
| structuring 案件漏报 | AML | 代码型(per-typology recall 门槛) | ✅ recall ≥ 0.85 已进 CI |
| normal 案件被误判成可疑 | AML | 代码型(normal FPR 门槛) | ✅ FPR ≤ 0.15 已进 CI |
| SAR 草稿引用了不存在的交易(幻觉引用) | AML | 代码型(citedTxIds ⊆ 案件交易集) | ✅ 测试已断言子集关系 |
| SAR 草稿叙述逻辑不连贯/语气不专业 | AML | LLM-judge + 人工抽检 | ❌ 待建(当前为模板,无 LLM 生成) |
这张表的设计原则来自 Hamel/Shreya 的成本梯度:能用代码型断言判定的失败,绝不动用 LLM judge。 简单 assertion(regex、schema 校验、子集关系)是确定性的、零成本、零漂移的;LLM judge 昂贵、需要 100+ 标注样本维护、还会自己漂移,只应该瞄准那些"对错本身需要语义理解才能判"的持久问题。本仓库 AML 子系统聪明的地方在于:它把"幻觉引用"这种看似需要 LLM 才能查的问题,降维成了一个纯代码可判的集合包含关系(citedTxIds ⊆ 交易集)——这正是错误分析的价值,它告诉你哪些失败其实根本不需要 LLM 来抓。
5. 三类 evals 的分工与 LLM-judge 四段式
Aman Khan 把 evaluator 分为三类(2025-06 / 2026-04 更新),这与 Hamel/Shreya 的划分一致:
- 代码型 / 断言型:确定性检查。regex、JSON schema 校验、数值门槛、集合关系。快、便宜、可入 CI。
- LLM-as-judge:用一个模型给另一个模型的输出打分,适用于"相关性""有帮助""语气专业"这类需要语义理解的维度。是 reference-free 的,但需要 100+ 标注样本来校准并持续维护。
- 人工标注:领域专家亲自评,最贵但最权威,作为 judge 的校准锚点和高风险样本的最终裁决。
Aman Khan 给 LLM-judge 的 prompt 提供了一个四段式结构(2026-04 版),实战中非常稳:
- 角色与任务:你是某领域的资深评审,任务是判断以下输出是否满足 X。
- 评分标准(rubric):把"满足"拆成可勾选的具体条件,越具体越不漂移。
- 少样本范例:给 2–3 个正例和反例,锚定边界。
- 结构化输出:强制返回
{verdict, reasoning},先理由后判定,便于事后审计和找 judge 自己的错误。
但这里有一条 2026 年被反复验证的红线:LLM 模拟用户是不可靠代理。 Hamel/Shreya 在 FAQ 里明确警告不要用全合成的多轮对话来测 agent——"N-1 testing"(用真实对话前缀,只让模型生成最后一轮)远比纯合成交互可靠;在复杂领域、低资源语言、高风险场景,合成数据会失效到无法验证(2026-01)。另一份独立分析也指出"LLM 模拟用户是不可靠代理",关键评分必须保留人工抽检(2026-01)。
这条红线对 AML 这种高风险金融场景尤其要命。你不能让 GPT 扮演洗钱嫌疑人生成对话、再让另一个 GPT 判定 SAR 写得对不对——监管语境下,"模型判模型"的闭环没有任何外部锚点,是危险的自我循环。本仓库的处理是诚实的:SAR 当前是规则模板生成(sarDraft.ts,generatedBy: 'rule-template'),且测试断言每份草稿的引言必须含"合成数据"和"非 LLM"字样——把数据来源和生成方式的诚实声明写进了 eval 本身。
6. judge 校准:Cohen's kappa 与一个量化口子
一旦决定要用 LLM-judge,第一件事不是部署它,而是校准它。2026 年的共识是:judge 上线前必须在一个 gold-set 上跑过,并验证它与人类标注的 Cohen's kappa 超过阈值(futureagi.com,2026-01;eval.qa,2026)。gold-set 通常取 30–200 条来自真实评测分布、由领域专家标注的样本。
为什么是 Cohen's kappa 而不是准确率?因为准确率会被类别不平衡严重误导。Cohen's kappa 衡量的是扣除随机一致之后的真实一致度:
κ = (p_o − p_e) / (1 − p_e)
其中 p_o 是 judge 与人类的实际一致比例,p_e 是仅凭各自边际分布偶然一致的期望比例。一个广为引用的反例:一个准确率 0.9、Cohen's kappa 0.1 的 judge 基本就是在瞎猜——同样的 judge 在打乱标签的数据集上会给出几乎一样的准确率(futureagi.com,2026-01)。所以基线运行应当同时记录 accuracy / precision / recall / F1 / Pearson / Spearman / Cohen's kappa 一整套,而不是只报一个好看的数。
落地的 kappa 阈值经验值:
表 2:Cohen's kappa 解读与 judge 上线门槛
| κ 区间 | 一致度解读 | judge 是否可上线 |
|---|---|---|
| < 0.20 | 几乎随机 | ❌ 等同瞎猜,废弃重做 rubric |
| 0.20 – 0.40 | 弱一致 | ❌ 需重写 rubric + 加少样本 |
| 0.40 – 0.60 | 中等一致 | ⚠️ 可上线但需人工抽检兜底 |
| 0.60 – 0.80 | 强一致 | ✅ 多数生产场景可接受 |
| > 0.80 | 极强一致 | ✅ 高风险场景的目标线 |
配套的运维动作:建一个月度校准 job,每月拿 50–100 条 gold-set 重跑 judge,对 kappa 下跌告警(futureagi.com,2026-01)。同时控制 judge 的两类系统偏差——位置偏差(position bias,对调两个候选顺序各跑一遍取平均)与冗长偏差(verbosity bias,加长度惩罚或长度归一化)。一个 judge 真正"生产就绪"的定义是:rubric 锁定 + 测得 kappa + 位置/冗长偏差控制 + 跨模型族(用另一个 frontier 模型)交叉验证四件齐全。
7. 阻断式 CI gate:eval-driven development 五道门
evals 写出来不进 CI 等于没写。Braintrust 把 eval 定义成 CI/CD 里的质量门(eval-as-gate):PR 触发 eval,分数低于阈值直接红、阻断合并。这与传统单测的差别在于,eval 门槛是统计性的(recall、FPR、kappa),不是布尔的(pass/fail 单条),所以门槛要设成区间而非点值。
本仓库 AML 子系统已经把五道门焊进了 vitest(src/aml/__tests__/aml.test.ts),构成一套真正的 eval-driven development:
门 1 — 数据集完整性:66 案件、各 label 计数精确(structuring 18 / layering 15 / mule_network 15 / normal 18)、id 全局唯一、引用完整(账户属主体、交易属账户)。坏数据集会让一切下游指标无意义,所以先守数据。
门 2 — 确定性:同 seed 两次 generateDataset 必须 deep-equal。eval 的可复现是底线——一个随机抖动的 eval 没法 A/B,更没法回归。这呼应了本仓库 dsdb-lab 里用确定性 PRNG 做交互式教学的同一原则。
门 3 — per-typology recall 门槛:structuring recall ≥ 0.85、layering ≥ 0.80、mule_network ≥ 0.80。这是"该报的不能漏"。
门 4 — normal 误报门槛:FPR ≤ 0.15。这是"不该报的不能滥报"。门 3 与门 4 一起,把分类器钉在 recall-precision 权衡的一个可接受区域里——只守一边会被钻空子(全部判可疑可以让 recall=1,但 FPR 爆表)。
门 5 — 幻觉引用门 + 不变量:混淆矩阵计数总和必须 = 66(没有案件丢失或重复计数);每份 SAR 草稿 citedTxIds 必须是案件交易集的子集且去重。这道门把"模型/规则别引用不存在的证据"变成了编译期就能挡住的硬约束。
这五道门的设计哲学和金融系统的对账思路一脉相承:先守不变量(守恒、子集、计数),再守性能指标(recall、FPR)。 不变量被破坏是 bug,指标退化才是回归——两者要分开报警。
8. 可观测:OTel GenAI semconv 与 Langfuse
CI 门守的是上线前,生产线上的失败要靠可观测捕获。Aman Khan 的三段式路径 "Prototyping → Observability → Evals"(2025-06 / 2026-04)说明了顺序:先有原型,再有观测拿到真实 trace,最后用真实 trace 喂错误分析和 evals。观测是连接"线上真实失败"与"离线 eval 套件"的输血管。
标准层面,OpenTelemetry 的 GenAI semantic conventions 正在成为 LLM 可观测的事实标准。需要诚实标注的是:截至 2026-03,这套 semconv 仍处于 experimental(Development)状态,API 尚未稳定(opentelemetry.io)。它定义的关键属性包括 gen_ai.request.model、gen_ai.usage.input_tokens、gen_ai.response.finish_reasons,以及 agent 维度的 gen_ai.agent.id / gen_ai.conversation.id 等。一个对金融场景至关重要的默认设置:默认不采集 prompt/completion 正文内容(opt-in 才记录)——这对 AML 这种含 PII 和敏感交易细节的场景是合规友好的默认值。Datadog 已在 2025-12 原生支持这套 semconv,新旧版本切换由 gen_ai_latest_experimental 开关控制(默认仍发 v1.36.0 及更早,避免破坏已有采集)。
工具层面,Langfuse 是开源自托管首选——这对金融/AML 场景的数据驻留与合规要求几乎是硬需求(trace 不能离开自己的边界)。一个值得记录的生态事件:Langfuse 于 2026-01 被 ClickHouse 收购,但承诺保持开源(这点对依赖它的团队是定心丸)。生产侧再补两块拼图:Braintrust 做"eval-as-CI 质量门",Arize Phoenix 做生产观测 + 漂移检测。漂移检测尤其关键——它正是触发"该重做一轮错误分析了"的信号源,把第 3 节那个"失败分布会漂移"的洞察闭环了起来。
值得一提的是 agent 可靠性的度量正在升级。τ²-bench 提出的 pass^k 指标("k 次独立尝试全部成功",2025-06 论文,2026-04 扩到 38 个模型对比)刺破了一个普遍的自欺:一个 pass@1 90% 的 agent,在 k=8 时 pass^k 可能掉到 57%——这就是"能力-一致性鸿沟"。对多轮 agent,worst-case 可靠性才是用户体感,平均分会骗人。Princeton 的 HAL 评测基础设施(2025-10)则在标准化这类大规模、可复现的 agent 评测怎么跑。对 AML Copilot 这种"错一次就可能漏掉真实洗钱"的场景,pass^k 思维比平均 recall 更贴近风险本质。
9. AML Copilot 实证:规则基线数字的诚实解读
最后回到本仓库 AML 子系统的实测数字,并给一个诚实到位的解读——这正是 PM/架构师最该具备的判断力:知道一个漂亮数字到底证明了什么、没证明什么。
在 66 案合成金标上跑规则基线(evalRuleBaseline,实测输出):
表 3(补充):AML 规则基线实测
| 类型学 | 样本数 n | recall | 解读 |
|---|---|---|---|
| structuring | 18 | 1.00 | 18/18 全中 |
| layering | 15 | 1.00 | 15/15 全中 |
| mule_network | 15 | 1.00 | 15/15 全中 |
| normal | 18 | FPR 5.56% | 1/18 误判为 structuring |
混淆矩阵干净到几乎对角线:structuring→structuring 18、layering→layering 15、mule_network→mule_network 15、normal→normal 17、唯一一处错配 normal→structuring 1。三个 recall=1.0、FPR=5.56%,看起来近乎完美。
但这个数字必须这样诚实地读:
第一,这衡量的是口径一致性,不是模型性能。generator.ts 用一套规则按 typology 合成案件,typology.ts 用一套规则去检测——两套规则同源同假设。recall=1.0 真正证明的是"生成口径与检测口径自洽",不是"这套规则能在真实脏数据上达到 100% 召回"。真实世界的 structuring 不会乖乖按合成模板长,对抗方还会主动规避。把这个 1.0 当成性能指标写进简历,就是第 2 节那个"词法基线 recall"错误的翻版。
第二,也是最关键的——规则基线的真正用途,是给未来的 LLM 方案立一块必须打败的地板。 这是整个 AML eval 体系设计中最值钱的一招。任何要引入的 LLM typology 分类器或 LLM-SAR-生成器,都必须在同一个 66 案金标上跑,并且至少打平这条规则基线(recall 1.0 / FPR 5.56%)才有资格上线。如果一个昂贵、慢、不确定、还会幻觉的 LLM 连确定性规则的地板都够不到,那它就不该进生产。规则基线 = LLM 必须打败的地板,这把"该不该上 LLM"从信仰之争变成了可量化的 A/B 裁决。这恰恰是 Braintrust eval-as-gate 哲学在一个高风险金融场景里的具体落地。
第三,那个唯一的误报(normal→structuring)不是噪声,它是下一轮错误分析的入口。一个真实的演进闭环会把这条 trace 拎出来开放编码:是阈值设太松,还是这个 normal 案件本身就长得像 structuring?答案会反哺规则或为未来 LLM 的 rubric 提供一个边界样本。一个 FPR 不为零的 eval,比一个 FPR=0 的 eval 更有信息量——后者往往意味着测试集太容易。
10. 结语
把这条演进线收束成一句话:评测体系的成熟度,等于它逼近"用户真正在乎的失败"的程度。
- recall@k 原型教会我们:一个跑得过的 eval 未必测到了真问题(词法 vs 语义)。
- 错误分析(Hamel/Shreya 五步)教会我们:先看数据、先建 taxonomy,再建指标。
- 三类 evals 分工教会我们:能用代码判的别用 LLM judge,高风险场景别让模型判模型。
- Cohen's kappa 教会我们:judge 上线前先校准,准确率会骗人。
- 五道 CI 门教会我们:先守不变量、再守指标,eval 不进 CI 等于没写。
- OTel + Langfuse 教会我们:观测是连接线上失败与离线 eval 的输血管,且要合规默认。
- AML 实证教会我们:漂亮数字要诚实解读——规则基线 1.0 是口径一致性,更是 LLM 必须打败的地板。
对一个 10 年金融零售背景、转向 AI 产品/架构方向的人,这套能力的迁移性极强:金融系统的"对账不变量""清结算地板""风控 recall-precision 权衡",几乎可以一对一映射到 evals 的"子集/计数不变量""规则基线地板""典型学 recall vs normal FPR 权衡"。evals 不是一门新学科,它是把金融级的严谨,搬到 LLM 产品质量上。
SOTA 检查 (2026-06-11)
- 错误分析方法论:Hamel Husain + Shreya Shankar 的五步法(人工错误分析 → 开放/轴向编码 → judge → 代码型检查)截至 2026-01-15 的 FAQ 更新仍是社区主线,Maven 课程持续开班(2000+ 学员)。仍是 SOTA,无替代品;竞争的是工具生态而非方法论本身。
- LLM-as-judge 校准:Cohen's kappa + gold-set + 位置/冗长偏差控制是 2026 主流口径(futureagi.com 2026-01)。仍是 SOTA;元判(meta-judge)多 agent 框架(arXiv 2504.17087)是前沿补充,尚未成主线。
- agent 可靠性度量:τ²-bench 的 pass^k(2025-06,2026-04 扩 38 模型)正取代 pass@1 成为多轮 agent 可靠性的主线指标;HAL(Princeton 2025-10)在标准化评测基础设施。pass^k 是当前 SOTA 思路。
- 可观测标准:OTel GenAI semconv 截至 2026-03 仍为 experimental(Development)状态——这是已知现状,采用时需锁版本(
gen_ai_latest_experimental开关)。Datadog 原生支持(2025-12)。事实标准方向明确但未 GA。 - 开源观测工具:Langfuse 2026-01 被 ClickHouse 收购、承诺保持开源,仍是自托管首选。无变更风险。
- 本仓库局限(诚实复述):(1)
retrievalGolden仍是 BM25 词法基线,语义检索指标待向量 embedding + query 重写上线;(2) AML recall 1.0 是合成数据口径一致性,非真实性能,其价值在于充当 LLM 必须打败的地板;(3) SAR 当前为规则模板(非 LLM),故 LLM-judge 校准链路尚未落地。
本文方法论部分以近 12 个月资料为主线(2025-06 ~ 2026-04);最新进展请追踪 hamel.dev、Aman Khan、OpenTelemetry semconv release notes 与 τ²-bench 排行榜更新。