# 25 · 评测驱动:把「够好」写进架构 > 一句话点题:**[17 章](17-大模型时代的架构判断.md) 抽走了「同样输入 → 同样输出」这块地基,`assert result == expected` 失效了。怎么防止「换个模型、改句提示,质量就悄悄变差」?把「够好」量化成一套评测(eval),当 CI 门禁——让质量从「靠投诉发现」变成「可量化、可守门」。** --- > **🤝 AI 协同设计篇第 3 章 · 本章只练一件事** > > [24 章](24-审查清单AI产出默认缺什么.md) 靠人逐条审,但「答案质量稳不稳」人查不过来。本章把关从「人工逐条」升级成「机器持续」。这是 [20 章 ADR-005](20-演进剧本MVP到规模化.md) 和 [22 章](22-AI原生系统设计.md) 反复点到的 **eval 门禁**的完整展开,也是非确定性([17 章](17-大模型时代的架构判断.md))唯一靠谱的解法。 --- ## 一、为什么传统测试在 AI 系统上失效 传统系统的测试,建立在**确定性**上: ``` 传统: assert summarize(x) == "预期的那一句" ← 二元:对 / 错,能精确断言 LLM: summarize(x) 这次输出 A,下次可能输出 A' ← 温度、模型版本、上下文一变就不同 两次都「对」,但字面不同 → assert == 直接挂 ``` [17 章](17-大模型时代的架构判断.md) 说过:LLM 把确定性地基抽走了。于是传统测试遇到两个死局: 1. **断言不了**:输出不固定,`== expected` 必然误报。 2. **退化无声**:你把模型从旧版升到新版、或改了句系统提示,某类问题的答案**悄悄变差了**——没有任何测试会红,你只能等用户投诉([20 章](20-演进剧本MVP到规模化.md) 那个「两周后才从投诉发现」的坑)。 > **核心转变(来自 [17 章](17-大模型时代的架构判断.md)):从「断言单条正确」转向「衡量一个质量分布」。** 不再问「这一条对不对」,而问「这一**批**代表性输入,整体质量分**够不够好、有没有比上一版退**」。这就是 eval。 --- ## 二、eval 的三件套 ``` ┌─────────────┐ ┌──────────────┐ ┌─────────────────────┐ │ ① eval 集 │──▶│ ② 评分 │──▶│ ③ 门禁(CI) │ │ 代表性输入 │ │ 规则/模型/人工 │ │ 分数低于基线 → 拦截 │ │ + 期望要点 │ │ 给每条打分 │ │ 不许上线 │ └─────────────┘ └──────────────┘ └─────────────────────┘ ``` ### ① eval 集:测试集的 AI 版 一批**代表性输入** + 每条的**期望要点**(注意:是「要点 / 判据」,不是「逐字的标准答案」)。 > 例(AI 客服):输入「我上周买的鞋开胶了能退吗?」→ 期望要点:`①引用了质保政策 ②给出明确的能/否 ③没有编造不存在的政策 ④口吻得体`。评的是这几个要点中了几条,不是逐字比对。 ### ② 评分:谁来判「够不够好」 | 评分方式 | 适合 | 代价 / 风险 | |---|---|---| | **规则 / 程序判定** | 有客观判据(含不含某关键词、格式对不对、有没有引用) | 便宜、稳定,但只能判「硬」标准 | | **LLM-as-judge**(模型当裁判) | 主观质量(答得好不好、相不相关) | 灵活,但**裁判本身也非确定、也会错、也烧 token** | | **人工抽样** | 校准前两者、兜底高价值场景 | 最准,但慢、不可规模化 | > 实务:**规则能判的先用规则**(便宜可靠),主观的用 LLM-as-judge,再**定期人工抽样校准裁判**——别盲信模型裁判,它也是个会出错的模型。 ### ③ 门禁:让 eval 真正「守门」 光跑 eval 不够,要**接进 CI 当门禁**(这正是 [20 章 ADR-005](20-演进剧本MVP到规模化.md)):**换模型、改提示、改检索策略前,CI 自动跑 eval;整体分数低于基线,一律拦截、不许上线。** ``` 改提示 / 换模型 ──▶ CI 跑 eval ──┬─ 分数 ≥ 基线 → 放行 └─ 分数 < 基线 → 🔴 拦截(防悄悄退化) ``` --- ## 三、怎么建第一个 eval(别想一步到位) 新手一听「评测集」就想攒几千条——然后永远没开始。正确姿势是**从小、从真实失败长出来**: 1. **种子来自线上真实 bad case**:每一条用户投诉、每一个「答错了」的截图,都是最值钱的 eval 样本——它们是真实失败,不是你想象的失败。先攒十几二十条,就能跑起来。 2. **离线 + 在线两条腿**: - **离线 eval**:固定数据集,进 CI,把关「上线前」(防退化)。 - **在线 eval**:对**真实流量**抽样打分 / 影子运行打分(正是 [21 章](21-拆分与迁移实战.md) 的影子流量!),把关「上线后」(真实分布永远比你的数据集刁钻)。 3. **持续加 case**:每次发现新的失败模式,就把它**固化成一条 eval**——和写回归测试一个道理。eval 集是「活」的,随系统一起长大。 > 这套「从真实失败攒起、小步快跑、持续扩充」的节奏,和 [21 章](21-拆分与迁移实战.md) GitHub Scientist 的「用真实流量当裁判」、[07 章](07-从0到1设计一个系统.md) 的「架构是迭代出来的」完全同源——**别等完美的评测集,先用粗糙的把循环跑起来。** --- ## 四、eval 不替代传统测试,是新增一层 别误会成「有了 eval 就不写单测了」。一个 AI 系统里,**确定性的部分照样用传统测试**,eval 只管「非确定性输出的质量」: ``` ╱╲ eval 层(新增) ╱ ╲ ── 非确定性输出的「质量分布」:答得好不好、退没退化 ╱────╲ ╱ E2E ╲ 传统金字塔(照旧) ╱──────────╲ ── 确定性逻辑:退款幂等、状态机、鉴权、API 契约 ╱ 集成 / 单测 ╲ 这些有唯一正确答案 → 照样 assert == ╱────────────────╲ ``` 回到 [19 章](19-完整设计演练中等复杂度系统.md) 那个 AI 客服:**退款服务是确定性的 → 用单测断言幂等、断言金额校验**(`assert ==` 照样有效);**模型生成的答案是非确定的 → 用 eval 评质量分布**。两套并存,各管一段。**「把不确定性挡在副作用之外」([19 章](19-完整设计演练中等复杂度系统.md))的好处在这又兑现了一次:确定的部分还能用确定的方法测。** --- ## 五、eval 的成本与陷阱(它不是免费的) 把 eval 当架构组件,就要像对待任何组件一样看它的代价: - **跑 eval 烧钱、耗时**:每条样本都要真实调用模型,LLM-as-judge 更是「评一次 = 又一次模型调用」。eval 集越大、跑得越勤,成本越高——要在**覆盖度和成本**之间权衡(又一次 [06 章](06-质量属性与取舍.md) 的取舍)。 - **裁判会错**:LLM-as-judge 本身非确定、有偏见(比如偏好长答案)。要用人工抽样校准它,别把它的分当圣旨。 - **过拟合与老化**:盯着固定 eval 集调久了,会「为了考高分而优化」,对集外样本未必好;且业务变了,旧 eval 集会过时。要持续更新(同 [23 章](23-规格即架构约束怎么写给AI.md) AGENTS.md「过时比没有更糟」)。 > **架构智慧**:**eval 是 AI 系统的「质量适应度函数」**——它之于答案质量,正如 [14 章](14-演进与拆分大型系统.md) 的适应度函数之于架构边界:都是「把你在乎的东西,变成一道会失败、能卡 CI 的自动检查」。区别只是:架构边界能精确断言,答案质量只能评分布。**把「够好」写进 eval、接进门禁,你才敢放心地升级模型、迭代提示——否则每一次「升级」,都是闭着眼睛赌它没变差。** --- ## 🎯 随堂检验 --- ## 本章小结 - **传统测试在 AI 上失效**:输出非确定,`assert ==` 误报;更糟的是质量退化**无声**,只能等投诉。 - **从「断言单条」转向「衡量分布」**:这是 [17 章](17-大模型时代的架构判断.md) 的核心转变,落地就是 eval。 - **eval 三件套**:① eval 集(代表性输入 + 期望要点)② 评分(规则 / LLM-as-judge / 人工抽样)③ **门禁**(进 CI,低于基线就拦,即 [20 章 ADR-005](20-演进剧本MVP到规模化.md))。 - **从真实失败小步攒起**:种子来自线上 bad case;离线(CI)+ 在线(影子,[21](21-拆分与迁移实战.md))两条腿;持续加 case。 - **eval 不替代传统测试**:确定性逻辑照样单测,eval 只管非确定输出的质量分布。 - **eval 不免费**:烧钱、裁判会错、会过拟合老化——要权衡覆盖与成本、持续校准维护。它是 AI 系统的「质量适应度函数」([14](14-演进与拆分大型系统.md))。 > **承上启下**:到这儿,AI 协同的三件武器齐了——**规格(23)给约束、清单(24)审产出、eval(25)守质量**。但什么时候用哪件、什么时候干脆放手 vibe、什么时候必须 spec-first?最后一章 [26 · 协作决策树:何时 vibe、何时 spec-first](26-协作决策树何时vibe何时spec-first.md) 把这三件武器收成**一套可照着走的 workflow**,并为整套 26 章教程收尾。 --- ## 相关链接 - 理论本体:[17 · 大模型时代的架构判断](17-大模型时代的架构判断.md)(非确定性 → 评测驱动) - 同源案例:[20 · 演进剧本(ADR-005 eval 门禁)](20-演进剧本MVP到规模化.md) · [22 · AI 原生系统设计](22-AI原生系统设计.md) · [21 · 影子流量](21-拆分与迁移实战.md)(在线 eval) - 配套:[14 · 适应度函数](14-演进与拆分大型系统.md)(架构的自动检查)、[06 · 质量属性与取舍](06-质量属性与取舍.md)(覆盖 vs 成本)