Skip to content

长上下文注意力衰减:为什么模型最容易丢掉中间信息

这篇文章解决什么问题

这篇笔记来自一个很典型的问题:

和 AI 对话时,如果上下文过长,AI 对上下文哪部分的注意力会降低得明显?原理是什么,有没有相关文章参考?

短答案是:

长上下文里,模型最容易低效利用的是中间部分。这不是某个模型的玄学问题,而是长上下文模型里反复观察到的位置偏置现象,常被称为 Lost in the Middle

但只说“中间会丢”不够。真正重要的是理解三件事:

  • 它不是“模型完全看不见中间”,而是“中间信息更难被稳定调用”。
  • 它不是单一原因导致,而是注意力竞争、位置编码、训练分布、对话格式和工程拼接方式叠加。
  • 它可以通过 prompt 布局、RAG 重排序、结构化锚点和分阶段处理明显缓解。

采集时间:2026-04-30

先说结论

长上下文利用率常见趋势不是线性下降,而是更像一个 U 型:

text
信息利用率
高  ──┐                    ┌──
      │                    │
低    └──────── 中间 ───────┘
      开头                 结尾

也就是说:

  • 开头信息通常更容易被保留,因为它常放 system、任务定义、角色、全局约束。
  • 结尾信息通常更容易被调用,因为它离当前生成位置最近,天然带有近因优势。
  • 中间信息最容易被弱化,尤其是长文档、多轮对话、批量检索结果和大段代码一起塞进去时。

工程上要记住一句话:

长上下文窗口是“容量上限”,不是“均匀可用的工作记忆”。

一个模型写着能吃 128K200K1M token,不代表这 1M token 里的每一段都会被同等重视。越接近窗口极限,位置、结构和检索顺序越重要。

“注意力衰减”这个说法要更精确

很多人说“注意力衰减”,容易误会成:

Transformer 对中间 token 的 attention weight 天生一定更小。

这不完全准确。

更专业的说法应该是:

在长上下文任务里,模型对不同位置的信息存在利用率差异;中间位置的关键信息更容易在最终回答中被忽略、误用或被首尾信息覆盖。

这里有两个层次:

层次含义是否一定可见
注意力权重某一层、某个 head 对 token 的权重分布需要模型内部可观测
信息利用率最终回答是否真正用了那段信息可以通过任务表现评估

普通用户感受到的“忘了中间”,多数是第二层:信息利用率下降。

这也是为什么同一个模型有时能在 needle-in-a-haystack 测试里找到中间的一句话,但在真实项目里仍然会漏掉中间的关键约束。前者往往是单一事实定位,后者通常需要多证据组合、冲突判断、约束继承和最终生成。

证据:Lost in the Middle

最经典的论文是:

这篇论文关心的不是“模型能不能接受长输入”,而是“模型是否真的用好了长输入”。

它做了两类很有代表性的实验:

实验看什么结论方向
多文档问答相关文档放在不同位置时,回答质量怎么变相关信息在开头或结尾时表现更好,在中间时明显变差
Key-value 检索给一堆键值对,让模型按 key 找 value长度变长后,中间位置更容易出错

这说明问题不只是“上下文够不够长”,而是:

模型即使能读入很长上下文,也不一定能稳定调用任意位置的信息。

为什么中间最容易丢

1. 注意力是竞争,不是平均分配

Transformer 的 self-attention 允许一个 token 看前面的 token,但“允许看”不等于“会平均看”。

注意力大致可以理解成:

text
当前要生成的 token
  -> 拿 query 去和上下文里所有 key 做匹配
  -> 相关性高的 token 权重大
  -> 权重混合 value 后影响输出

当上下文很短时,关键信息很容易成为显著信号。

当上下文很长时,会出现几个问题:

  • 候选 token 变多,竞争更激烈。
  • 相似段落变多,模型更难判断哪一段是真正依据。
  • 中间信息没有天然边界优势,更容易被前面的任务定义和后面的最新问题压住。
  • 如果中间信息没有标题、编号、引用标识,它在注意力里就更像一段普通背景噪声。

所以问题不是“中间没有 attention”,而是“中间很难在最后决策时赢过其他更显眼的位置”。

2. 对话和指令格式天然强化首尾

真实 LLM 对话里,开头和结尾承担的语义不同。

开头常见内容:

  • system 指令
  • developer 约束
  • 角色设定
  • 输出格式
  • 全局任务目标

结尾常见内容:

  • 当前用户问题
  • 最新补充条件
  • 最后一轮纠错
  • “就按这个来”的最终指令

中间常见内容:

  • 历史对话
  • 长文档
  • 检索结果
  • 代码片段
  • 旧需求和旧结论

模型在训练和对齐阶段见过大量这种格式,久而久之会学到一种很实用但有副作用的策略:

