跳到主要内容

11 篇博文 含有标签「ci-cd」

查看所有标签

Eval 差异分析作为分支保护:交付分数变化,而非分数下限

· 阅读需 11 分钟
Tian Pan
Software Engineer

我曾合作过的一个团队拥有一套看起来很清爽的评估门禁(eval gate):每个 prompt PR 都必须在黄金测试集(golden set)上获得 0.85 以上的评分,否则合并按钮就会保持灰色。他们为此感到自豪。但在六周后,平均质量已从 0.93 悄然滑落至 0.87 —— 每个 PR 都通过了门槛,每个 PR 都成功上线,而且没有任何一个改动需要为这种质量回退负责,因为它们都没有违反规则。这个门槛是根据上个季度的质量快照设定的,而不是根据上周的质量。

这就是绝对阈值评估门禁的失效模式:一个将评分从 0.92 降低到 0.86 的 PR 可以绿灯通过,而一个将评分从 0.80 提升到 0.84 的 PR 却会被挡在门外。团队学到的是“只要过线就能发布” —— 这是一个关于质量的故事。但你真正需要的信号是“如果这个改动在重要的切片(slices)上没有发生回退就发布” —— 这是一个关于回退检测的故事。

测试覆盖率工具在十年前就解决了这个问题。它们报告相对于父提交(parent commit)的差异,并将其细化到每个文件。评估门禁还没赶上这个进度。

Prompt Linting 是 Eval 与生产环境之间缺失的一层

· 阅读需 12 分钟
Tian Pan
Software Engineer

事故报告读起来就像一个单元测试的恐怖故事。一次 Prompt 编辑作为“前置说明清理(preamble cleanup)”的一部分,删除了一段五行的安全条款。测试套件中的每个 Eval(评估)都通过了。每个 Judge(裁判)评分都保持在容差范围内。两周后,一个面向客户的助手产生了一个本该被拒绝的响应,这种响应会在深夜 11 pm 触发信任与安全(Trust & Safety)页面的报警。复盘将这次回归追溯到了一个 PR 中的单处删除,而当时没有任何人标记它,因为负责捕捉回归的套件对安全条款是否存在没有意见——它只对模型在套件记得询问的情况下的表现有意见。

!["https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=Prompt%20Linting%20%E6%98%AF%20Eval%20%E4%B8%8E%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B9%8B%E9%97%B4%E7%BC%BA%E5%A4%B1%E7%9A%84%E9%82%A3%E4%B8%80%E5%B1%82"]

这就是行为评估(behavioral evals)与结构正确性之间的鸿沟。Eval 衡量的是模型生成的内容;它们不衡量 Prompt 本身是什么。而 Prompt 就像代码一样,有一个独立于行为而存在的结构层——必须存在的章节、必须解析的引用、必须插值的变量、必须遵守的长度预算、以及绝不能出现的弃用标识符。当结构层断裂时,行为表现通常会在一段时间内保持绿色,直到生产环境中的某个边缘情况将故障暴露为事故。

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

· 阅读需 12 分钟
Tian Pan
Software Engineer

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

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

无法合并的智能体重构:为什么多文件差异会在衔接处崩溃

· 阅读需 10 分钟
Tian Pan
Software Engineer

一个来自 AI 编程智能体的 40 个文件的重构任务摆到了你的桌面。你打开 PR,滚动查看差异(diff),每一个代码块(hunk)看起来都没问题。命名重构很一致,导入很整洁,测试在隔离状态下也能编译。你合并了代码。40 分钟后,主分支的 CI 变红了,因为同级包(sibling package)中的两个调用点仍然向一个现在需要四个参数的函数传递三个参数,而原本能捕获这一错误的类型检查器从未包含在智能体的内环(inner loop)中。

这是当今智能体编写的重构中最常见的失败模式,而且它与单个修改的质量几乎无关。每一个文件单独审查时,看起来都像是一个细心的人类写的。Bug 存在于“接缝”处——即来自不同文件的修改必须保持一致的边界。文件级的审查隐藏了接缝级的正确性,而大多数审查工作流都是围绕文件设计的。

AI 作为 CI/CD 门禁:智能体可以和无法可靠拦截的内容

· 阅读需 11 分钟
Tian Pan
Software Engineer

一个 AI 审查器拦截了一个合并(merge)。一名开发者盯着失败的检查,点击“查看详情”,扫视了三段样板文字,然后在没有阅读实际发现的情况下提交了一个“强制推送异常”(force-push exception)。在不到一周的时间里,团队中的每一位工程师都在潜意识里认为 AI 门禁只是背景噪音——是需要被忽略的,而不是需要去参与处理的。

这是大多数构建 AI CI/CD 门禁的团队实际交付的结果,即便底层模型在技术上是有能力的。问题不在于 AI 是否能审查代码,而在于你要求它拦截什么,以及你期望在它拦截时发生什么。

真正能阻断 PR 合并的提示词回归测试

· 阅读需 12 分钟
Tian Pan
Software Engineer

问任何一个 AI 工程团队是否测试了他们的提示词,他们都会说"是的"。再问一句:一个有问题的提示词能否让 PR 失败并阻断合并?房间里会安静很多。对大多数团队而言,诚实的答案是否定的 —— 他们偶尔会跑一些评估笔记本,也许有一份记录已知提示词问题的共享 Notion 文档,以及一种模糊的感觉:事情比以前更糟了。那不是测试,那是在碰运气。

