大语言模型(LLM)已经渗透到代码生成、信息检索、决策辅助等众多场景,但幻觉问题始终是最令人头疼的短板之一。传统方案往往通过引入额外的 LLM 调用进行事实核查,或者构建复杂的 RAG 验证链路——代价是翻倍的 token 消耗和响应延迟。有没有可能在不增加任何额外推理开销的情况下,靠模型自己"知道它不知道什么"?

什么是 Multi-Hop 幻觉

Multi-hop 推理是指模型需要通过多步逻辑链条推导出最终答案的场景。例如:"2024 年诺贝尔物理学奖得主在获奖时所属的大学位于哪个国家?"——这需要先检索获奖者、再定位其所属机构、最后判断所在国家。每一步推理都有可能引入微小偏差,而这些偏差会在多跳过程中累积放大,最终输出一个看似合理实则错误的答案。

更棘手的是,multi-hop 幻觉往往具有"局部正确、全局错误"的特征——每一步孤立看都没问题,但组合之后逻辑断裂。传统的端到端评估很难捕捉到这类错误,因为评判模型自己对多跳事实的核实也同样依赖于链式推理,形成"用幻觉检测幻觉"的死循环。

为什么传统 RAG 验证方案有局限性

目前主流的幻觉缓解手段离不开 RAG(检索增强生成)和 Self-Refinement:

这些方案的共同痛点是:它们发生在输出之后,需要额外的推理轮次。如果能在一轮推理的过程中就完成不确定性评估,就能从根本上消除额外开销。

利用隐藏层注意力权重检测不确定性

近年来,mechanistic interpretability 的研究者发现了一个有趣的现象:模型在对自己输出缺乏信心时,中间层注意力分布会有可测量的变化。具体来说:

基于这些发现,我们可以设计一个轻量级的不确定性评分器,在模型前向传播过程中实时捕捉异常信号,而无需任何额外的 token 生成。

Token 级别的置信度评估方法对比

目前几种主流的 token 级置信度度量各有优劣:

# 方法1:输出概率(最朴素)
prob = softmax(logits)[token_id]

# 方法2:熵(度量分布的不确定性)
entropy = -sum(p * log(p))

# 方法3:表征方差(需要额外扰动)
# 对隐藏层施加 dropout 后观察输出变化
var = mean((output_with_noise - output) ** 2)

# 方法4:注意力熵(无需额外计算)
attn_weights = layer.self_attn.weights
attn_entropy = -sum(attn_weights * log(attn_weights))

其中方法 4(注意力熵)最具吸引力:它在标准前向传播中天然可用,不需要修改模型架构,不需要额外的前向/反向计算,真正做到了零额外 token 开销。

实际效果:Python 代码生成任务减少 30% 幻觉输出

我们在一个内部 Python 代码生成基准上部署了这套方案。具体做法是:在每个生成步骤中,实时监控注意力熵的变化趋势。当检测到连续若干个 token 的注意力熵超过阈值时,触发一个简单的回退策略——中断当前生成分支并回退到上一个低熵 token 重新采样

实验结果令人振奋:

我们同时发现,注意力熵对"引用不存在的 API"和"混淆相似库函数"这两类常见幻觉尤其敏感——这让它在实际开发场景中非常有价值。

当前局限和未来方向

当然,这套方案远非完美:

未来的工作方向包括:将注意力熵与 logit-based 指标(如温度缩放后的概率)做联合建模;探索在 PPO/DPO 等对齐训练中直接将不确定性校准作为优化目标;以及研究更细粒度的注意力头级别分析——不同注意力头可能负责不同类型的不确定性监测。


幻觉检测不应该是"事后诸葛亮"。当模型的前向传播过程本身就携带着丰富的不确定性信号时,我们需要做的只是学会倾听。零额外 token 开销的检测方案或许还处于早期阶段,但它指向了一个更有想象力的方向:让模型在推理时同时输出答案和对答案的信心——就像人类在被提问时,除了给出答案,还能说一句"这个我不太确定"。