跳到主要内容

在 18 个月后复现 AI 决策

· 阅读需 11 分钟
Tian Pan
Software Engineer

一位客户对贷款被拒提出异议。监管机构开启调查。原告律师提交证据开示请求。这三者都带着同一个看似简单实则棘手的问题:你的系统做了什么决定,以及为什么? 决策发生在 18 个月前。你调出案例,发现产生原始输出的每一个组件都已经发生了变化。托管模型版本已被弃用并迁移。系统提示词(System Prompt)被修改了 9 次。你的智能体(Agent)检索到的文档被重新分块(re-chunked)、重新嵌入(re-embedded)并重新排序(re-ranked)到了一个新的索引中。而让整个过程具有非确定性的采样设置从一开始就根本没有记录。

你无法复现该决策。这不是因为你疏忽大意,而是因为你的技术栈中没有任何东西是为了可复现性而构建的。事后解释性(Explainability-after-the-fact)归根结底是一个伪装成解释问题的可复现性问题——而可复现性这种东西,你要么在决策发生的时刻就通过工程手段将其固化,要么就会永远失去它。

令人不安的事实是,大多数团队发现这个漏洞时,恰恰是他们最承受不起后果的时候。重建决策的需求几乎从不会在正常运营期间出现。它往往伴随着诉讼、审计,或是带着监管机构电话号码的愤怒客户而来。到那时,捕获正确证据的窗口期早在一年半前就已经关闭了。

每个输入都有不同的时钟

重建之所以如此困难,是因为 AI 决策并非单一的产物。它是一个流水线的输出,其中每个阶段都有自己的生命周期,而这些生命周期与你解释它们的义务并不同步。

想想一次推理中实际包含的内容。模型版本是最先失效的。主流供应商通常为托管模型提供约 12 到 18 个月的有效期,然后就会弃用。他们的弃用通知会告诉你模型何时退役以及如何迁移,但几乎对行为兼容性绝口不提。一旦旧的快照消失,你就无法重新运行产生原始答案的精确计算,绝无可能。如果你指向的是一个别名端点(aliased endpoint)而不是固定的快照版本,那么底层模型在正式退役之前就已经在发生漂移了。

**提示词(Prompt)**失效的速度更快。系统提示词经常被修改——这里为了减少拒绝回答做点微调,那里加个新的护栏——除非每次修改都有版本记录并盖戳到决策记录上,否则你无法知道在涉及的那一天哪个提示词是生效的。“我们使用这个提示词”是一个关于现状的陈述,而不是关于关键时刻的陈述。

**检索上下文(Retrieval context)**的失效最为无声无息。如果你的系统使用了 RAG,答案取决于从特定索引中提取的特定分块。但索引会被重建。你更换了嵌入模型并重新索引所有内容;你使用了不同的重叠度重新分块;你添加了文档导致排名发生变化。支撑原始答案的分块可能不再以相同的形式存在——如果没有记录检索到的文档 ID 及其在检索时的内容,你就无法说明模型当时实际看到的是什么。

最后,采样参数——温度(temperature)、top-p、任何随机种子(seed)——通常根本没有被捕获,因为在当时看来,它们像是基础设施的琐碎细节,而不是证据。

四个输入,四个独立的时钟,没有一个是为了记录你最终会被问及的那个时刻而上弦的。

甚至模型本身也无法复现自己

假设你做对了一切。你固定了确切的模型快照,存档了确切的提示词,保存了确切的检索文档和确切的采样参数。你重新运行请求,但仍然可能得不到相同的输出。

这一部分会让那些默认认为计算机是确定性的工程师感到惊讶。在托管端点上,零温度(temperature zero)并不能保证得到相同的答案。 罪魁祸首不是采样器中的随机性,而是底层的算术运算。浮点数加法不满足结合律:(a + b) + c 并不总是等于 a + (b + c),而且 GPU 内核会以对当前形状最快的顺序累加张量。改变形状,最后几位小数的结果就会改变,而这偶尔会产生连锁反应,导致生成不同的 Token。

更深层次的原因,正如最近关于推理非确定性的研究所表明的那样,是 Batch Size 依赖性。你的请求不是单独运行的;它会与在同一毫秒到达的其他任何请求一起批处理。跨批次求和的归约内核(Reduction kernels)会根据正在处理的请求数量产生微小的差异。虽然你的提示词在每次运行时都是相同的,但提示词所在的“批次”却不同——这足以让输出无法复现,即使是在零温度和固定种子的条件下。

攻克这个问题是可能的。用于归一化、矩阵乘法和注意力机制的批次不变内核(Batch-invariant kernels)可以在一千次运行中产生位一致(bit-identical)的输出——但代价是大约 60% 的吞吐量损失,几乎没有任何生产系统愿意支付这个代价。现实中,严格的确定性只有在你自己硬件上运行的开源权重模型上才能实现,且需要控制内核并进行单批次推理。在一个共享的托管端点上,“可复现”意味着“统计一致”,而非“位一致”——你的证据策略必须考虑到这一差距,而不是假装它不存在。

