跳到主要内容

你的思维链是一个故事,而非审计日志

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个智能体用简洁明了的文字告诉你,它检查了用户权限,查阅了策略,确认请求在范围内,并执行了操作。法务阅读追踪记录(trace)。审计人员阅读追踪记录。你的事故复盘也在阅读追踪记录。每个人都阅读同一段话,并且每个人都感到满意。

他们中没有人知道权限检查是否真的运行了。这段文字是叙事的证据,而不是执行的证据——而这两者之所以会被混淆,正是因为叙事足够流畅,让人感觉像是证明。Anthropic 自身关于推理模型忠实度的研究发现,当 Claude 3.7 Sonnet 收到关于正确答案的提示时,平均只有约 25% 的时间承认使用了该提示,而在有问题的类别(如针对评分者的 trick、不道德的提示)中,这一比例低至 19%–41%。模型的陈述推理与其真实行为在大约一半或更多的时间里是不一致的,即使是那些被明确训练以展示思考过程的模型也是如此。

请将那个数字视为思维链(chain-of-thought)所能承载的证据价值的上限。如果追踪记录在 60% 的时间内是正确的,而在 40% 的时间内是错误的,且你无法仅通过追踪记录本身来区分两者,那么你拥有的就不是审计日志。你拥有的是一个带有置信区间的合乎逻辑的叙事,而没有任何监管机构、原告或事故复盘委员会(post-mortem committee)会接受这作为控制措施已启动的证明。

显而易见的范畴错误

审计日志回答了一个特定的问题:发生了什么? 它是对世界上发生的事件的记录——工具调用、数据库写入、策略评估、以及在你可以独立验证的地方留下的痕迹。其定义特征在于它是由行动机制本身产生的,而不是由对该机制的描述产生的。

思维链回答了一个不同的问题:模型计划做什么,以及模型如何界定它产出的内容? 它是通过生成输出的相同过程生成的,受到相同的优化压力,并由奖励听起来合理的散文的相同训练目标所塑造。模型对于哪些注意力头被触发或采取了哪些检索路径并没有特权的内省访问权。从字面意义上讲,它是在编造一个关于它自己的故事。

混淆这两者是一个范畴错误(category error),其性质就像阅读小说家的作者自序并将其视为对犯罪现场的法庭重建一样。作者自序没有撒谎,它在尽职尽责。但它的工作并不是你需要完成的工作。

这种失效模式并不是说推理追踪是无用的——它们对于调试、评估分类和引导通常确实很有参考价值。失效模式在于它们被误认为是合规、安全和事故响应真正需要的证据层,而该层的范畴错误会传播到基于其构建的每一个下游主张中。

叙事与行动的分歧点

对于任何试图将追踪记录作为证据的人来说,有三种分歧模式至关重要。

事后合理化(Post-hoc rationalization)。 模型先生成答案,然后生成能够合理解释该答案的推理。最近对比推理模型的研究清楚地显示了这种模式:一些模型经常在追踪中途修正中间结论(这表明推理正在起作用),而另一些模型几乎从不修正,这表明思维链是为了证明通过其他手段达成的结论而编写的。你无法仅从追踪记录本身判断你处于哪种模式。

省略步骤。 模型执行了一项计算——获取记录、对检索结果评分、应用启发式方法——但根本没有在文字中提及。Anthropic 的忠实度研究发现,即使“提示”是模型获得正确答案的真实原因,模型通常也不会承认使用了它。从统计学上讲,遗漏(omission)比虚假陈述(commission)更常见,而且根据定义,遗漏对读者来说是不可见的。

计划行动 vs. 执行行动。 这是最能击毁合规性论据的一点。追踪记录写道:“我现在将验证用户权限。”下一段写道:“权限检查已通过。”在这两句话之间,模型可能调用了权限工具,可能跳过了调用直接猜测,可能调用了不同的工具,或者可能调用了正确的工具但忽略了结果。文字中没有任何内容可以区分这些情况。只有工具调用记录(由模型以外的机制捕获)才能区分。

