跳到主要内容

28 篇博文 含有标签「devops」

查看所有标签

LLM SDK 升级税:为什么补丁版本更新实际上是一次伪装的模型发布

· 阅读需 11 分钟
Tian Pan
Software Engineer

我上个季度合作的一个团队在周二凌晨 2:14 向生产环境推送了一个回归错误。值班警报触发了,因为其摘要代理(summarization agent)下游的 JSON 解析器以“尾随逗号错误”拒绝了二十分之一的响应。模型没变。提示词(prompt)没变。评估套件在前一天晚上的通过率为 96.4%,稳稳高于 95% 的准入门槛。改变的只是 package.json 中的一行:模型提供商的 SDK 从 4.6.2 升级到了 4.6.3。补丁更新(Patch bump)。由依赖机器人自动合并。发布说明里写着“内部清理”。

所谓的“内部清理”是一个收紧的 JSON 模式解析器,它删除了一个宽容的后备路径,而这个路径此前一直在默默修复模型工具调用输出中反复出现的尾随逗号怪癖。模型的行为没有改变。但 SDK 对该行为的解释改变了。团队的评估套件从未发现这个回归,因为评估套件运行的 SDK 版本与依赖机器人刚刚推送的版本不同。

这就是 LLM SDK 升级税,它是当今生产环境 AI 中最隐蔽、代价最昂贵的故障模式之一。SDK 不是被动的传输工具。它是你提示词行为的积极参与者,而那些在没有评估的情况下升级 SDK 的团队,实际上是在进行一场伪装的模型发布。

编程智能体自主曲线:阅读是免费的,合并是事故级的

· 阅读需 13 分钟
Tian Pan
Software Engineer

关于编程智能体(coding agents)的讨论总是陷入二元对立:自主还是受监督,YOLO 模式还是手握方向盘,--dangerously-skip-permissions 还是“批准每一次按键”。这种构想框架本身就是一个范畴错误。编程智能体执行的并非“一个动作”,而是一系列动作,其成本跨越了至少七个数量级 —— 从读取文件(免费、可撤销、无副作用)到合并至主分支(不通过 revert PR 则不可逆),再到向集群发布二进制文件(六位数成本级别的事故)。用一个自主性开关来处理如此广泛的范围,就像是为停车场和高速公路设置统一的限速一样。

如果团队在发布“无所不能的智能体”时,没有将每个动作映射到其爆炸半径(blast radius),那么只需一个带有提示词注入风险的 GitHub 评论,就足以引发一场事后复盘 —— 事实上,我们已经有了这种失败模式的公开案例。Anthropic 的 Claude Code 安全审查、Google 的 Gemini CLI Action 以及 GitHub Copilot Agent 在 2026 年都被证实可以通过精心设计的 PR 标题和 issue 正文被劫持,研究人员将这种攻击模式命名为“评论并控制”(Comment and Control)。这些智能体并非在抽象意义上损坏了,而是因为自主性层级悄无声息地将低信任输入抹平为“一视同仁”,从而基于这些输入执行了高阶动作(如推送代码、开启 PR)。

接下来需要建立的规范是:针对每个动作的曲线、随层级扩展的闸门、与爆炸等级匹配的回滚速度,以及一个测试工具组合升级而非单一动作失败的评估程序。

当你的 CLI 开始说英语:可提示基础设施的最小权限原则

· 阅读需 13 分钟
Tian Pan
Software Engineer

我本季度交流过的一个平台团队发布了一个封装了 kubectl 并支持英语指令的 Slack 机器人。一名工程师输入了 “清理 staging 中未使用的分支”。这个机器人非常“热心地”删除了 12 个命名空间——其中一个的名字匹配到了子字符串 “branch”,但它恰好托管了移动团队已经使用了一周的长期集成环境。没有任何异常被抛出。机器人发起的每一次调用都是它合法持有的权限。复盘报告无法指出任何违背的访问规则,因为确实没有规则被打破。该机器人完全按照其 IAM 策略允许的操作执行。

Unix 哲学是一种隐藏在审美偏好下的隔离策略。具有窄接口的小型工具意味着任何单个命令的爆炸半径都受到它所接受的谓词和标志 (flags) 的限制。rm -rf 极其危险,因为这是大家的共识;kubectl delete namespace 要求操作者完整输入命名空间名称,而这种手动输入就是一道关卡。最小特权原则之所以容易执行,是因为权限是词法化的:命令的形式告诉了你行动的形式。

