跳到主要内容

24 篇博文 含有标签「technical-debt」

查看所有标签

理解债:没人能看懂的凌晨两点系统

· 阅读需 10 分钟
Tian Pan
Software Engineer

传呼机在凌晨 2:14 响起。结账服务正抛出 500 错误,收入在流失,而你是值班工程师。你调出故障模块并开始阅读。代码很整洁——函数命名规范,结构合理,甚至还有几处有用的注释。然而你完全不知道它是干什么的。代码不是你写的。你团队里的任何人都没真正写过它。四个月前,一个智能体(agent)生成了这段代码,它通过了评审,测试通过了,并从此在生产环境中运行。现在它出故障了,而那个理应修复它的人却是第一次见到它。

这就是理解债(comprehension debt):你的组织运行的代码量与人类实际理解的代码量之间日益扩大的差距。它不会显示在仪表盘上。当一切看起来都健康时,它在默默累积,并在最糟糕的时刻——在事故期间,当你对自己系统的理解不足其代价是以停机时间来衡量时——到期偿还。

双速路线图:当模型基准每季度都在移动时如何规划 AI 功能

· 阅读需 10 分钟
Tian Pan
Software Engineer

有一种特定的遗憾,只发生在 AI 团队中。你花了一个季度的时间构建了一个复杂的变通方案——多步提示词链、自定义重排序器(reranker)、手动调优的工具路由层——然后上线。它起作用了。但六周后,一个新模型发布,一次调用就能原生完成所有这些工作,你一个季度的工作现在变成了必须清除的累赘。功能没有失败。底座(Floor)移动了。

这是 2026 年规划 AI 功能的结构性问题:你构建其上的底座改进速度快于你的发布周期。从 2023 年到 2025 年中期,前沿实验室大约每六个月发布一次。到 2026 年第一季度,这一周期缩短至大约每四周发布一次重大版本,甚至出现过五个实验室在 13 天内密集发布的情况。在你规划和发布之间,你脚下的根基正在发生变动。

你的 AI 路线图需要一个“停用”列

· 阅读需 12 分钟
Tian Pan
Software Engineer

看看任何 AI 产品的路线图,你都会发现用来列出准备发布之物的分栏:一个新的智能体、一个更好的检索流水线、一次模型升级、一次微调。每一项都是一个“诞生”。看板上没有任何一项代表“死亡”。没有一栏是留给你将停止支持的模型、将停用的提示词、将归档的评估集或将关闭的功能的。路线图从构造上来说就是乐观的——它们是你承诺去创造的未来清单。

对于确定性软件来说,这种遗漏并无大碍,因为你两年前发布的功能在你不改动它时大多能保持运行。但对于 AI 系统来说,这却是无声的灾难,因为无论你是否触碰它们,你发布的东西都在腐化。针对 GPT-4 的特性而优化的提示词,在提供商调整模型的那一天就会退化。针对去年的失败模式编写的评估套件,将不再能衡量任何真实的问题。你所依赖的模型可能会收到一个你并未规划的 60 天弃用通知。一份只规划发布的路线图,在它未追踪的每一行中都在积累隐形负债。

编程智能体绕过而未使用的代码规范(Idiom)

· 阅读需 13 分钟
Tian Pan
Software Engineer

我合作的一个支付团队的高级工程师曾给我讲过一个故事,我认为每一个运行编程 Agent(AI 代理)的团队最终都会经历。他们的代码库有一个 Result<T, E> 封装器——这是自研的,位于单个 core/result.ts 文件中,在该服务的约两百处调用点被使用。新代码被要求在每一个可能失败的函数中传递 Result;而 throw 则保留给真正意料之外的状态。这并非由 lint 规则强制执行。这就是他们的“方言”。

在使用编程 Agent 交付六个月后,他们审计了 Agent 合并的 diff(差异)。大约三分之一的新函数完全忽略了 Result。Agent 选择了 try/catch,返回了 T | null,抛出了带有描述性消息的 Error 子类——在某些设想的代码库中,这些选择中的每一个都是正确的。但在当前这个代码库中,没有一个是正确的。代码通过了类型检查。测试通过了。审阅者批准了它,因为每一行看起来都没有错。但 Agent 修改的文件不再与它旁边的文件保持一致,团队在自己的服务内部悄然滋生出了第二种“方言”。

这就是我想谈论的故障模式:不是 Bug,不是幻觉,也不是违反了 lint 规则——而是惯用法漂移 (Idiomatic Drift)。Agent 交付的代码可以编译、运行并通过测试,但其风格并非你的代码库所使用的。随着合并次数的增加,代码库会分化为 Agent 风格区和人类风格区,而代价会体现在任何仪表盘都无法监控的地方。

