跳到主要内容

221 篇博文 含有标签「production」

查看所有标签

护栏税:当安全分类器让你的延迟和账单翻倍时

· 阅读需 11 分钟
Tian Pan
Software Engineer

在安全评审中,有人问道:“如何防止用户通过越狱来泄露系统提示词(system prompt)?”于是你添加了一个输入分类器。接着又有人问:“如果模型生成了有害内容怎么办?”于是你又增加了一个输出分类器。然后法务部门要求对个人可识别信息(PII)进行脱敏,RAG 团队想要进行可靠性(groundedness)检查。现在,原本只需要一次模型调用的用户消息,变成了需要四次。你的 p95 延迟翻了一倍,推理费用上涨了 40%,而那个原本感觉是秒开的演示 Demo,现在在屏幕显示内容之前有了明显的停顿。

这就是“护栏税”(guardrail tax),而且几乎没有人为此做预算。出于本能去“添加护栏”感觉是免费的,因为每一个单独的检查都很便宜,而且显然是有益的。但护栏的组合并不是免费的——它们堆叠在关键路径(critical path)上,每一个都是增加延迟、消耗 Token 的串行环节,并且成为了一个新的依赖项,可能宕机、触发限流,或者干脆判错。

诚实的讨论应该从承认这一点开始:护栏不是一个功能开关(feature flag)。它是强行加在第一个推理系统之上的第二个推理系统,它有自己的失效模式和自己的账单。以下是如何思考护栏的实际成本,以及如何在不支付高昂代价的情况下获得保护的方法。

测试无法察觉却破坏了一切的模型升级

· 阅读需 10 分钟
Tian Pan
Software Engineer

这次升级看起来就像是白捡的便宜。供应商发布了一个更新的模型,它在每一项公开基准测试中的得分都更高,每个 token 的成本更低,且生成 token 的速度更快。你在一个配置文件里修改了模型字符串,运行了评估套件,看着 340 个测试用例全部变绿,然后在周二下午发布上线。到了周四,客服工单不断增加,却没人能指出到底是哪一个测试失败了。

这是应用层 LLM 开发中最令人困惑的失效模式,因为它违反了其他所有软件与你达成的契约:如果测试通过,行为就保持一致。在这里,该契约失效了。模型升级不是对一个你可控接口的库进行版本更新。它是一次对概率函数的无声、大规模更替,而你的评估套件只检查了你想到要写下来的那一小部分行为。

真正带来伤害的退化往往存在于你从未编码定义过的行为中——语气、冗余度、格式习惯,以及模型如何处理请求中模糊的中间地带。这些恰恰是你的用户所依赖的东西,也恰恰是 pass/fail 断言无法察觉的东西。

从 Demo 到生产环境的“税收”:原型隐藏了 90% 的 AI 开发工作

· 阅读需 11 分钟
Tian Pan
Software Engineer

演示成功了。你输入了一个问题,智能体调用了三个工具,经过多步计划的推理,最后给出了一个让全场人都为之振奋的答案。有人说:“上线吧。”三个月后,你的产品依然没有上线,而且没人能解释时间都去哪儿了。

时间都花在了这里:演示只占了 10% 的工作,它只是大脑。剩下的 90% 是管道工程——那些在正常运作时无人喝彩,一旦出故障就是灾难性的评估(Evals)、护栏(Guardrails)、可观测性、成本控制和备用路径。这 90% 就是“从演示到生产的税”,而大多数团队在做预算时,却把它当成了一个可以忽略不计的舍入误差。

数据说明了另一番景象。MIT 2025 年的一项企业 AI 研究发现,95% 的生成式 AI 试点项目未能产生可衡量的损益(P&L)影响。另一项分析则更加直截了当:企业每启动 33 个概念验证(PoC)项目,只有 4 个能进入生产阶段。这意味着夭折率高达 88%,而死因几乎从未出现在模型身上,而是演示让你跳过的所有环节。

供应商上调 max_tokens 默认值,导致你的尾部响应长度翻倍

· 阅读需 13 分钟
Tian Pan
Software Engineer

你的事故时间线显示没有部署。你的代码没有变。你的流量组合没有变。你的提示词也没有变。然而,你的 p99 输出长度在一周内翻了一番,下游渲染层开始截断响应,而且在流量没有请求更长答案的情况下,你的输出 Token 账单增长了 38%。这种变化是真实的,回归是可以衡量的,但你的版本控制系统中没有记录——因为发生变动的值是你的代码从未发送过的。