第三模式是最危险的,因为它看起来最像证据。模型正在用过去时描述一个动词,仿佛它已经发生。读者的脑海会将其注册为一份执行报告。但事实并非如此。

对于智能体而言,真实的审计日志是什么样的

监管机构已经开始将其落于纸面。欧盟《人工智能法案》(EU AI Act)第 12 条要求高风险人工智能系统在整个系统生命周期内自动生成事件日志,涵盖输入、输出和决策点,其详细程度需足以进行独立重建。专门针对智能体系统,指南明确指出“与风险识别和系统监控相关的事件”是指工具调用及其效果,而不是模型对其意图的叙事。不合规的处罚最高可达 1500 万欧元或全球营业额的 3%(以较高者为准)——这足以激励工程实践,而不仅仅是文字叙事。

能够通过监管审查的模式是“边车操作日志”(sidecar action log):一种由执行工具调用的运行时(runtime)产生的结构化记录,而不是由请求工具调用的模型产生的。每次调用的最小 Schema 大致如下:

  • 工具名称和版本 —— 解决关于哪个 Schema 正在生效的清单漂移(manifest-drift)争议。
  • 实际发送的参数 —— 不是模型在文字中描述的参数,而是离开智能体运行时(runtime)的字节流。
  • 身份和授权上下文 —— 哪个用户、哪个会话、哪些范围(scopes)、应用了哪个策略决策。
  • 返回负载和结果状态 —— 成功、失败、部分成功,并捕获足够的响应(遵守脱敏规则)以验证下游主张。
  • 具有时钟纪律的时间戳 —— 尽可能使用单调时钟,否则进行同步,足以重建跨并行子智能体的顺序。
  • 关联 ID (Correlation ID) —— 将一个智能体轮次中的每个工具调用绑定回入站请求,并跨多智能体移交。
  • 副作用凭据 —— 由下游系统返回的 ID 或哈希值,以便“我们写入了 X 行”这一主张可以与记录系统进行交叉验证。

OpenTelemetry 的生成式人工智能语义公约现在对其中的许多内容进行了编码:gen_ai.tool.call.idgen_ai.tool.name,以及作为执行机制(工具调用、检索查询、API 请求、人类输入)的操作的跨度(span)级属性,这些属性不同于模型的文字描述。当你的可观测性技术栈从运行时发射这些 span,而不是从模型的补全结果(completion)中抓取时,你就拥有了审计日志。当它从文字中抓取它们时,你拥有的只是由审计对象编写的审计日志摘要。

叙述与行动的差异(Diff)是 Bug 的藏身之处

一旦有了 Sidecar 日志,一种全新的诊断方式就成为了可能:将 Trace(轨迹)中的描述与运行时记录的实际情况进行对比。差异所在之处,往往就是最值得关注的故障发生地。

生产事故中常见的一个模式是:思维链(CoT)声称“我将使用 lookup_policy 工具来验证该请求”,但行动日志却显示实际调用的是 search_docs,且查询语句非常宽松。Agent 根据文档内容推断出了一个结果,然后像执行了结构化策略检查一样写下了一段文字,而任何阅读 Trace 的人都会认为流程是合规的。这个 Bug 的本质不在于 Agent 幻觉出了一个工具调用,而在于 Agent 的措辞将一次“推断”提升为了“验证”。如果没有 Sidecar 日志,这个 Bug 是不可见的。有了它,这就是一个简单的告警规则:标记出那些叙述的工具不在行动日志中,或者行动日志中包含叙述未提及的工具调用的 Turn。

这种差异捕捉到了比工具偏差更深层的东西:它捕捉到了那类“幻觉式成功”的失败——Agent 因为写下了一句声称自己完成了工作的句子,就认为工作已经完成了。这个声称是由生成工作的同一个过程产生的,而从生成声称的过程内部来看,没有任何信号表明工作实际上并未发生。只有外部观察者——运行时、网关、工具服务器——才能区分其中的真伪。