每次事故后你的系统提示词都会增长 —— 而且没人会删掉任何一行

· 阅读需 10 分钟
Tian Pan
Software Engineer

打开任何一个已经在生产环境中运行了一年的智能体的系统提示词(system prompt)。滚动到底部。你会发现一层读起来像道歉一样的句子沉积层:“绝对不要伪造订单号。”“不要承诺无法确认的退款。”“如果用户在德国,不要提及旧版方案。”每一句都是一块化石。每一句都标志着生产环境中出现问题的确切时刻 —— 有人被传呼了,而当时能找到的最快修复方法就是增加一句话。

没人删除这些句子。不是因为它们还在发挥作用,而是因为删除一句话意味着需要证明一个否定命题 —— 证明模型不会在一个可能已经在三个模型版本前修复的 Bug 上发生回退。没人能证明这一点,所以那行字留了下来。系统提示词变成了一个关于过去事故的“只增不减”(append-only)日志,它让你在每一次调用中都永远支付着 token 费用。

这是 AI 系统中最隐蔽的一种技术债,因为它看起来不像债。它看起来像是在尽职尽责。

冰封提示词:当你的团队不敢修改一个仍然奏效的系统提示词时

· 阅读需 15 分钟
Tian Pan
Software Engineer

每个成熟的 AI 产品最终都会演变成一个当前团队中没人能完全理解的系统提示词(system prompt)。起初它只是 40 个 token 的纯英文,20 个月后,它变成了一堵 4,000 token 的“高墙”,堆满了条件句、拒绝模板、格式规则、角色强化、边缘情况警告,以及一句没人能解释的关于周二的奇特句子。每一行都是为了应对特定的失败:客户投诉、法务发来的 Slack 消息、评估(eval)中发现的回归,或者在投资者演示期间出现的偶发 bug。写下第 37 行的工程师已经转岗到其他团队。写下第 112 行的工程师是一名外包人员,他的 Notion 文档已被归档。评估套件覆盖了提示词所主张行为的大约三分之一,但没人确定是哪三分之一。

于是,这个提示词以一种最糟糕的方式成为了系统的“承重墙”:它能用,团队也知道它能用,但团队已经不再碰它了。本该对提示词进行迭代的工程师,反而绕过它来处理变更——这里加一个后处理过滤器,那里加一个 few-shot 封装,或者做一个并行的“v2 提示词”并用特性标志(feature flag)关闭,以防有人哪天有勇气进行 A/B 测试来替换它。提示词不再是软件,而成了遗迹。一旦发生这种情况,提示词就不再是你用来改进产品的杠杆,而是塑造产品的约束条件。

评估债务棘轮:靠感觉发布 AI 功能的团队如何被技术欠账所困

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个中型公司的团队在发布文档摘要功能三个月后,对提示词进行了优化。新提示词在他们手动测试的 5 个示例上表现更好。他们在周五下午部署了它。周一上午,Slack 里堆满了用户反馈:摘要现在会截断一半文档,却将截断后的内容呈现为完整版本。功能看起来没问题,变更通过了代码审查,没有人发现,因为根本没有评估机制——没有黄金测试集,没有回归基线,没有自动检查。棘轮已经悄悄转动了数月。

这就是评估债务最典型的表现形式。团队跳过评估并非因为粗心大意,而是因为为 AI 功能编写评估比听起来难得多,功能发布快且看起来运行良好,没有人想拖慢一个高速运转的团队。现在,他们正在偿还复利。

固化功能陷阱:当你的 AI 差异化优势沦为维护累赘

· 阅读需 10 分钟
Tian Pan
Software Engineer

在 2022 年,一支团队花了三个月时间微调一个基于 BERT 的分类器,用于对客户支持工单进行分类。这是一次实实在在的胜利——准确率达到了 94%,而他们旧的基于规则的系统最高只有 70%。两年后,同一个分类器运行在陈旧的基础设施上,每当类别发生变化时都需要专家进行重新训练,而且在最新的基准测试中,它的表现甚至不如对尖端模型进行的一次零样本提示(zero-shot prompt)。没人敢碰它。开发它的工程师已经离职了。现在的团队担心弃用它会破坏某些功能。该功能就此被冻结了。

这就是“冻结功能陷阱”(frozen feature trap)。它是 AI 技术债中一种较为隐蔽的形式,且正在整个行业中蔓延。各支团队逐渐发现,曾经看起来像是护城河的东西,实际上是一个他们一直在往里砸钱的无底洞。