随后,封装层开始接受英语。现在,“命令的形式”变成了 LLM 认为它是什么,它就是什么。

系统提示词作为代码、配置或数据:影响全局的架构决策

· 阅读需 13 分钟
Tian Pan
Software Engineer

上个季度我交流过的一个团队发布了一个客户支持智能体,其系统提示词存储在 Postgres 的一行中,每个租户一行。这个方案听起来很合理:企业客户要求定制语气,“让提示词可编辑”是实现这一目标最廉价的方式。六个月后,发生了三件事。评估套件从 200 个案例膨胀到了 11,000 个,因为每个租户的提示词现在都需要自己的回归测试集。提示词更新工作流悄然变成了一个没有审核的写入路径,因为产品负责人被赋予了对表的直接访问权限。此外,由于部署流水线根本不知道提示词发生了变化,一个韩国租户提示词中损坏的 UTF-8 字符导致该租户的聊天机器人下线了两天,却没人察觉。

这些结果都不是需求强制导致的。它们是由一个无人刻意做出的架构决策所强制导致的:系统提示词存放在哪里?在代码中?在配置文件中?还是在数据库行中?团队选择了“数据库”,因为这是实现功能最快的路径,而后果在接下来的几个月里级联影响到了每一个相邻系统。

AI 更新日志问题:为什么你的提示词更新正在破坏其他团队的工作

· 阅读需 13 分钟
Tian Pan
Software Engineer

一个平台团队对他们的摘要服务的系统提示词(system prompt)进行了一行细微的调整。没有代码审查,没有迁移指南,没有版本更新——这“仅仅是一个提示词”。两周后,法律产品团队发现他们的合规自动脱敏功能一直在静默地泄露姓名。调查耗费了一个冲刺(sprint)。修复很简单。损害的是信任。

这是 AI 变更日志问题的缩影。行为现在是你系统的一等输出(first-class output),当提示词、模型、检索器或工具模式(tool schemas)发生变化时,行为也会随之改变——而这些变化都不会出现在消费方应用的 git diff 中。如果团队像对待后端部署那样对待 AI 更新,认为在 #releases 频道发一条 Slack 消息就足够了,那么他们最终会重蹈 2010 年代早期那种“我们先上线,稍后再告诉 QA”工作流的覆辙。

模型迁移类比数据库迁移:如何在不破坏生产环境的情况下安全切换 LLM 供应商

· 阅读需 12 分钟
Tian Pan
Software Engineer

当你的团队决定从 Claude 3.5 Sonnet 升级到 Claude 3.7,或者从 OpenAI 迁移到自托管的 Llama 部署时,直觉通常是将其视为一次库升级:更改 API 密钥,更新模型名称字符串,进行快速的健全性检查,然后发布。这种直觉是错误的,那些遵循这一做法的团队会在第二周的凌晨 2 点发现原因——当时客服代理开始以完全不同的格式生成响应:技术上有效,语义上却是灾难性的。

切换 LLM 提供商或模型版本在结构上与数据库模式迁移(database schema migration)完全相同。两者都涉及更改系统中应用其余部分具有隐式契约的行为。两者可能在第一天看起来没问题,但在第十天发生灾难性的失败。两者都需要双重运行(dual-running)、金丝雀发布(canary deployment)、回滚标准和迁移方案(migration playbook)——而不是修改配置后发一条 Slack 消息。

正确的 Prompt 版本管理:将 LLM 指令视为生产软件

· 阅读需 9 分钟
Tian Pan
Software Engineer

三个词。就这么多。

一个团队在现有 prompt 中添加了三个词,目的是改善"对话流畅性"——这个调整在 playground 里看起来无害。几个小时内,结构化输出错误率急剧攀升,一个创收工作流停止运作,工程师们争相还原 prompt 改动前的内容。没有版本历史,没有回滚机制,只有一条 Slack 消息,来自某个"大致记得"内容的人,以及一份与 Google 文档中过时副本的 diff。

这不是假设场景,而是几乎每个规模化交付 LLM 功能的组织都在重复经历的模式。Prompt 从应用代码中的字符串起步,经过非正式编辑演化,积累了无文档记录的微小调整,最终到达无人确信生产环境里运行着什么、也不知道为何如此表现的状态。

