Lost in the Middle 与位置偏见
状态:✅ 正文已补
一句话定义:长上下文里,模型对 开头与结尾 更敏感, 中间 信息更容易被忽略——所以「提示词两头重要、中间次要」。
你为什么要学这个
做 RAG、拼长 system prompt、塞多段资料时,若把关键约束或证据放在中间,模型可能「看不见」。窗口越大、填充越满,这个问题越明显。它不是纯理论:任何把多类信息拼进一次调用的系统(Chatbot、Agent、Workflow、IDE 助手)都会撞上。
学完应能:按层规划 payload、把硬约束与当前任务放在注意力友好区,并在上线前用简单探针验证「中间有没有丢」。
1. 现象:什么是 Lost in the Middle
Lost in the Middle /ˌlɒst ɪn ðə ˈmɪdl/ (Liu 等人,2023)描述的是:在长上下文问答里,相关信息放在上下文 开头与结尾 时,模型更容易用上;放在 中间 时,准确率往往明显下降。这与「位置偏见」( position bias /pəˈzɪʃn ˈbaɪəs/ )是同一工程叙事下的两面:
- 位置偏见 :模型对序列中不同位置的信息利用不均(常呈 U 形:两头强、中间弱)。
- Lost in the Middle :这种偏见在 长上下文 + 多段资料 场景下的具体表现。
直觉(不必死记论文细节):
训练与位置编码让模型更擅长「开头定调、结尾收束」。
注意力在长序列上被摊薄;中间段落既不像开头那样建立框架,也不像结尾那样紧贴生成点。
声称读过 ≠ 推理时用上了 。模型可能复述「我已阅读全部材料」,却漏掉只出现在中间的关键句。
短上下文、结构极清晰、关键句被强标记时,偏见会弱一些;但 不要用「模型窗口很大」当免死金牌 。
2. 提示词构成:从「一层糊墙」到「分层 payload」
规划提示词,先回答:这次调用里到底有哪些 层 ?层的职责不同,默认位置也应不同。下面是与具体厂商 API 解耦的逻辑分层(再映射到 system / user / tool 等角色即可,细节见姊妹文)。
| 层 | 典型内容 | 默认位置建议 |
|---|---|---|
| 身份与硬约束 | 角色、安全红线、必须遵守的格式 | 靠前 (system 头) |
| 工具 / Schema | 函数名、参数、何时调用 | 靠前偏中;过长则压缩描述、按需加载 |
| 业务规则 / Skills | 领域 SOP、项目规范 | 中前;关键规则在 尾部再锚一次 |
| 检索证据 / 附件 | RAG chunks、文件、日志 | 中间主体; 最相关的放头或尾 |
| 对话历史 | 多轮原文或摘要 | 中后;旧轮摘要,近轮保留 |
| 当前任务 | 用户问题、本轮目标、输出检查项 | 靠后 (靠近生成点) |
原则图:
[硬约束] → [能力/工具] → [可变上下文] → [当前任务 + 尾部再强调]
高优先、短而硬 可压缩/按需 易 Lost-in-Middle 最高注意力区
把「提示词」理解成一次请求的 payload 编排 ,而不是一段散文:
- 固定层 :身份、安全、输出契约——短、硬、可版本管理。
- 半固定层 :工具定义、Skills、业务规则——可裁剪、可按任务加载。
- 可变层 :检索结果、附件、历史——按相关度与新鲜度进出。
- 任务层 :本轮问题与验收标准——尽量靠近输出。
同一条信息出现两次并不丢人: 头尾各放一次短规则 ,往往比在中间写一篇长文更稳。
3. 注意事项
- 位置是信号 。同样一句话,放在尾部「输出前检查」和埋在万字中间,被用上的概率可以差一截。
- Token 预算优先于「全塞」 。中间是缓冲区,不是荣誉席;塞满窗口会同时推高成本、延迟和中间丢失率。
- 可验证优于可声明 。关键约束应能被检查(格式校验、拒答条件、引用字段),而不是只写「请务必遵守」。
- 窗口越大 ≠ 中间越安全 。有效利用依赖选材与重排;长窗口只是给了你更多把事情做砸的空间。
- 结构化标记能缓解,不能替代重排 。XML / Markdown 分区、明确标题有助于定位,但最相关证据仍建议避开「纯中间」。
- 摘要会丢约束 。压缩历史时,优先保留红线与已确认决策,而不是闲聊细节。
4. 最佳实践
4.1 两端放硬货
- 头 :身份、安全红线、全局输出格式。
- 尾 :本轮问题、必须引用的证据、输出前检查清单(3–5 条短句即可)。
- 关键业务规则若只能出现一次,优先 尾部靠近任务 ;若很长, 头摘要 + 尾复述 。
4.2 中间放可丢可压的内容
背景介绍、次相关 chunk、旧对话、冗长日志——放中间,并接受「可能被弱化」。真正不能丢的,不要只放这里。
4.3 相关度重排,而不是检索分原样拼接
RAG 常见错误是按召回顺序或分数从高到低一路拼下去,结果最相关段落落在中间带。更稳的做法:
- 控制 k(常比「多塞几个」更有效)。
- Rerank 后,把 Top-1 / Top-2 放到 紧挨问题 的位置(常在尾部证据区),或采用「头尾夹击」。
- 次相关材料放中间或直接丢掉。
4.4 摘要替代堆叠
- 长历史 → 滚动摘要 + 近 N 轮原文。
- 长文档 / 长 tool 输出 → 先摘关键字段再回灌。
- 多跳任务 → 拆成多轮或多节点,让 单次 payload 变短 。
4.5 尾部锚点复述
在用户问题之后(或同一条 user 消息末尾)加一小段:
## 输出前检查
- 只能依据 <evidence> 作答;不足则明确说不知道
- 必须给出引用编号
- 禁止输出密钥与内部 URL
短、可扫、紧贴生成点——专门对抗「规则写在前面但生成时忘了」。
4.6 自测「中间是否丢了」
上线前做一次廉价探针:把 唯一关键事实 只放在上下文中段,头尾不出现,问一个必须依赖该事实的问题。若答不上或胡编,说明你的编排在当前模型与长度下已经 Lost-in-the-Middle。
5. 坑点
| 坑 | 为什么坑 | 怎么绕 |
|---|---|---|
| 窗口大就使劲贴 | 中间带变「信息坟场」,成本与延迟双升 | 先选材、再填充;能 RAG 就不整文塞入 |
| 核心规则只写在长 Rules 中段 | 落在注意力低谷 | 规则短化;关键条尾部锚点 |
| 工具 Schema 占满前半 | 用户问题被挤到相对中间 | 精简描述;按任务加载工具;结果先摘要 |
| RAG 原样拼接 Top-k | 最相关段落落在中间 | Rerank + 两端放置 + 控 k |
| 摘要把约束摘要掉 | 多轮后「人设/红线」消失 | 摘要模板强制保留硬约束字段 |
| 「请仔细阅读以上全部」当银弹 | 不改变位置偏见 | 重排、缩短、锚点、分治 |
| 把知识库整份塞进 system | system 膨胀且中段失效 | 检索注入;system 只留稳定契约 |
6. 不同场景怎么用
6.1 RAG
| 放两头 | 放中间 | 要点 |
|---|---|---|
| 用户问题、引用格式、拒答条件;最相关 1–2 个 chunk | 次相关证据、可选背景 | 控 k;Rerank;「无证据则拒答」写在尾部 |
工程口诀: 检索解决找得到,位置解决用得上。 找得到但放中间,等于没找到。
6.2 Agent
| 放两头 | 放中间 | 要点 |
|---|---|---|
| 目标、工具使用红线、停止/升级条件 | 观察轨迹、长 tool 原始输出 | Tool 结果先摘要再进入下一轮;Schema 描述短;避免把整段日志当「记忆」永久粘贴 |
Agent 特有风险:多步之后上下文越来越长, 早期目标被挤到「相对中间」 。应用「目标卡片」在每轮尾部重贴当前目标与未完成项。
6.3 Chatbot
| 放两头 | 放中间 | 要点 |
|---|---|---|
| 短人设与安全;当前用户话 | 历史轮次 | 滚动摘要;近 N 轮原文;人设勿被历史淹没;不要把百科知识塞进 system |
多轮产品里,位置偏见常表现为:模型更听 最近几句 ,却忘掉会话早期的约束——用摘要保留约束,或周期性重注入短人设。
6.4 Workflow(图编排 / 流水线)
| 放两头 | 放中间 | 要点 |
|---|---|---|
| 本节点输入契约、输出 JSON Schema | 上游大段原始文本 | 节点间传结构化中间态 ,不要把上一节点的完整 prompt 上下文透传给下一节点 |
Workflow 的优势正是:把一次超长调用拆成多次短调用。每个节点只带 完成本步所需的最小上下文 。
6.5 ChatFlow(对话型编排,轻提)
前台对话应保持 短链路、可解释 :硬约束与当前用户意图靠两端;重知识、重工具放编排侧按需拉取。与「前台短、后台重」一致,避免把整条编排状态一次性铺进对话模型上下文。
6.6 场景速查总表
| 场景 | 两头优先 | 中间可压 | 特有策略 |
|---|---|---|---|
| RAG | 问题、格式、Top 证据 | 次相关 chunk | Rerank + 控 k + 拒答 |
| Agent | 目标、红线、停止条件 | 轨迹与长输出 | 摘要回灌 + 目标重贴 |
| Chatbot | 人设、当前话 | 旧历史 | 滚动摘要 + 近 N 轮 |
| Workflow | 节点契约与 schema | 上游原文 | 结构化中间态,禁透传 |
| ChatFlow | 对话短约束 | 编排态细节 | 前台短、后台按需 |
7. 例子:Cursor 的 Context Usage(解剖,非教程)
真实产品里,一次调用往往已被拆成彩色条带。以 Cursor 的 Context Usage 为例(数值随会话变化,结构可迁移):
System prompt ← 头:身份与底座指令(通常很短)
Tool definitions ← 前中:工具 Schema(可能很胖)
Rules / Skills ← 中前:项目规则与技能
MCP / Subagent … ← 中:动态能力与子代理定义
Summarized conversation← 中后:旧对话压缩
Conversation ← 尾:近轮对话(常占大头)
(+ 附件 Files) ← 视产品拼接到会话附近
可观察的工程含义:
- Conversation 靠后 —— 对「当前任务」友好,符合「结尾敏感」。
- Tools / Rules / Skills 易落在中前 —— 若写得很长,关键条文正好进 Lost-in-the-Middle 带。
- Tool definitions 动辄近万 token —— 会挤占预算,并相对推远「真正重要的用户句」;能按需加载就不要全量挂载。
- Summarized conversation —— 摘要质量决定约束是否幸存;摘要模板应显式保留红线。
映射回第 2 节:产品已经帮你分层,但 分层 ≠ 自动防中间丢失 。你仍要:规则短化、关键条可尾部锚点、工具与附件控量、任务描述靠近生成点。
8. 上线前检查清单
- 硬约束是否出现在 头或尾 (更好是两端短复述)?
- 本轮用户问题 / 验收标准是否靠近 输出端 ?
- 最相关证据是否避开「纯中间」?是否做了 rerank 与控 k?
- 单次 payload 是否还能再砍约 30% 而不损任务?
- 长 tool / 长文件是否先摘要再回灌?
- 历史摘要是否保留了红线与已确认决策?
- 是否用「关键事实只放中间」做过一次探针测试?
- Workflow / Agent 是否避免把完整上游上下文透传到下一跳?
学习要点(应能回答)
- 为什么常见「两头强、中间弱」?长上下文下注意力与位置利用不均;中间段落既不定调也不紧贴生成。
- RAG 命中段落应放哪? 最相关放两端(尤其靠近问题) ,次相关放中间或丢弃;先 rerank 再拼接。
- 系统约束、工具规则、用户问题分别适合放哪? 约束靠前(可尾部锚点)、工具靠前但要瘦、问题与检查项靠后 。
已有相关文档(先读这些)
- 上下文窗口(已有一小节)
- 上下文工程 · 知识库
- Context Engineering · 编程范式
- RAG 检索增强生成
- 消息角色与提示结构(角色如何承载各层)
- Few-shot 示例排序与位置(示例顺序与位置偏见)
评论
评论加载中…