08. 长 Context 下 Prompt 设计要注意什么?"Lost in the Middle"问题是什么?

整理长 Context 下的 Prompt 设计原则,以及 Lost in the Middle 问题。

简单回答

Lost in the Middle 是指当 Prompt 很长(尤其是几十 K token 以上)时,大语言模型对位于中间位置的内容关注度显著低于开头和结尾,导致关键信息如果放在中间就容易被"忽视"。长 Context 的 Prompt 设计要遵循:重要信息放开头或结尾、避免"稀释"关键内容、给模型明确的任务锚定、以及用结构化标记帮助模型定位信息。

详细解答

Lost in the Middle 的实验证据

Liu et al. 2023 发表了专门研究这个现象的论文。他们用一个 multi-document QA 任务来测试:把答案所在的文档放在 20 个文档序列的不同位置,看模型在不同位置下的准确率。

结果显示出一个明显的 U 型曲线:答案文档在序列的开头或结尾时,模型准确率明显更高;放在中间位置时,准确率显著下降,而且随着总文档数增加,中间位置的性能下降更明显。

即使是 GPT-4 这样的强模型,在很长的 context 里,中间位置的内容也会被相对忽视。这不是"模型看不到",而是注意力分配的问题——transformer 的 attention 机制天然对序列的首尾有更强的偏置(类似于人类阅读时对首段和末段印象更深)。

设计原则一:重要信息的位置

最重要的信息放开头:如果 Prompt 里有关键的约束、特殊规则、或者用户的核心需求,放在 Prompt 的最开始(通常是 System Prompt 里),而不是埋在大段文档后面。

任务指令放结尾(User Prompt 里):在 RAG 等场景里,检索到的文档片段通常很长,放在中间。用户的实际问题和回答格式要求应该放在文档后面,紧靠模型生成的位置,增加模型的关注度。一个经验上效果较好的结构:

[System Prompt: 角色和行为约束]

[检索到的参考文档 1]
[检索到的参考文档 2]
...
[检索到的参考文档 N]

[用户问题: 基于以上文档,请回答...]
[格式要求: 用 JSON 格式输出,包含...]

答案可能来自的内容不要稀释:如果有 20 个文档,但只有 2 个和问题相关,不要把 20 个全放进去,这会"稀释"关键文档,让它更难被注意到。Rerank 阶段的价值就在于此——只把最相关的几个文档送进模型,而不是把所有召回的文档堆进去。

设计原则二:结构化标记帮助定位

在长 Prompt 里,用明确的结构化标记帮助模型"知道在哪里找什么":

XML 标签:用 <document_1><document_2> 这样的标签包裹每个文档片段,而不是直接拼接。标签让模型更容易定位每个文档的边界。

摘要式标题:在每个文档前加一行摘要("以下是关于 X 主题的文档:……"),让模型在扫描 Prompt 时更容易判断哪个文档可能和问题相关。

显式引用指令:告诉模型"在回答时明确引用来源(比如文档 1说明了……),不要凭空生成"。这个指令会让模型在生成时主动去"查找"对应文档,而不是依赖隐式的注意力。

设计原则三:任务锚定和减少干扰

在文档之前和之后都放任务描述(重复锚定):在长文档序列的前后各放一遍任务说明,防止模型在读完大量文档后"忘了"自己要做什么。这在 context 很长时有明显帮助。

减少无关内容:长 Prompt 里的无关内容不只是浪费 token,还会"干扰"模型对关键内容的关注。预处理时去掉文档里明显不相关的段落,比扔进去更多文档要好。

明确文档总数和来源:"以下是 5 篇相关文档,编号为15,请基于这些文档回答问题"——给模型一个全局视图,有助于它更好地组织对这些文档的处理。

长 Context 模型的能力边界

随着模型的 context window 越来越大(现在已经有支持 1M token 的模型),很多人认为"把所有东西都扔进去就行了"。但实际上长 Context 模型的能力有几个边界需要注意:

"针"越小越难找:Needle-in-a-Haystack 测试发现,在 100K+ token 的 context 里找一段特定文本,即使是最强的模型,错误率也会随 context 长度增加而上升,特别是在 context 中段位置。

推理成本:context 越长,prefill 时间越长,第一个 token 的延迟越大。在对延迟敏感的场景,塞太多文档进去会明显影响体验。

注意力稀释:即使模型"看得到"所有 context,有限的注意力容量在越长的 context 里被稀释得越厉害,很难对所有内容保持同等关注。

面试时可以这样答

Lost in the Middle 是一个有实验支撑的现象:在很长的 Prompt 里,模型对中间位置的内容关注度显著低于首尾,答案文档放在中间序列时准确率明显下降,即使是 GPT-4 也有这个问题。

设计上有几个原则。重要的约束和规则放开头;任务指令和格式要求放在文档序列之后,紧靠生成位置;不要把大量无关文档都扔进去,Rerank 过滤掉低相关文档比堆文档更有价值;用 XML 标签包裹每个文档,帮助模型定位边界;在长文档序列前后都放一遍任务描述,防止"读着读着忘了干嘛"。

长 Context 模型不是万能的。即使 Context Window 很大,注意力会被稀释,还有延迟增加的问题。根本解法还是做好 Rerank,只把最相关的内容送进模型,而不是靠 Long Context 来"兜底"。

常见追问

  1. Lost in the Middle 现象在不同模型之间差异有多大?有没有模型解决了这个问题?
  2. Needle-in-a-Haystack 测试具体怎么做?结果说明了什么?
  3. 在 1M token context 的场景里(比如 Gemini 1.5 Pro),Lost in the Middle 还是个问题吗?