跳到主要内容

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

· 阅读需 11 分钟
Tian Pan
Software Engineer

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

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

传统技术文档建立在一个基本假设之上:确定性行为(deterministic behavior)。同一个输入运行一千次,产生相同的输出。这个假设让你敢写下“返回一个带有字段 X 的 JSON 对象”,并相信到下个季度这依然成立。这就是 API 参考文档发挥作用的原因。

基于 LLM 的系统摧毁了这个假设。同一个提示词(prompt)运行一千次,产生的是一组输出分布——而不是一个单一的值。模型更新会静默地改变这个分布。上下文窗口(context window)的填充会以任何规范中都未记载的方式降低指令保真度(instruction fidelity)。而真正塑造输出行为的训练数据,几乎从未在功能文档中被记录。

结果就是,文档层的腐烂速度比团队以前处理过的任何东西都快,且方式完全不同。

为什么传统文档变成了虚假保证

当你为确定性系统编写文档时,最难的部分是做到完整。当你为概率系统(probabilistic system)编写文档时,最难的部分是不要意外撒谎。

想想当团队为 LLM 功能编写 API 风格的文档时会发生什么:“提交支持工单摘要 → 返回一个结构化的 JSON 对象,包含字段:issue_category、priority 和 recommended_action。”这句话在你写下的那天是准确的。它描述了该功能在大多数情况下的表现。但它隐藏了几个虚假保证:

  • “返回”暗示它总是会返回,而不是它在大多数情况下返回,偶尔会出现幻觉字段或格式偏差
  • “结构化 JSON”暗示结构是稳定的,而不是它在特定的提示词模式或上下文窗口压力下会退化
  • 输出 schema 并没有说明 priority 值的分布——是偏高,还是在模型更新后这种偏向发生了变化

当一名新工程师阅读这份文档时,他们会编写期望确定性 JSON 的代码。当模型产生格式错误的响应时,失败在生产环境中表现为解析错误,而不是文档问题。文档在技术上一直是诚实的,但在结构上具有误导性。

对 Hugging Face 上超过 32,000 个模型卡片(model cards)的分析发现,只有不到 18% 包含任何关于局限性或失败模式的说明——这意味着团队通常只记录了系统是如何构建的,而没有记录系统在边缘情况下的表现。而边缘情况恰恰是 AI 系统与其文档中那些“顺境描述”偏差最大的地方。

破坏知识库的三种模式

静默行为漂移(Silent behavioral drift)。 模型版本改变了输出分布,却不改变 API。当基础模型供应商更新权重时,基于其构建的功能可能会开始表现出不同的行为——产生更长的响应、拒绝以前能处理的边缘情况,或改变结构化输出的风格。针对旧版本编写的文档现在错了,但没有弃用警告,没有功能版本号的提升,也没有能捕获它的自动化检查。团队直到用户反馈某些东西变了时才会发现这种漂移。

上下文窗口敏感行为。 一个在短提示词下正常运行的功能,可能会随着上下文的填充而显著退化。在 200K token 模型中,填充了 80% 的上下文窗口可能会导致指令保真度下降,使得该功能的表现就像运行在更弱的模型上一样。这种行为从未在功能规范中被记录。该功能“正常工作”——只是在文档从未预料到的负载条件下表现更差。

嵌入数据中的隐式需求。 传统软件需求是显式的:你可以在规范、工单或注释中找到它们。在 AI 系统中,需求通常是隐式的——嵌入在告知设计的训练数据构成、模型检查点和评估数据集中。当一个团队记录 AI 功能时,他们记录的是它被设计去做什么。而训练数据编码了它实际学会了做什么。这种差距在功能文档中是不可见的,只有当边缘情况揭示了与意图不符的学习行为时才会浮现。

文档转而需要表达的内容

解决办法不是写更长的文档,而是改变文档所声明的内容。

记录输出分布,而非输出值。 不要写“返回 priority: high | medium | low”,而是写“在计费问题中,约 35% 的情况返回 priority: high,50% 返回 medium,15% 返回 low;技术问题的分布会有显著变化——请参阅评估数据。”这样做更诚实,准确性维持得更久,并告诉下游工程师在处理偏差时真正需要了解的信息。

锚定示例,而非仅限规范。 抽象规范比具体示例退化得更快,因为它们离系统的实际表现更远。包含代表性示例的文档——一个成功案例、一个边缘案例和一个标明了失败模式的失败案例——为工程师提供了一个校准目标。当模型更新后输出发生变化时,示例对比通常是捕获变化的关键。

