跳到主要内容

553 篇博文 含有标签「ai-engineering」

查看所有标签

右缘准确率下降:为什么上下文窗口的最后 20% 是个陷阱

· 阅读需 12 分钟
Tian Pan
Software Engineer

200K token 的上下文窗口并不是真正的 200K token 窗口。将其填满,你刚刚付费使用的模型就会悄然变成一个更糟糕的版本——这种退化并非发生在“迷失在中间(lost in the middle)”所预言的中间位置,而是在右侧边缘,也就是近因偏差(recency bias)本应拯救你的地方。包装盒上的标签卖给你的是余量;而硅片卖给你的却是悬崖。

这是一种大多数团队尚未内化的不同失效模式。“迷失在中间”训练了一代提示词工程师(prompt engineers),让他们习惯于将关键指令放在开头,将关键问题放在结尾,坚信首因效应(primacy)和近因效应(recency)能确保信号得以传递。然而,当利用率接近宣称的窗口极限时,这种启发式方法会悄然失效。这种下降并非逐渐的、线性的,也与模型在半满状态下的表现不对称。一旦超过某个随模型而异的利用率阈值,你就进入了一个不同的运行机制,在 30K 时有效的提示词结构在 180K 时会彻底失败。

经济上的诱惑让情况变得更糟。如果你刚刚为百万 token 的窗口付费,那么使用它的压力是巨大的——你会倾倒整个代码库,喂入每一张支持工单,交给它季度财报,并让它找出重点。结果就是,你会得到一个看似推导严密、实则自信错误的答案,而在审计时它会瞬间瓦解。

橡皮图章式崩溃:为什么 AI 编写的 PR 正在掏空代码审查

· 阅读需 12 分钟
Tian Pan
Software Engineer

一位资深工程师在四分钟内批准了一个 400 行的 PR。diff 很整洁。命名很合理。测试通过。两周后,值班工程师翻阅一个查询时发现,它返回的行形状是对的,但取错了列 —— 本该用 user.created_at 的地方用了 user.updated_at —— 队列分析仪表板已经对 CFO 撒了九天的谎。审查者很称职。代码结构良好。这个 bug 在 diff 中是不可见的,因为它不是语法异味,而是语义问题。审查者无从着力,因为没有人写下这个变更原本打算做什么。

一旦你代码库中的大部分 diff 都源自模型输出,这种失效模式就会出现。审查者不再问“这正确吗?”,而是开始问“这看起来像代码吗?”。答案几乎总是肯定的。AI 编写的代码在语法上极其流畅,这种流畅性绕过了工程师们花费十年时间在人类编写的烂代码上磨练出来的审查启发式规则。

语义缓存是安全隐患,而非性能提升

· 阅读需 14 分钟
Tian Pan
Software Engineer

语义缓存命中是唯一一种能在不到一毫秒的时间内,将错误答案发送给错误用户的 LLM 优化方式。SQL 缓存之所以会返回你或他人的数据行,是因为有人写错了 join —— 这种故障模式属于查询 bug。而语义缓存返回另一个租户的响应,是因为两个 embedding 在 0.03 的余弦距离内落到了一起,这正是系统完全按设计运行的结果。缓存完成了它的工作,问题在于这份工作本身。

大多数团队将语义缓存作为一种成本方案来推行 —— 每个 AI 工程 Slack 频道里都流传着一份“削减 70% 账单”的 PPT —— 并且像对待 Redis TTL 一样审查缓存键(cache key):完全不审。这种审查通常交由性能团队负责。安全团队永远看不到设计文档,因为没有人会为“我们增加了一条更快的路径”提交安全审查。六个月后,某人的合规审计发现,“我无法登录我的账户,我的电子邮件是 [email protected]”和“我无法登录我的账户,我的电子邮件是 [email protected]”在向量化后都处于“我无法登录我的账户”的阈值内,于是缓存愉快地向 Bob 提供了原本为 Jane 生成的响应,其中包含了她账户请求的密码重置链接。

这篇文章将讨论为什么语义缓存值得拥有与 SQL 谓词相同的审查严谨性、如何通过缓存键设计从结构上防止跨用户泄露,以及你需要什么样的审计追踪来区分“缓存命中提供了正确答案”与“缓存命中在亚毫秒级延迟下提供了他人的答案”。