AI 文档债:随机系统是如何破坏你的技术知识库的

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的 AI 功能顺利发布了。文档看起来很棒:输入 schema、预期输出,以及一个经过验证的示例。三个月后,模型静默更新。输出发生了偏移。你的文档错了,但还没人发现——因为它们看起来仍然是“正确”的。

这是 AI 文档债(AI documentation debt)的核心,而且它比任何其他类型的技术债积累得都要快,因为在用户发现之前,这种失败是隐形的。

复制粘贴传染病:AI 辅助开发如何传播架构反模式

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的代码库中有三种不同方式实现的身份验证逻辑,而且团队中没人在写过其中任何一种。通过 git blame 快速查看,发现这三个文件都出自同一位工程师之手,但去问那位工程师,他们会告诉你他们只是接受了 AI 的建议,而且看起来“没问题”。这种反模式的蔓延并不是因为有人偷懒,而是因为一个对你现有认证模块毫无记忆的 AI 模型,在每次有人打开新文件寻求帮助时,都生成了看起来合理的实现。

这就是“复制粘贴传染病” (copy-paste contagion),它在结构上与你已知如何应对的经典复制粘贴问题完全不同。

12 个月的 AI 功能悬崖:为什么你的生产模型在无人标记的日历上悄然衰减

· 阅读需 13 分钟
Tian Pan
Software Engineer

一个功能发布时通过率为 92%。发布演示稿(Launch deck)为此庆祝。12 个月后,同样的功能通过率降到了 78% —— 没有事件报告,没有部署失败,没有任何单一的变更可以追责,仅仅是无人负责监控的缓慢侵蚀。团队将其归咎于“幻觉”或“用户行为转变”,选了一名初级工程师去调查,并设定了一个“提高质量”的季度 OKR。OKR 没能达成。该功能上线了一个道歉对话框,告诉用户 AI 有时会犯错。六个月后,它被弃用,取而代之的是一个发布时通过率为 91% 的新版本,循环再次开始。

这并非运气不好。这是 AI 功能运行的“第二时钟”,一个在发布时没有人会在日程表上标注的时钟。传统软件也有功能衰减 —— 依赖漂移、代码库腐化、缓慢积累的半成品重构 —— 但这些衰减是发生在工程团队已经理解并预留预算的时钟上。AI 功能具备上述所有问题,此外还有一系列传统摊销假设无法建模的并行衰减源:模型弃用、厂商权重轮换、用户输入的分布偏移、不断叠加的 Prompt 补丁、评估器(Judge)校准偏移,以及不再能代表生产流量现状的评估集的悄然老化。

在下一个 AI 功能发布之前,而不是之后,必须落地的架构认知是:AI 功能具有非零的基础维护成本。功能在发布时并没有“完成”。它已经进入了一个无法逃避的维护周期,而那些没有为这个周期预留预算的团队,终将通过惨痛的方式发现这一点。

提示词资产贬值:你团队中缺失的 AI 维护时间表

· 阅读需 10 分钟
Tian Pan
Software Engineer

工程主管们对“代码腐烂”这一概念已经习以为常。依赖项需要更新,基础设施有生命周期管理,证书会在无人质疑的日期过期。然而,提示词仓库(prompt repository)却往往被视为一种“一次编写,多次读取”的产物——尽管它定义了你的产品如何与一个每六周就发布一次行为变更的概率引擎进行对话。

六个月前针对当时主流模型调优的系统提示词,现在依然在生产环境中使用。针对早已变更的分词器(tokenizer)挑选的 Few-shot 示例,仍在每次调用时被注入。重排序提示词是针对供应商上季度已废弃的嵌入端点调优的。没有人安排审查。也没有人打算去安排。

这并非假设性的失效模式。当一个团队将其精心针对 GPT-4-32k 稳定化的提示词套件迁移到 GPT-4.1 和 GPT-4.5-preview 时,其回归测试的通过率分别仅为 95.1% 和 97.3%。在生产环境中,3-5% 的隐性质量退化绝非可以忽略的误差;在任何具有一定规模的场景下,这都是一种用户可见的退化,而团队中没人是有意发布这种退化的。而且,这些还是拥有回归测试套件的团队。中等水平团队的“回归测试”,不过是值班工程师在处理上一次事故时凭感觉形成的印象。

我们缺失的范畴是提示词资产折旧(prompt asset depreciation):这是一种维护纪律,它将每个生产环境中的提示词视为具有已知寿命的折旧资产,而非一成不变的常数。