跳到主要内容

46 篇博文 含有标签「testing」

查看所有标签

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

· 阅读需 12 分钟
Tian Pan
Software Engineer

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

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

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

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

· 阅读需 11 分钟
Tian Pan
Software Engineer

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

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

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

· 阅读需 10 分钟
Tian Pan
Software Engineer

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

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

AI 功能的 Bug Bash:分布采样,而非猎捕缺陷

· 阅读需 12 分钟
Tian Pan
Software Engineer

经典的 Bug Bash 是一种为确定性软件量身定制的确定性仪式。十名工程师挤在一个 Slack 频道里两小时,对照着黄金路径流程清单疯狂测试,然后提交带有清晰复现步骤的工单:“点击 X,看到 Y,预期 Z。” 这套方法之所以奏效,是因为被测系统是可复现的——相同的输入,相同的输出,相同的 Bug,次次如此。

如果针对 AI 功能运行完全相同的仪式,你最终会得到 200 张工单,其中 180 张会因为“符合预期的随机波动”而被关闭,同时还会漏掉那 20 张预示着真正的群体性回归(cohort regression)的工单。这种形式不仅陈旧,而且完全错位了。针对基于 LLM 的功能进行 Bug Bash 并不是一场捕捉缺陷的会议。它是一场针对概率分布的抽样练习,如果团队像运行确定性测试那样运行它,就是在收集噪声并将其视为信号。

这篇文章讨论的是如何为随机系统重新设计 Bug Bash——包括流程形式、参与者、分级准则以及什么才算“完成”等方面需要做出哪些改变。

评估迁移税:为什么 Prompt Schema 的一次变更会毁掉 800 个测试用例

· 阅读需 13 分钟
Tian Pan
Software Engineer

我见过的每一个发布过“小规模”输出 Schema 变更的 AI 团队,都经历过同样的一周。有人在系统提示词(system prompt)中重命名了一个字段——比如将 summary 改为 tldr,或者工具目录中增加了一个必填的 confidence 参数——结果下一次 CI 运行就在 800 个与该变更毫无关系的 Eval 用例中亮起了红灯。提示词的 diff 只有 15 行。而 Eval 的 diff 却变成了一个为期四天的迁移项目,且无人规划、无人负责,也从未包含在预算之内。

这就是 Eval 迁移税(Eval Migration Tax)。这是任何路线图都没有考虑到的维护成本,它以发布延迟的形式支付,而这些延迟往往被归咎于“不稳定的测试”(flaky tests),而非真正导致它们的架构选择。大多数团队在意识到这一模式之前已经支付了数年的代价,因为每一个单独的事件看起来都像是普通的日常损耗。只有当你统计一个季度内用于迁移 Eval 的工程小时数,并发现它们超过了用于改进 Eval 本应衡量的模型行为的时间时,这种复利效应才会显现。

当你的模型具有随机性时,快照测试在撒谎

· 阅读需 12 分钟
Tian Pan
Software Engineer

当你团队中的初级工程师第一次输入 --update-snapshots 并推送到 main 分支时,你的测试套件就不再是测试套件了,它变成了一份记录稿。虽然 Diff 依然显示为红绿颜色,CI 徽章依然会变为通过,但信号已经悄然反转:测试套件不再告诉你代码是否正确,而是告诉你是否有人费心看过输出。对于确定性的代码,这种风险尚在可接受范围内,因为大多数 Diff 确实是符合预期的。但当网络调用的另一端是一个随机模型时,同样的流程会让每一个 PR 变成一场硬币投掷,让每一位评审者变成一个橡皮图章。

快照测试曾是确定性世界里的一个美妙构想。你记录下上周二 render(<Button />) 的生成结果,断言本周二它会生成相同的字符串。从定义上讲,任何 Diff 都是值得人工核查的行为变更。这种模式在 Jest、Vitest、Pytest、整个 React 生态系统以及一代又一代的 UI 快照扩展中得以幸存,是因为底层契约依然成立:相同的输入加上相同的代码等于相同的输出。但这个契约对 LLM 调用并不奏效。相同的输入、相同的代码加上相同的提示词(Prompt),却会产生不同的字符串——而且这种差异并非 Bug,而是产品按设计正常运行的结果。

评估作者的单一文化:为什么你的基准测试会变成一张自画像

· 阅读需 12 分钟
Tian Pan
Software Engineer

绿色 CI 并不意味着“这个提示词有效”。绿色 CI 的本质是“编写评测的工程师想不出这个提示词会如何出错”。这是两个截然不同的断言,而它们之间的差距正是生产事故的温床。一个评测套件并不是对模型的测量——它是对编写者的冰冷写照。他们的方言、领域知识、资历、偏好的失败模式,以及他们在编写测试用例时恰好使用的模型。根据构造,工程师没想到的测试内容统统未经测试。更糟糕的是:他们会从同一个视角不断扩展套件,因此随着套件的增长,盲点并不会缩小,反而会变得根深蒂固。