这个差距的存在,是因为提示词测试在感觉上与单元测试有本质区别。代码要么行为正确,要么不正确。提示词的输出处于一个连续谱上,输出是非确定性的,而且运行足够多的样本以建立信心会花费真金白银。这些都是真实的约束,但没有一个是无法克服的。那些建立了真正阻断合并的提示词 CI 的团队,并不是在每次构建上花费五十美元 —— 他们在三分钟以内、花费不到一美元的情况下完成运行,这得益于几个让这个问题变得可处理的设计决策。

CI 流水线中的 AI 智能体:如何为无法单元测试的部署设置质量关口

· 阅读需 11 分钟
Tian Pan
Software Engineer

发布一个调用 LLM 的功能很容易。但要判断该功能的下一个版本是否优于生产环境中的当前版本,却相当困难。传统 CI/CD 对确定性行为提供通过/失败信号:函数要么返回正确值,要么不返回。但当函数封装了一个语言模型时,输出是概率性的——相同的输入在不同运行、不同模型版本和不同时间会产生不同输出。

大多数团队的应对方式是绕过这个问题。他们运行单元测试,对几个提示词做快速的人工检查,然后发布。这种方式在出问题之前都还能用——直到某个模型提供商悄悄更新了底层权重,或者一个看似没问题的提示词改动在孤立测试中没有异常,却在凌晨三点以生产流量规模改变了输出分布。

更好的答案并非假装 LLM 输出是确定性的,而是构建基于分布、阈值和评分标准的 CI 质量关口,而不是精确匹配。

Agent 测试金字塔:为什么 70/20/10 的分层对 Agentic AI 行不通

· 阅读需 14 分钟
Tian Pan
Software Engineer

每一个从"我们有个聊天机器人"升级到"我们有个 Agent"的工程团队,都会撞上同一堵墙:他们的测试套件开始失去意义。

经典测试金字塔——70% 单元测试、20% 集成测试、10% 端到端测试——建立在三个基本假设之上:单元测试运行成本低、与外部系统隔离、结果确定可重复。Agentic AI 系统同时打破了这三个假设。所谓的"单元"是一次消耗 token 且每次返回不同结果的模型调用。一次端到端运行可能耗时数分钟,消耗的 API 预算足以让一位初级工程师整个迭代周期的测试都无法证明其合理性。而隔离性几乎无从实现,因为 Agent 的智能恰恰来自于与外部工具和状态的交互。

大模型驱动的测试生成:利用 AI 发现软件中的 Bug,而不仅仅是编写代码

· 阅读需 10 分钟
Tian Pan
Software Engineer

大多数使用 LLM 的工程团队都专注于代码生成 —— 让模型更快地编写功能。但有一个杠杆率更高、受关注度却低得多的应用:使用 LLM 生成能发现人类遗漏的 bug 的 测试。不是测试 AI —— 而是 AI 测试你的软件。

这个想法非常诱人。手动编写的测试套件受限于人类的想象力,这意味着它们往往集中在开发者能想到的场景中。LLM 探索状态空间的方式则完全不同。它们生成的输入和边界情况对于原始作者来说往往感觉很陌生 —— 而这恰恰是未被发现的 bug 潜伏的地方。

但现实比愿景要复杂得多。原生 LLM 生成的测试有一半以上的时间无法通过编译。超过 85% 的失败源于错误的断言。而且,将非确定性的生成过程集成到确定性的 CI 流水中,本身就会产生一系列工程难题。以下是让它真正发挥作用的方法。

如何在 CI 中对 AI Agent 工作流进行集成测试,而无需完全 Mock 模型

· 阅读需 13 分钟
Tian Pan
Software Engineer

大多数构建 AI Agent 的团队在经历第一次生产事故后,都会发现同一个测试陷阱。你有两个明显的选择:在 CI 中进行实时的 API 调用(缓慢、昂贵、且具有非确定性),或者将 LLM 完全 Mock 掉(快速、廉价、但内容空洞)。这两种方法都会以不同但可预见的方式失败,而第二种方法的失败模式更糟糕,因为它是隐形的。

Mock 掉 LLM 的团队可能会跑六个月的全绿 CI,发布到生产环境后,才发现代码库中一直潜伏着一个 bug:在 8 步循环的第 6 步,Agent 处理畸形工具响应的方式有问题。那个总是返回 "Agent response here" 的 Mock 根本没有触及编排层。实际的工具分发、重试逻辑、状态累积和兜底路由代码从未被测试过。

好消息是还有第三条路。它与其说是一种单一的技术,不如说是一个由三层测试组成的架构,每一层都旨在捕获不同类别的失败,且无需承担其他方法的成本。

代理系统的非确定性 CI:为什么二进制的通过/失败模式会失效,以及取而代之的是什么

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的 CI 流水线假设了一件自你加入 LLM 调用以来就不再成立的事情:运行相同的代码两次会产生相同的结果。传统的 CI 是为确定性软件构建的 —— 编译、运行测试、获得绿灯或红灯。传统的 ML 评估是为固定的输入输出映射构建的 —— 对测试集进行推理、计算准确率。Agent AI 同时打破了这两个假设,其结果是一个要么对你撒谎,要么因误报而阻塞每次合并的 CI 系统。

核心问题不在于 Agent 难以测试,而在于你现有的测试基础设施是为一个“非确定性是 Bug 而非特性”的世界设计的。当你的 Agent 在连续运行中通过不同的工具调用路径得到相同的正确答案时,确定性断言就会失败。当它产生语义等效但词汇不同的响应时,字符串比较会将其标记为回归。测试框架本身变成了噪音的来源。