解决方案不是一个新工具,而是对团队一直以配置文件方式对待的东西施加工程纪律。

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

· 阅读需 11 分钟
Tian Pan
Software Engineer

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

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

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

LLM 服务商故障手册:当 AI 基础设施宕机时如何保持服务在线

· 阅读需 13 分钟
Tian Pan
Software Engineer

2024 年 12 月,OpenAI 整个平台宕机超过四个小时。一项新部署的遥测服务配置错误,导致大规模集群中的每个节点同时猛攻 Kubernetes API。DNS 崩溃,控制平面瘫痪,所有服务随之倒下。恢复耗时如此之久,部分原因在于团队缺乏他们后来所说的"破防工具"——那些在常规流程失效时可以立即调用的预建应急机制。

如果那天你正在运营一款 AI 驱动的产品,你必须在压力下快速做出决策。多服务商路由?优雅降级?缓存响应?还是只能祈祷,然后挂出一个状态页面?

这就是你应该在那个电话打来之前就已经写好的应急手册。

提供商抽象税:构建无需重写即可切换模型的 LLM 应用

· 阅读需 12 分钟
Tian Pan
Software Engineer

一家医疗初创公司从某个主流前沿模型迁移到了同一供应商提供的新版本。结果是:为了恢复功能对等(feature parity),耗费了 400+ 个工程小时。新模型每次响应生成的 token 数量是原来的五倍,抵消了预期的成本节省。它开始提供未经请求的诊断建议——这带来了合规性风险。而且它破坏了下游的所有 JSON 解析器,因为它把响应包裹在了 Markdown 代码块语法中。同一供应商,不同的模型,却是推倒重来。

这就是供应商抽象税(provider abstraction tax):它不是切换供应商的成本,而是不为此做规划所产生的累积成本。它不是一次性的迁移事件,而是一个持续的消耗——你在升级三周后发现的行为退化、无法跨模型迁移的提示词工程工作,以及因为某个供应商分别计算输入和输出 token 的速率限制而导致静默失败的重试逻辑。直接在单一供应商之上构建系统的团队会无形中积累这种债务,直到收到弃用通知或价格变动通知时,账单才会一次性结清。

模型 EOL 倒计时:将供应商 LLM 视为外部依赖项管理

· 阅读需 13 分钟
Tian Pan
Software Engineer

2026 年 1 月,OpenAI 仅提前两周通知便将若干 GPT 模型从 ChatGPT 中退役——而就在此前不久,其 CEO 刚刚在公开场合承诺在此次退役后会"提前充分通知"。对于那些已将工作流构建在这些模型之上的团队而言,这份公告无异于周五下午收到的一条页面报警。那一次 API 未受波及,但下一次未必如此。

你当前调用的每一个模型都有弃用日期。部分日期已列在供应商的文档页面上,另一些尚未宣布。操作层面的问题不是你的生产模型是否会被退役,而是你能否在问题发生前及时收到通知并从容应对,还是在用户开始遭遇故障后手忙脚乱地迁移。

Prompt 静态分析:你的 AI 系统缺失的预部署门控

· 阅读需 9 分钟
Tian Pan
Software Engineer

每个严肃的工程团队在合并代码前都会运行一次 Lint 检查。ESLint 捕获未定义的变量,Prettier 强制格式规范,Semgrep 标记安全反模式。没有人会在不先运行至少一次静态检查的情况下将 JavaScript 发布到生产环境。

现在想想你的团队在发布一次提示词变更之前会做什么。如果你的团队和大多数团队一样,答案是:在 PR 里审阅一下,用肉眼扫描,也许手动测试几个输入用例,然后合并。你生产 AI 功能的系统提示词——控制模型如何为每一位用户表现的指令集——所受到的预部署审查比一次 CSS 改动还要少。

这个差距不是一个微小的流程疏漏。一项分析了 2,000 多个开发者提示词的研究发现,超过 10% 的提示词存在提示词注入攻击的漏洞,约 4% 存在可衡量的偏见问题——而这一切都在没有人察觉的情况下部署到了生产环境。自动捕获这些问题的工具已经存在,只是大多数团队还没有把它接入流水线。