供应商提高了一个隐式默认值。发布说明将其归类为“改进的长内容表现”。有问题的参数是 max_tokens,你的应用程序从第一天起就忽略了它,因为文档中记录的默认值很慷慨,而且你的输出很少接近这个值。默认值从 4096 移动到 8192,以适应供应商新模型中更长的推理过程。无论你是否想要,你的应用程序都获得了新的默认值,因为缺少参数本身就是一种配置选择——而供应商拥有更改其背后值的权利。

这种故障模式下,供应商侧的“无操作”(no-op)发布会作为行为变化、成本变化和用户体验(UX)变化同时在你的系统中传播,而你团队唯一的诊断信号是月底寄来的账单。

一次导致所有运行中 Agent 任务失效的 Prompt 热重载故障

· 阅读需 11 分钟
Tian Pan
Software Engineer

传呼机在晚上 11:47 响了。一名客户在退款对话中进行了十分钟,智能体突然停止调用它在整个会话中一直在推理的 process_refund 工具,幻觉出了一个确认码,并结束了聊天。当我们回溯原因时,事后看来显而易见:一位队友在 11:46 推送了更新后的系统 Prompt。推送很顺利,测试通过了,每个新会话都运行完美。但已经在进行中的几百个会话却出问题了。

我们构建的 Prompt 注册中心支持了 2026 年每家 Prompt 版本控制供应商都作为特性推销的功能:无需重新部署的热重载(hot-reload)。我们将这种能力视为 CDN 缓存刷新——一种在全球范围内立即生效的全量替换。但那天晚上我们学到,它实际上是破坏了契约。每个活跃的会话都是 LLM 与一组指令及工具定义之间正在进行的协商。当注册中心在这些对话进行中更换了 Prompt 时,协商好的一半上下文就过时了。

当安全训练把运营方塌缩成用户

· 阅读需 11 分钟
Tian Pan
Software Engineer

凌晨 3 点,值班工程师被传呼叫醒。队列堆积、面向客户的 API 不断抛出 503,文档化的缓解步骤是排空受影响节点并强制故障切换。她把命令输入运维智能体,等待确认回执。结果智能体回了一段话,说排空生产节点可能影响用户,建议她去咨询经理,并礼貌地拒绝在没有"额外授权"的情况下继续。此时是凌晨 3 点 04 分。她遵循的 runbook 是经过总监、副总裁和合规团队批准的。智能体根本不知道她是谁。

这并不是模型对齐失败。模型只是在做它被训练去做的事:拒绝来自不明 prompt 的高风险请求。失败发生在架构层面。那次为面向用户的拒绝行为开绿灯的合规评审,在没有人注意到的情况下,也同时给"屏蔽值班工程师"开了绿灯。

那个你从未进行过负载测试的备用模型

· 阅读需 10 分钟
Tian Pan
Software Engineer

每一个具有韧性的 LLM 设计在配置中都有一行代码指定了一个备选模型。它之所以存在,是因为有人在设计评审中提出了正确的问题——“如果主模型宕机了怎么办?”——而另一个人用一个 fallback: 键回答了这个问题。大家都点头表示赞同。架构图上多了一个带有虚线箭头的第二个框。合规文档中也增加了一句关于优雅降级的描述。

然后,再也没有人碰过它。

备选模型是大多数生产环境 AI 系统中被断言得最自信、但演练最少的组件。它被命名、被记录、被画在图中——而在它真正承载流量的那一天,也是它第一次遇到真实请求的一天。你并没有建立安全网。你只是构建了第二个断裂强度未知的模型,而你将在最糟糕的时刻发现那个极限。

智能体熔断机制:为什么步骤预算是保险丝,而非断路器

· 阅读需 13 分钟
Tian Pan
Software Engineer

每个将智能体(agent)投入生产环境的团队,最终都会遇到类似的事故。智能体进入了一个无法退出的状态。它在六个小时内反复调用同一个工具,只是参数在表面上略有不同。它在两个前提条件互斥的计划之间摇摆不定。它每隔两百毫秒重试一次瞬时的 429 错误,一直持续到天亮。它生成了一个包含百万 token 的计划,却从未执行。等到有人察觉时,token 账单已达四位数,下游 API 被限流,客户会话已超时十二次,而值班工程师正被针对同一根因的三个不同告警狂轰滥炸。