开头像规则,结尾像当前任务,中间像背景。

这在短上下文里通常没问题。到了长上下文里,问题就出来了:如果真正关键的业务规则、冲突约束、证据片段被塞在中间,它就可能被当成背景。

3. 位置编码和长度外推不是无成本的

Transformer 本身没有人类意义上的“第 1 页、第 2 页”。它需要位置编码告诉模型 token 的顺序和相对关系。

常见路线包括:

  • 绝对位置编码
  • RoPE,也就是 Rotary Position Embedding
  • ALiBi,也就是 Attention with Linear Biases
  • 各类长上下文扩展、插值、缩放、稀疏注意力方案

相关基础论文:

这些技术能让模型处理更长序列,但长上下文不是简单把窗口参数调大。

原因是模型训练时见过的数据长度、任务形式、位置分布都有边界。推理时突然塞进远超训练常态的长输入,模型可能仍然能跑完,但远距离定位、跨段引用和中间信息利用会变差。

所以“窗口支持长”只是第一步,“模型真的擅长在长窗口里稳定找证据”是另一件事。

4. 中间信息缺少结构锚点

人在读长文时会靠目录、标题、页码、脚注、引用编号来定位。

模型也需要类似锚点。

如果上下文长成这样:

text
doc1
doc2
doc3
...
doc20

那中间的 doc10 很容易被淹没。

如果改成:

text
[EVIDENCE-10]
来源:退款规则.md
结论:超过 7 天但未发货时仍允许人工退款。
适用条件:订单状态 = pending_ship
原文:...

模型就更容易把这段作为可引用证据,而不是普通长文本。

这就是为什么 RAG 系统里不能只关心“召回了没”,还要关心:

  • 召回片段放在哪里
  • 是否有清晰标题
  • 是否有 source id
  • 是否把最终问题重新贴近相关证据
  • 是否让模型必须引用证据编号

5. 长上下文里会出现“相似证据互相干扰”

真实业务资料很少只有一条证据。

更常见的是:

  • 多个版本的 API 文档
  • 多轮需求修改
  • 多段相似代码
  • 多个用户反馈
  • 多篇检索结果讲同一概念

这些内容一起塞进上下文后,中间位置的信息不仅要和首尾竞争,还要和大量相似片段竞争。

如果中间那段是旧版本、例外规则、边界条件,模型就更容易出现这种错误:

  • 记住了大方向,漏掉例外条件。
  • 引用了相似段落,但不是正确来源。
  • 按最后一段用户话术回答,覆盖了中间的硬约束。
  • 总结时把多个位置的事实混在一起。

这类错误看起来像“幻觉”,本质上经常是上下文组织失败。

Attention Matrix 视角

可以把一次生成想成一个矩阵:

text
             被看的 token
          开头    中间    结尾
生成 token  [  ]   [  ]   [  ]

最后生成答案时,模型会对前面所有 token 建立注意力关系。但这个矩阵不是均匀亮起来的。

在长上下文下,常见模式是:

  • 一些 attention head 专门盯格式、分隔符、标题。
  • 一些 head 更偏向近邻 token。
  • 一些 head 会捕捉全局锚点,比如开头规则或系统指令。
  • 中间普通段落如果没有强标记,就不一定能形成稳定路径。

这也是为什么“把关键规则重复到结尾”经常有效。

不是因为模型不能看前面,而是你帮它在最终生成位置附近重新建立了高权重锚点。

相关改进方向

Found in the Middle:校准位置偏置

Found in the Middle: Calibrating Positional Attention Bias Improves Long Context Utilization 关注的是 positional attention bias,也就是模型对不同位置天然有偏好。

它的启发是:

长上下文能力不只取决于窗口大小,也取决于模型是否能校准不同位置的注意力偏差。

对普通使用者来说,这篇论文的意义不是“马上照着改模型”,而是提醒我们:位置偏置是可测量、可优化的,不只是用户错觉。

Landmark Attention:给长上下文建立索引点

Landmark Attention: Random-Access Infinite Context Length for Transformers 的思路可以粗略理解为:给长上下文放一些 landmark token,让模型能更像随机访问一样定位长文本区域。

它对工程实践的启发很直接:

长上下文需要索引点。没有索引点的大段拼接,就是让模型在长卷轴里凭感觉找东西。

这和我们在 prompt 里加 EVIDENCE-01RULE-03FILE-ADECISION-2026-04-30 是同一类思路:给信息可寻址的名字。

Prompt 和 RAG 怎么改

1. 关键约束不要只放中间

差写法:

text
[任务]
[很长背景]
[关键约束在这里]
[更多背景]
[请回答]

更稳写法:

text
[任务]
[关键约束摘要]
[长背景]
[关键约束复述]
[请基于这些约束回答]