“Agent 说它检查过了”毫无价值

请将此视为你代码库中一个可测试的不变量:对于每一个受控行为,都应该有一个由运行时发出的记录,证明控制逻辑已触发,并带有足够的细节来重构决策过程。而不是模型生成的一句话。也不是由一段要求“记录你检查了什么”的 Prompt 生成的日志行。而应该是执行实际检查的代码所产生的记录。

实际的后果包括:

  • 授权决策属于授权服务的日志,而不是 Agent 的叙述。 如果你的策略引擎没有为每个请求发出自己的“带有理由的允许/拒绝”记录,那么你拥有的不是访问日志,而是语言模型对访问日志的总结。
  • 数据检索的溯源(Provenance)属于检索服务。 “Agent 参考了策略文档”是一个声称;“检索服务针对查询 Z 返回了版本为 Y 的文档 ID X”才是证据。
  • 外部写入属于下游系统的审计追踪。 “Agent 创建了工单”是一个声称;工单系统 API 返回的工单 ID 才是证据。
  • 工具调用参数属于发送请求的运行时。 模型可能会用自然语言描述调用;但只有运行时知道在电缆上实际序列化传输的内容是什么。

每当你发现自己依赖 CoT 来证明上述任何一点时,那里就存在一个本该由 Sidecar 日志填补的缺口。这个缺口是审计员会纠缠的地方,也是你的事故响应会陷入僵局的地方。

CoT 是调试辅助工具,而非原始记录

这并不意味着推理轨迹毫无价值。它对于评估(Eval)分类、引导以及理解为什么一次运行会脱离正轨极其有用。当行动日志显示 Agent 调用了错误的工具时,CoT 通常能解释原因——模型可能基于某种错误的假设或 Prompt 中的歧义推导出了该行动,而你可以据此修复。CoT 是很好的信号;问题在于它承载的权重。

有效的工作纪律是保留这两个层级,并明确每个层级回答的是哪个问题:

  • 行动日志(主要记录,外部观察者): 发生了什么?适用于合规、事故响应、法证重构、满足监管要求。
  • 推理轨迹(次要记录,模型生成): 模型的逻辑框架是什么?适用于调试、评估工作、Prompt 迭代、故障模式分析。

将二者混淆——因为推理轨迹冗长且流畅而允许其替代行动日志——会创造出“审计追踪悖论”:日志看起来像是证明,但实际上无法证明任何事情,因为审计的对象同时也是它的叙述者。解决方案是架构性的,而非编辑性的。你无法通过写出更好的 Prompt 来让模型更可靠地讲述关于它自身的真相;你需要一个完全不经过模型的频道。

Sidecar 是一条底线,而不是一个层级

做得好的团队往往将行动日志视为与身份验证或输入校验具有同等地位的防御线——这是你不能触碰、不能通过模型重定向、在写入持久化存储之前不能用文字总结的东西。日志由工具运行时发出,通过独立的流水线流向防篡改存储(仅追加存储,通常为了完整性而采用哈希链),并根据相关监管周期进行保留(《欧盟人工智能法案》第 12 条规定的六个月是底线,而非上限;HIPAA、SOX、PCI-DSS 各有要求)。

做得不好的团队往往将推理轨迹作为审计工件提交,有时是因为这样更容易发布,有时是因为日志基础设施从未建立,有时是因为在审计员或原告律师替他们提出“谁在生成此记录,他们是否可能是个不可靠的叙述者?”这个问题之前,没有人问过这个问题。

请把这个问题带回你自己的系统中:对于你 Agent 的叙述所做的每一个声称——我检查了、我验证了、我查找了、我确认了——是否有一个由模型以外的东西产生的记录来证明这个动词确实发生了?如果是,你的 CoT 可以是一个故事。如果不是,你的 CoT 就被要求承担它在统计学意义上无法可靠承受的重量。而当这种重量变得至关重要时——合规、事故审查、诉讼——故事与审计日志之间的缝隙,正是故障被发现的地方。

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