跳到主要内容

55 篇博文 含有标签「testing」

查看所有标签

Eval 回填税:为什么每一次模型能力发布成本都超出了你的预算

· 阅读需 11 分钟
Tian Pan
Software Engineer

一名高管发了一封只有一行字的邮件:“好消息——我们在下个冲刺周增加视觉能力。”产品经理将其解读为一星期的工作量:更换模型、开放图像参数、发布。评估(Eval)团队读了同样的邮件,脑子里已经开始起草一份尚未获批的四周计划。到了周五,这种认知脱节在站会上表现为一句含糊的“我们需要做一些评估工作”,然后大家一致同意以后再解决。

这种在“我们添加了视觉能力”与“我们可以安全发布视觉能力”之间的鸿沟,就是评估补填税(Eval Backfill Tax)。每当新的模型能力落地时——多模态输入、工具使用、更长上下文、推理轨迹、电脑使用——这项工作就会悄无声息地落在评估团队身上。因为历史测试案例是在一个模型不会以这些新方式失败的体系下构建的。测试套件依然显示绿色,头条基准测试分数在上升,但生产环境的发布却暴露出了没人写过测试的失效模式。

快照评估衰减:当绿色的 CI 不再意味着你的产品仍然可用

· 阅读需 12 分钟
Tian Pan
Software Engineer

六个月的绿色 CI 掩盖了一个事实:大约 40% 的评估集(eval set)已不再代表用户在产品中的实际行为。测试套件仍在运行,裁判(judge)仍在打分,仪表盘依然闪烁着绿光。但这些案例是针对查询分布、语料库、工具界面和监管文本编写的,而这些内容早已发生了变化——现在的绿色运行意味着“昨天的产品在昨天的现实中依然有效”,而这并不是你付费让 CI 回答的问题。

这就是“快照评估退化”(snapshot eval decay),它是 AI 评估中最缓慢、最昂贵的失败模式。说它缓慢,是因为套件从未失败——陈旧性表现为无法区分模型优劣,而不是构建变红。说它昂贵,是因为当有人意识到评估通过的模型切换导致了生产环境回归时,团队已经建立了一年之久的“评估通过即发布”的肌肉记忆,而这一记忆是建立在一个早已悄然失效的资产之上的。

Agent 分支覆盖率:你的评测仅命中了 Happy Path,而非 Planner 的 If-Else 逻辑

· 阅读需 9 分钟
Tian Pan
Software Engineer

我上季度合作的一个团队针对其支持智能体(support agent)运行了一套包含 240 个案例的评估集。连续六个月,测试结果全线飘绿。接着,他们更换了规划器提示词(planner prompt)中的一个句子——仅仅是一次语气调整——结果第二天生产环境的人工接管请求激增了 3 倍。而评估分数却纹丝不动。人工接管分支仅仅是开始在以往能在线解决的临界案例上触发,而评估集中没有一个案例属于这种临界类型。该分支存在于提示词中,存在于生产环境中,唯独不存在于评估集中。

这就是我想命名的失败模式:智能体分支覆盖率 (agent branch coverage)。代码覆盖率工具在过去的 40 年里一直是调试的基础,但智能体系统具有运行时控制流——规划器分支会选择工具、限定回复条件、升级到人工、拒绝执行、或尝试不同的策略重试——而评估集仅触及团队想到的那些案例。规划器 80% 的决策分支从未在测试下执行,于是,一份“全绿”的评估报告就成了一场披着回归测试外衣的冒烟测试。

需求文档、代码、测试皆出自一人:你正在悄然失去的独立性

· 阅读需 12 分钟
Tian Pan
Software Engineer

当同一个模型负责编写需求、实现代码并编写用于验证正确性的断言时,“所有测试通过”不再是功能正常工作的证据,而仅仅证明了模型是内部一致的。这是两回事,而这种区别正是编写测试的初衷。

我们通常对测试套件的理解是,它们提供了“第二意见”。作者带着一种对需求的心理模型编写代码,而测试编写者则带着略有不同的心理模型编写断言。这两个模型不一致的地方,往往就是 Bug 潜伏之处。这种说法的前提是测试编写者与代码作者拥有不同的认知视角。如果去掉了视角的差异,测试套件就不再携带关于正确性的任何独立信息——它只携带关于一致性的信息。

LLM-as-Judge 的对抗性失效:当你的评测框架被操控

· 阅读需 10 分钟
Tian Pan
Software Engineer

你的 LLM-as-judge 给新模型开了一张健康证明。胜率上升,各项评分指标全线改善,自动化评测流水线全绿通过。然后你上线了——用户满意度却下降了。

这不是边缘案例。研究人员构建了一个无论何种输入都输出固定回复的「空模型」,并在 AlpacaEval 2.0 上拿下了 86.5% 的长度控制胜率。而当时经过验证的真实最优水平是 57.5%。当一个毫无任务能力的模型都能登顶你的排行榜,你的评测框架就有了值得系统审视的问题。

你的评测套件是一座博物馆:生产故障应当成为明天的测试用例

· 阅读需 10 分钟
Tian Pan
Software Engineer

大多数 AI 团队只会构建一次评测套件——在上线前的冲刺阶段,他们精心设计了边界场景用例,记录预期输出,经过评审后发布。六个月后,套件仍然通过。然而,模型在实际生产流量上已经悄然退步,而评测框架却是在那些流量出现之前编写的。它仍然在评判作者提出问题的答案,而非用户真正在问的问题。