这就是评测作者单一化(eval-author monoculture)问题,也是当今 AI 工程中讨论最少、风险最高的可靠性问题。团队痴迷于裁判偏差、位置偏差、冗长偏差、泄漏和污染——但上游偏差其实是最初决定测试用例的人的偏见。其他任何评测误差来源都会被它放大。如果你的套件是由一个人编写的,那么你就拥有了一个带有性格的基准测试,而这种性格正是你的 CI 能够捕获风险的无形天花板。

你的评测框架是单用户运行的,但你的智能体并非如此。

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的 Agent 通过了 92% 的评估测试集。你发布了它。在上线一小时的真实流量中,发生了一些从未在任何追踪(trace)中出现过的事情:Agent 在频率限制(rate-limit)重试风暴中停滞不前,一个客户在工具响应中看到了另一个客户的草稿邮件,你的模型供应商连接池处于 100% 的占用率,而 CPU 却处于闲置状态。这些失败没有一个源自模型。它们存在于你测试的方式与生产环境运行方式之间的鸿沟中。

这个鸿沟表现为同一种形式。你的评估工具(eval harness)在一个固定数据集上一次循环一个 Agent。而你的生产环境则在共享基础设施上同时运行许多 Agent。顺序评估隐藏了每一个前提条件为“两个事物接触同一个资源”的 Bug。在你将对抗性并发(adversarial concurrency)构建到评估工具本身之前,这些 Bug 只会以紧急运维(on-call)报警的形式出现。

评估通过,但工具全是 Mock 的:为什么你的 Agent 最棘手的生产故障从未进入测试框架

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的智能体在评估测试集上达到了 94% 的准确率。然而你的轮值告警却响个不停。房间里没人撒谎,这两个数字都是真实的。实际情况是,测试框架(harness)在测试提示词(prompt),而生产环境在测试智能体(agent),这是两个完全不同的产物,只是恰好共享了权重。

Mock 工具的评估通常是产生这种差距的原因。你用预设的 JSON 存根(stub)了 search_orderscharge_cardsend_email,给模型输入一个用户回合,并对最终响应进行断言。这种运行方式成本低、具有确定性且可复现——这些都是 CI 系统喜欢的特性。但它对工具选择、延迟、速率限制(rate limits)、部分失败和重试行为保持沉默,也就是说,它忽略了那些在事故回顾中占主导地位的失败因素。

Prompt 的语义差异分析:为什么 Git Diff 在提示词变更的影响上会误导你

· 阅读需 12 分钟
Tian Pan
Software Engineer

一位队友提交了一个 PR,将你 Agent 的系统提示词(System Prompt)从 420 行重写为 380 行。Diff 是一片红绿交错的“惨状”:删除了段落、移动了章节、精简了语言。你批准了它,因为这些清理看起来很合理。一周后,退款请求的准确率下降了 8 个百分点,却没人能说出到底是哪一行导致的。

另一位队友在一条指令中添加了“简洁”(concise)这个词。Diff 只有三个字符。没人仔细审查它,因为几乎没有什么可看的。但这次修改导致 22% 的查询在工具调用(Tool-call)行为上发生了变化。

AI 流水线的契约测试:组件间 Schema 校验的交接规范

· 阅读需 11 分钟
Tian Pan
Software Engineer

大多数 AI 流水线故障并非模型问题。模型运行正常,输出看起来也是 JSON,但下游阶段却悄然崩溃——原因可能是字段被重命名、类型发生变化,或者嵌套对象新增了一个下游阶段根本不知道如何处理的必填属性。流水线执行完毕并报告成功,而某个数据仓库里的数字已经悄悄出错。

这就是 AI 流水线的契约测试问题,也是生产 AI 系统中最被忽视的可靠性风险之一。根据近期基础设施基准数据,企业 AI 系统平均每月发生近五次流水线故障,每次解决耗时超过十二小时。主要原因并非模型质量差,而是数据质量和 Schema 契约违规:64% 的 AI 风险存在于 Schema 层。

生产分布差距:为什么内部测试人员找不到用户遇到的Bug

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的 AI 功能在内部测试中表现出色。工程师拍手叫好,产品经理竖起大拇指,评估套件在基准测试中显示了 94% 的准确率。然后你上线了,两周之内,用户就遇到了你从未见过的故障模式——错误的答案、混乱的输出,以及让模型显得极为糟糕的边缘情况。

这就是生产分布差距(production distribution gap)。这不是一个新问题,但对 AI 系统来说,它比确定性软件严重得多。理解其背后的原因——并制定具体的解决方案——是决定 AI 功能悄然侵蚀用户信任还是随着使用不断改进的关键分水岭。