实际的后果是:你的目标通常不是重新生成完全相同的字节。而是为了证明,在给定相同输入的情况下,系统的行为处于一个有界的、可解释的范围内——并且已经捕获了当时提供的实际输出,因为那是唯一影响过真实用户的版本。

决策记录是唯一能留存的东西

如果你无法可靠地重现过去,你就必须将其记录下来。面对“重现此决策”的持久答案是决策记录:一个在推理时编写的、包含重建和辩护结果所需一切的不可变快照。这不只是你希望稍后拼凑起来的日志——而是在决策瞬间捕获的专用工件。

一个可辩护的决策记录至少应捕获:

  • 锁定的模型标识——确切的快照版本而非别名,以及提供商和端点。
  • 完整输入上下文——确切的系统提示词、用户输入,以及作用域内任何工具或函数定义的逐字节记录。
  • 检索到的证据——检索到的文档或数据块的 ID 及其在检索时的具体内容,加上检索评分(如果有的话)。
  • 采样参数——temperature、top-p、最大 token 数、种子(seed)以及任何其他影响生成的因素。
  • 实际提供的输出——用户或下游系统实际接收到的响应,而不是重新生成的近似值。
  • 溯源元数据——时间戳、请求 ID 以及周边应用程序的代码或配置版本。

这正是监管推动的方向。《欧盟人工智能法案》第 12 条要求高风险系统必须具备自动事件记录功能——系统必须在无需操作人员提醒的情况下生成记录;手动记录不算数。第 12 条明确要求日志能够实现系统生命周期内运行的可追溯性,对于某些系统,还需记录导致匹配的输入数据以及验证结果的人员。监管门槛不是“你保留了一些日志”,而是“系统设计之初就考虑了决策的可重建性”。

随之而来的设计原则:将决策记录视为每次推理的一等公民输出,自动生成并写入仅限追加、防篡改的存储。如果生成记录是可以在负载压力下跳过的手动步骤,那么在你日后需要辩护的决策上,它极有可能会被跳过。

保留陷阱:记录一切 vs. 按需删除

这是良好意愿与法律发生冲突的地方。阅读上述内容后的本能是永久记录一切。但这种本能本身就是一种合规违规。

使决策可重建的完整输入上下文正是隐私法要求你最小化并删除的个人数据。GDPR 的数据最小化和存储限制原则指出,你应该只收集必要的数据,并仅在需要时保留;擦除权则规定个人可以要求你删除其数据。与此同时,《欧盟人工智能法案》要求你保留日志——高风险系统的自动日志至少保留六个月,而在 HIPAA 等行业规则下,文档要求可能长达数年。一个体系要求删除,另一个要求保留。两者都适用于同一份决策记录。

将客户原始 PII(个人身份信息)存储在不可变且保留十年的审计轨迹中无法同时满足这两个体系——它在结构上就违反了其中之一。从业者们正在趋同的解决方案是架构分离。原始个人数据存储在受最小化和擦除规则约束的仓库中,当其操作目的结束时自动删除。而长期的审计轨迹则由非个人或不可逆匿名化的资产构建——哈希、引用、假名 ID、结构化元数据——这样它就可以在《人工智能法案》要求的更长窗口期内保留,而不会将个人数据作为人质。

先后顺序很重要:首先在原始存储上履行擦除义务,而审计轨迹中留存的内容从一开始就经过设计,不包含任何可恢复的个人数据。搞定这种分离确实很难,而且这往往是团队最常推迟的部分——而这正是为什么值得在第一个监管机构询问之前,而不是之后就进行设计的原因。

在需要之前构建记录

核心逻辑在于,可复现性不是一种可以事后补救的属性。AI 决策的每个组件——模型、提示词、检索、采样——都有各自的更替周期,而且即使你冻结了所有组件,托管推理甚至都无法做到比特级的确定性。十八个月后你真正能辩护的决策,只有那些在决策做出瞬间捕获了证据的决策。

具体来说:锁定模型快照而不是别名,并记录哪个快照服务于每个请求。为你的提示词建立版本,并将版本标记在每个决策上。记录检索到的文档 ID 及其内容,而不只是最终答案。将采样参数捕获为证据,而不是基础设施噪声。将所有这些写入自动的、仅限追加的决策记录中——并将个人数据从持久审计轨迹中分离出来,以便你能同时履行删除和保留义务。

这都不是什么高深工程。这是一个能够自我解释的系统与一个仅仅运行过一次的系统之间的区别。重建决策的请求并不是你运气不好才可能遇到的边缘情况;对于任何在受监管领域运营的人来说,这是一个日期未知的必然。能够冷静应对的团队,是那些将今天的每一次推理都视为明天可能要在法庭上重建的团队。

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