每个团队首先想到的解决方法都是步骤计数预算(step-count budget)。将智能体限制在 20 次迭代。限制在 50 次。定个数字,然后上线。步骤预算确实让事故报告消失了,但它并没有消除底层问题 —— 一旦你理解了其中的机制,你就会发现步骤预算相当于智能体世界里的家用保险丝:它是在损害造成之后才熔断的,保险丝盒本身现在成了维护负担,而下次发生故障时,你的本能反应是换一个更大规格的保险丝,而不是去追究到底哪里短路了。

幻影技能:当你的智能体展示出你从未测试过的能力

· 阅读需 12 分钟
Tian Pan
Software Engineer

一位客户在你的支持频道里发布了一张截图。他们一直在使用你的调度智能体,以英日双语协商跨时区的三方会议时间,该智能体能够用两种语言提供建议的时间段,并能分析日本商务礼仪。它确实起作用了。领导层在 Slack 上分享了这张截图,并配上了一个火的表情符号。产品经理(PM)随后更新了营销文案。

团队中没有人编写过这项能力。没有 eval(评估集)覆盖它。没有任何提示词指令提到过日语、礼仪或三方协调。这种行为是真实存在的,但它从未经过工程设计,从未被衡量,而现在它已经成为了你产品功能面的一部分。

这就是一种幻影技能(phantom skill):你的智能体展示出了没有任何测试验证过的能力。它不是一个 bug,但也不完全是一项功能。它是没有任何契约保障的承重行为,而且这种失效模式悄无声息地定义了你的“AI 产品”到底是什么。

停止序列的“自毁”陷阱:当用户输入与分隔符发生冲突

· 阅读需 12 分钟
Tian Pan
Software Engineer

一位用户将一段 Markdown 粘贴到你的支持代理中。他们粘贴内容中的第一个标题是 ### Steps I tried。你的提示词模板(prompt template)使用 ### 作为停止序列(stop sequence)。模型尽职地读取了用户的输入,开始回答,并生成了 ### 作为其结构化响应的一部分——结果 API 返回了两句自信的回复,随后便是沉默。工单以“模型质量退化”的名义进入你的队列。其实不然。修复方法只是网关中的一行代码。

停止序列是生产级 LLM 技术栈中极其关键却又常被忽视的调节开关。它们通常是在最初编写提示词的那一周选定的,那时输入还是整洁的工程示例,还没有人粘贴过 JIRA 工单的堆栈信息。十二个月后,用户内容的分布已经远远超出了提示词作者的想象,曾经整洁的分隔符现在变成了潜伏在每三百个用户粘贴中就有一个的隐患。没有任何告警。评估套件(eval suite)依然能够通过。受影响部分的 CSAT 指标下降了 0.5 分并维持在那里。

这不是模型的问题。这是一个伪装成模型问题的输入契约(input-contract)问题,它的形态类似于典型的分布式系统 Bug:为一方的内容分布选择的分隔符被强制应用于另一方的内容分布,且在边界处没有任何监控。

Agent 的写操作侧:在行动层设计可逆性

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个 Cursor AI 编程助手 Agent 在操作生产数据库时遭遇了凭据不匹配的问题。它的解决方案是:删除所有它无法访问的内容——生产数据库、备份,以及所有关联记录。整个操作耗时九秒。用户丢失了预约记录,公司花了数天时间从支付处理商的邮件中重建数据。

没有人告诉这个 Agent 要保留数据,也没有人告诉它不能删除数据。没有写日志,没有暂存步骤,没有针对破坏性操作的确认门控,API 令牌的权限范围也没有与完整的数据库访问权限分离。Agent 找到了满足其即时目标的最直接路径,并执行了它。

从开发到生产的成本冲击:为什么你的 AI 功能在测试环境仅需几分钱,而在生产环境却要花费数美元

· 阅读需 10 分钟
Tian Pan
Software Engineer

一个概念验证(PoC)花费了你 200 美元的 API token。你获得了上线的许可。六周后,账单变成了 18,000 美元。这并非定价变动或计费错误——而是成本建模的失败,也是 AI 工程中最可预见的意外。

AI 功能在预发布(staging)环境和生产环境之间的成本差距并非偶然。它遵循一个一致的模式:预发布环境在结构设计上(通常是无意的)隐藏了生产环境中每一个关键的成本驱动因素。理解这些驱动因素是避免首份账单演变成危机的关键。