发布并固定版本之陷阱:模型版本的稳定性如何演变为弃用技术债

· 阅读需 11 分钟
Tian Pan
Software Engineer

在生产环境中固定(Pinning)模型版本感觉像是一种工程纪律。你将 claude-opus-4-0gpt-4o-2024-08-06 锁定到配置中,在 README 中写下原因,然后继续交付功能。输出分布不再发生偏移,评估(Evals)保持绿色,你上个季度做的提示词调优也依然有效。但实际上,你已经启动了一个静默计时器。十二到十五个月后,弃用通知邮件随之而来,三个冲刺周期(Sprint)的未记录行为依赖——提示词调优、评估校准、输出形状假设、温度特征(Temperature Quirks)——都会在瞬间到期结算。

这就是“交付即固定”(Ship-and-Pin)陷阱。从短期来看,固定版本是正确的,但从长期来看,它却是灾难性的,因为稳定性的成本会在你忽略的地方不断复利。一年前“足够好”的提示词,现在正以无人记录的方式承载着关键逻辑。你的下游服务所期望的 JSON Schema 是根据某个模型的分词习惯塑造的。你手动调优的少样本示例(Few-shot Examples)是针对特定模型对“有用性”的认知而优化的。当提供商停用该版本字符串时,这些依赖关系都不会自动迁移,而重新验证它们的工作总是在最后期限的压力下到来。

合成偏好陷阱:AI 排序的 RLHF 如何让你的模型悄然漂移到“老师”的口吻中

· 阅读需 15 分钟
Tian Pan
Software Engineer

第一个迹象几乎总是相同的:你的内部评估仪表盘显示一片绿色,奖励模型(reward-model)分数正在攀升,DPO 损失趋势向好——而一位 Zoom 会议上的客户耸耸肩说:“它现在听起来像 ChatGPT。”训练团队中没有人想听到这样的话。评估结果显示模型更好了。交付上一批偏好数据的标注员也说模型更好了。但用户告诉你的是真话,而仪表盘在撒谎。出问题的并不是某一个标签。出问题的是你的偏好数据不再属于你了。

这就是合成偏好陷阱。标注预算被压缩,有人提议使用一个更强大的模型来对第二个模型的补全结果进行排序,实验发布了,在一段时间内,这看起来像是一顿免费的午餐。学生模型在每一轮对话中都学着听起来更像老师,而且由于你的奖励模型是基于受老师影响的数据训练的,你的奖励模型会欣然表示同意。用户看到的产品读起来和任何其他基于相同前沿 API 构建的产品完全一样。你原以为通过微调买到的差异化,已经在不知不觉中被蒸馏掉了。

你的工具描述是提示词,而非 API 文档

· 阅读需 12 分钟
Tian Pan
Software Engineer

工具描述不是文档。它是模型在每一轮对话中都会读取的 prompt,用于决定该工具是否触发以及如何触发。你不是在为对接该工具的开发者编写内容——开发者已经在 PR 中看到了 schema、类型和示例。你是在为一个从未见过这个代码库的随机读者编写内容,它在同一个上下文窗口中还拿着另外二十个工具描述,并且必须在下一次前向传播中选出一个。

大多数团队并没有意识到这一点。他们把 OpenAPI 摘要粘贴到 description 字段中,把 JSON Schema 贴在下面,然后就发布了。结果,agent 调用工具的次数过少,或者自信地调用了错误的邻近工具,又或者用了任何读过 schema 的人类都会觉得“显而易见”是错误的参数来调用正确的工具。团队责备模型,但模型读取的正是一字不差的你写的内容。

验证器陷阱:事后防御如何从内部腐蚀你的提示词

· 阅读需 10 分钟
Tian Pan
Software Engineer

第一次验证器捕捉到糟糕的 LLM 输出时,感觉像是一场胜利。第二次,你会调整提示词以降低失败的可能性。到第二十次时,团队中没人能解释为什么提示词中存在那三个段落 —— 它们是早已被遗忘的事故留下的瘢痕组织,而模型在阅读警告上花费的 Token 比推理实际任务还要多。