这就是"博物馆问题":一个在某个时间点策划的评测套件会不断积累文物。它证明系统能处理某人预期的场景,却无法覆盖真正让它崩溃的场景。

Staging 环境的谎言:为什么预生产阶段对 AI 系统失效了

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的测试环境通过了所有检查。LLM 对每个测试提示词都做出了正确响应。延迟表现良好。质量评分看起来也不错。你发布了。然后,两天后,生产环境开始在你的评估集从未涵盖的一类查询中出现幻觉,你的成本飙升了 3 倍,因为缓存是冷的,而且你的供应商推送的模型更新静默地改变了行为,而你的旧测试套件无法检测到。测试环境显示一切正常,生产环境却给出了截然不同的结果。

这并不是一个可以通过编写更多测试用例来弥补的测试差距。预发布环境对 AI 系统具有结构性的误导,而对传统软件则不然。失败模式是系统性的,解决办法不是更好的测试环境,而是一种不同的架构。

评估集拥挤问题:为什么更大的测试套件捕获的回归反而更少

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的 AI 评估测试集(eval suite)有 800 个测试用例。你又增加了 200 个。现在你的模型在评估中得分 94%,你满怀信心地发布了。三天后,一名用户发现了一个回归(regression)问题,而你那 1000 个测试用例中没有一个捕获到它。

这不是运气不好 —— 而是结构性问题。回归问题的存在恰恰是因为你扩充测试集的方式,而不是尽管你扩充了测试集才存在。当出现故障时增加更多评估指标(evals)的本能在理论上是正确的,但在实践中却适得其反。更多的测试并不自动意味着对重要事项的覆盖率更高。它们意味着对那些易于测试的事项有了更好的覆盖,而这完全是两回事。

AI 系统中的功能交互故障:当两个正常运行的组件结合时发生崩溃

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的流式传输正常工作。你的重试逻辑正常工作。你的安全过滤器正常工作。你的个性化功能也正常工作。但当你将它们部署在一起时,奇怪的事情发生了:流式传输中途出现的速率限制错误导致用户看到的是一段被截断的响应,而系统却将其记录为成功。重试机制触发了,但流式传输已经结束。个性化层提供了一个定制化的响应,而安全过滤器本应拦截这个响应——除非过滤器看到的是 Prompt 的脱敏版本,而不是个性化层所处理的那个版本。

每一个功能都通过了你编写的各项测试。然而系统还是让用户失望了。

这就是功能交互故障(feature interaction failure),它是当今 AI 系统中最容易被误诊的生产环境 Bug。

提示词契约测试:多智能体团队如何协同而不互相破坏

· 阅读需 11 分钟
Tian Pan
Software Engineer

当两个微服务在API假设上出现偏差时,集成测试会在上线前捕获问题。当两个智能体在提示词假设上出现偏差时,你只会在客户收到自相矛盾的答案——或者整条流水线因级联故障崩溃——时才会发现。多智能体AI系统在生产环境中的失败率高达41%–87%。这些失败中超过三分之一并非模型质量问题,而是协调故障:某个智能体改变了输出格式,另一个智能体仍然期望旧的数据结构,而没有人为此写过测试。

根本问题在于,智能体之间通过隐式契约进行通信。一个研究型智能体——在某人的心智模型中——约定返回带有 sources 数组的JSON对象。编排型智能体依赖这个结构。没有人把它写下来,没有人测试它。六周后,研究型智能体的提示词被优化为返回排名列表而非 sources 数组,编排型智能体就悄无声息地丢失了一半输入。

Prompt 变异测试:找出哪些系统提示词指令真正起作用

· 阅读需 12 分钟
Tian Pan
Software Engineer

有一种特定的工程债(Engineering debt)永远不会出现在你的指标中。每当有人在系统提示词(System prompt)中添加一个句子来修复一个偶发的投诉——比如 “绝不讨论竞争对手的产品” 或 “始终以正式的口吻回复” ——而随后又没有人验证模型是否真的执行了它,这种债务就会累积。几个月后,提示词增加到 800 个 Token。它听起来很有权威感,包含的内容包罗万象。但也许其中三分之一根本没起作用。

提示词变异测试(Prompt mutation testing)就是找出那三分之一无效指令的实践。该技术借鉴了软件工程中经典的变异测试:系统地在代码中引入微小、刻意的错误,以确定你的测试套件是否真的能捕获它们。在这里,你向系统提示词中引入刻意的扰动——删除一个分句、抵触一条规则、用近义词替换关键关键词——并衡量模型的输出实际发生了多大变化。那些在扰动下幸存且不影响行为的指令是装饰性的。而那些一旦被触碰就会导致出错的指令则是承重的(Load-bearing)。

覆盖率幻觉:为什么 AI 生成的测试会继承代码的盲点

· 阅读需 10 分钟
Tian Pan
Software Engineer

一位小团队工程师花了三个月将测试生成委托给 AI。代码覆盖率从 47% 跃升至 72%,再到 98%。每次 PR 都返回绿色。然后生产环境崩了。用户注册中的竞态条件因数据库复制延迟导致重复邮箱。优惠码接口在代码无效时返回 null 而非零,导致支付计算对 4700 名客户静默出错。最终损失:4.7 万美元退款和 66 小时工程时间。测试并没有遗漏几个边界情况——它们覆盖了所写的代码,而非所部署的系统。

这就是覆盖率幻觉。随着 AI 辅助开发成为默认选项,落入这个陷阱正变得越来越容易。