明确规定公差(Tolerances)。 AI 功能的生产文档需要公差窗口:“为了保证输出格式的一致性,上下文窗口填充率不应超过 60%”;“p95 延迟为 X 毫秒,p99 则是其 3-4 倍——请据此做预算。”这些公差不在模型供应商的文档中,而是通过生产观察发现的。捕捉这些信息是功能文档的工作,而不是模型卡片的工作。

记录预期的失败分布。 如果一个功能在正常条件下有 3% 的失败率,请直说。明确失败是什么样子的,什么会触发故障率上升,以及恢复路径是什么。这在目前的实践中很少见——Hugging Face 的分析发现,不到五分之一的模型卡片以任何有意义的方式记录了局限性——但这正是设定诚实预期的文档与建立虚假信心的文档之间的区别。

运营模式:针对模型依赖的版本化文档

一个被低估的问题是,文档很少针对其编写时所对应的模型版本进行版本管理。一份功能文档可能在页脚标注着“使用 Claude 3.5”,而团队此后可能已经迁移到了 Claude 3.7,或者该功能是基于一个托管 API 抽象出来的,而底层的模型在团队不知情的情况下发生了更替。

从处理过这类问题的团队中总结出的一种实用准则:像对待库依赖(library dependencies)一样对待模型依赖。记录该功能是针对哪个模型版本进行评估的。将评估数据(不仅是基准测试 —— 而是带有标记预期输出的真实生产示例)与功能代码一起保留在版本控制中。当模型版本发生变化时,评估套件将决定文档是否需要更新。

这并不是一种繁重的流程 —— 而是要意识到评估数据才是 AI 功能行为的“事实来源”(ground truth),不参考评估数据的文档是在做出无法证实的声明。

最初 90 天揭示了什么

90 天的时间节点通常是 AI 文档债务首次浮现的时候。模型提供者更新了权重;上下文窗口成本发生了变化,团队为了削减成本缩短了上下文长度;一位新工程师加入并字面上地、而非概率性地解读文档。

成功应对这种模式的团队都有一个共同的观察:在 90 天后依然保持真实性的文档,是那些带有“显式不确定性”编写的文档。不是“功能 X 执行 Y”,而是“功能 X 在这些条件下执行 Y,在其他条件下执行 Z,而在我们仍在刻画的第三种场景中表现不可预测。”

这种表述方式写起来会让人感到不舒服。当目标是建立对功能的信心时,这看起来像是在承认弱点。但另一种选择 —— 即暗示系统并不具备确定性的文档 —— 会带来不同的问题:工程师们构建在虚假的保证之上,而当这些保证失效时,他们调试的是代码而不是文档。

构建更耐用的文档实践

对于概率系统,没有文档能永久有效。目标是最大限度地延长文档的有效寿命,并在失败演变成生产事故之前检测到它们。

实践中行之有效的几种模式:

让文档紧贴评估数据。如果规范脱离了示例和指标,那么当行为发生偏移时,文档就失去了锚点。引用特定评估运行结果、并附带评估数据集和所用模型版本链接的文档,在发生变化时是可以被审计的。

针对文档陈旧建立监测机制。当模型版本变更时,运行评估套件并进行对比。当输出分布超出功能规范中记录的容差窗口时,将其视为文档失效 —— 就像测试失败是代码失效一样 —— 并在重新部署前进行更新。

在首次部署前记录失败模式。在发布后编写失败模式文档需要诊断生产故障并进行逆向推导。而在发布前基于评估数据编写文档,可以在这些失败模式仍被理解时捕捉它们,而不是在它们被遗忘之后。

在监控中明确容差窗口。如果文档说明 p95 延迟为 400ms,那么监控阈值应接近 400ms。与文档记录的容差显著偏离的监控,标志着监控或文档中必有一个是错误的。

底层的转变

确定性系统可以作为一种“契约”来记录:“此函数保证此行为。”概率系统只能作为一种“刻画”来记录:“此系统在这些条件下以这种置信度表现出这种行为,并以这些已知方式失效。”

这种从“契约”到“刻画”的转变是大多数技术文档尚未完成的。编写 AI 功能文档的团队默认使用契约式语言,因为那是软件工程几十年形成的文档文化。但将契约式语言应用于概率系统会立即产生债务 —— 一旦分布发生偏移,契约就是错误的。

刻画式文档的准则 —— 输出分布、容差窗口、失败模式清单、示例锚定、模型版本追踪 —— 需要在前期投入更多精力。但它的准确性能维持更久,能设定更诚实的预期,并在失效时表现得更明显。

对于交付 AI 功能的团队来说,这才是真正的升级:不是在传统意义上写更好的文档,而是编写在下个季度依然真实的文档。

References:Let's stay in touch and Follow me for more thoughts and updates