关键不是机械重复,而是把不可违背的内容放在模型最容易使用的位置。

2. 给长资料加目录和编号

推荐结构:

text
你要回答的问题:...

关键证据索引:
- [E1] 退款规则:说明 7 天外未发货仍可人工退款
- [E2] 订单状态:pending_ship 表示尚未发货
- [E3] 客服话术:禁止承诺自动退款

详细资料:
[E1]
...

[E2]
...

[E3]
...

回答要求:
- 必须引用 E1/E2/E3
- 如果证据冲突,先指出冲突
- 不要使用未出现的规则

这样做有三个好处:

  • 开头先建立全局地图。
  • 中间资料有可引用锚点。
  • 结尾再次约束输出行为。

3. RAG 不要只按相似度顺序拼接

很多 RAG 系统做错在最后一步:

text
top1 + top2 + top3 + ... + top20

这会让中间位置变成信息坟场。

更稳的方式是:

步骤做法
召回先拿足候选,不急着全塞
去重去掉重复、过时、低置信片段
分层把规则、事实、案例、反例分开
重排最关键证据放前面或靠近最终问题
锚定每段加 ID、来源、时间、适用范围
约束结尾要求模型引用证据 ID

如果信息很多,可以用“两段式”:

  1. 第一轮让模型只做证据筛选和冲突判断。
  2. 第二轮只把筛出来的证据交给模型生成答案。

这通常比把全部资料一次性塞满窗口更稳。

4. 长对话要做状态压缩

长对话里,中间往往堆满旧消息。

更好的做法不是无限保留原文,而是维护一个当前状态:

text
当前任务状态:
- 已确认目标:...
- 不可变约束:...
- 已废弃方案:...
- 待解决问题:...
- 最新用户决定:...

然后把旧对话降级为可追溯资料,而不是继续挤在主上下文里。

关键点:

摘要不是为了省 token,而是为了把中间历史重新变成首部状态。

5. 代码任务里把“当前目标”贴近结尾

AI coding 场景特别容易触发 Lost in the Middle。

常见失败原因:

  • 给了太多文件。
  • 关键报错在中间。
  • 用户最后只说“修一下”。
  • 模型按最近文件改,却漏掉前面业务约束。

更稳格式:

text
任务:修复 xxx 编译错误。

硬约束:
- 不新增 TypeScript。
- 不新增 hooks。
- 只改 A.vue。

相关代码:
[FILE A]
...

[FILE B]
...

最终确认:
本次只需要修复 A.vue 的 defineProps 默认值引用问题,不做重构。

结尾这段“最终确认”很有用,因为它把中间的硬约束重新拉到模型最容易使用的位置。

一份可直接用的长上下文模板

text
你要完成的任务:
{{task}}

不可违反的约束:
1. {{constraint_1}}
2. {{constraint_2}}
3. {{constraint_3}}

资料索引:
- [S1] {{source_1_one_line_summary}}
- [S2] {{source_2_one_line_summary}}
- [S3] {{source_3_one_line_summary}}

详细资料:
[S1]
{{source_1}}

[S2]
{{source_2}}

[S3]
{{source_3}}

输出要求:
- 先给结论。
- 关键判断必须引用资料编号。
- 如果资料冲突,先列冲突,不要自行合并。
- 不要使用资料中没有出现的事实。

最后确认:
本轮任务只处理 {{task}},必须遵守上面的不可违反约束。

这个模板核心不是格式好看,而是把信息做成三层:

  • 开头:任务和硬约束
  • 中间:完整资料
  • 结尾:输出规则和最终提醒

它正好避开了“关键内容只在中间出现一次”的风险。

什么时候中间也能工作得很好

不是所有长上下文都会严重丢中间。

中间信息更容易被用好,通常满足这些条件:

  • 模型本身做过强长上下文训练。
  • 任务是明确检索,而不是复杂综合推理。
  • 中间片段有清晰标题、编号、来源和关键词。
  • 问题里直接点名了中间片段的 ID。
  • 上下文没有大量相似干扰项。
  • 输出要求强制引用证据。

所以不要把 Lost in the Middle 理解成绝对规律。

它更像一个工程风险:

当你把大量材料平铺进上下文,又没有结构锚点和重排策略时,中间信息最先变得不可靠。

最小落地清单

如果只能记几条,就记这些:

  1. 关键约束放开头,也在结尾复述。
  2. 长资料必须加标题、编号、来源和适用范围。
  3. RAG 结果不要无脑按 topK 拼接,要重排和去重。
  4. 让模型引用证据 ID,降低“看过但没用”的风险。
  5. 长对话要维护当前状态,不要把旧消息无限堆在中间。
  6. 需要高可靠时,用两步:先抽证据,再生成答案。

参考资料

基于 VitePress 的个人知识库骨架