这就是验证器陷阱。你添加的每一个事后防护(post-hoc guard)—— JSON 模式检查、正则表达式、内容分类器、第二个作为裁判的 LLM —— 都会对上游提示词施加反馈压力。提示词会增加防御性指令来安抚验证器,验证器反过来又会捕捉到一类新的失败,接着你又会添加更多指令。每一次迭代在局部看来都是合理且明智的。但总体而言,系统变得越来越慢、越来越贵,而且在原本设计的任务上的表现也明显变差了。

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

· 阅读需 13 分钟
Tian Pan
Software Engineer

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

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

在写第一个 Prompt 之前,先设计好你的 Agent 状态机

· 阅读需 11 分钟
Tian Pan
Software Engineer

大多数工程师在构建第一个 LLM agent 时,都会遵循相同的流程:写一个系统提示词,添加一个调用模型的循环,撒上一些工具调用逻辑,然后看着它在简单的测试用例上运行。六周后,这个 agent 变成了一团难以理解的嵌套条件、粘贴在 f-string 里的 prompt 片段,以及散落在三个文件中的重试逻辑。添加一个功能需要通读整个代码。遇到生产 bug 就得盯着一个上千 token 的上下文窗口,试图重建模型当时在"想"什么。

这就是"意大利面式 agent"问题,在以 prompt 为起点而非设计为起点的团队中几乎普遍存在。解决方案不是更好的提示技巧,也不是换一个框架,而是一种纪律:在写第一个 prompt 之前,先设计好状态机

归因鸿沟:如何将用户投诉追溯到具体的模型决策

· 阅读需 13 分钟
Tian Pan
Software Engineer

一张支持工单送达:「你们的 AI 对我的保险条款给出了完全错误的建议。」你查看日志,找到了时间戳和用户 ID,最终模型响应也原文呈现在那里。但你根本不知道是哪个提示词版本产生了这条输出、检索步骤取回了哪些上下文片段、中间是否调用过工具,也不知道你过去一个月部署的三个模型版本中究竟是哪个处理了这个请求。你能读到输出,却无法解释它。

这就是归因鸿沟——大多数 AI 团队在首次上线模型功能后六到十八个月都会撞上这道墙。问题不在模型或提示词,而在可观测性基础设施。传统日志记录的是请求-响应对,而 LLM 流水线并非请求-响应对,它是一棵决策树:上下文检索、提示词组装、可选工具调用、模型推理、后处理、条件分支。出现问题时,你需要看到完整的树,而不仅仅是叶子节点。

AI 代码审查实践:自动化 PR 分析真正能发现什么,又持续遗漏什么

· 阅读需 10 分钟
Tian Pan
Software Engineer

47% 的专业开发者现在使用 AI 代码审查工具——两年前这一比例仅为 22%。然而在同一时期,AI 协作编写的 PR 合并后产生的 Bug 数量是人工编写代码的 1.7 倍,整个行业的变更失败率上升了 30%。团队在部署这些工具时出了问题,而问题并非工具本身。

核心问题在于工程师在没有理解 AI 审查能力边界的情况下就将其引入工作流。这类系统在真实代码库上的效果上限为 50–60%,只擅长一小类表层问题,而恰恰在导致生产事故的错误上静默失败。将 AI 审查视为通用质量关卡的团队,得到的是虚假的信心,而非真正的覆盖。

为什么 AI 功能开关不同于普通功能开关

· 阅读需 12 分钟
Tian Pan
Software Engineer

金丝雀部署完美收工:错误率纹丝不动,延迟没有飙升,监控大盘一片绿色。你将新模型全量推送给所有流量——三周后,客服队列里挤满了用户投诉,说 AI "感觉不对劲"、"不再有用了"。

这正是将传统功能开关机制套用到 AI 系统上的核心问题。一个模型可以在"没有崩溃"的情况下悄悄退化:它照常返回 200 状态码,以正常速度生成 token,输出的文本也能通过表面校验——但与此同时,它的幻觉频率在悄悄上升,回答越来越简短或回避,或者在你的用户真正依赖的细微推理模式上悄然退步。你多年来一直监控的遥测指标,从来就不是为了捕捉这类故障而设计的。