长上下文提示技巧:在百万 token 里用好模型

过去一年,主流大模型的上下文窗口从几万 token 一路膨胀到百万级别。Anthropic 的 Claude 3 家族默认提供 200K 上下文窗口,并宣称可接收超过 100 万 token 的输入;OpenAI 的 GPT-5.6 系列上下文窗口为 1.05M;Google 的 Gemini 2.0 Flash 也具备 1M token 的上下文窗口。这意味着你可以把一整本书、一个中型代码库或数百份文档一次性塞进提示里。

但「装得下」不等于「用得好」。本文讲解向长上下文模型投喂长材料时的组织技巧,帮助你把百万 token 的真正价值榨出来。

长上下文能做什么与不能做什么

先把预期摆正。长上下文窗口解决了「材料放不进去」的问题,但并没有自动解决「模型会不会认真读、会不会读对」的问题。

长上下文擅长:

  • 跨多份文档做综合与对比,例如把十几份竞品报告汇总成一张对比表。
  • 在单个代码库范围内做全局理解,例如「这个仓库里所有与鉴权相关的函数有哪些」。
  • 保留长篇对话或多轮任务的完整背景,避免来回复述。
  • 一次性核对一份长合同、长论文里的前后一致性。

长上下文不擅长,或者说不能假设它擅长:

  • 自动记住中间段落里的每一个细节。相关结论放在中部时,模型容易遗漏。
  • 替你做信息筛选。材料越多,噪声越多,模型越容易被无关内容带偏。
  • 保证长输出里每一处引用都精确对应原文。
  • 把超长材料里的因果关系完整推理清楚,尤其是需要跨越很远距离的信息时。

一句话:长上下文是「容量」的升级,不是「注意力」的免费升级。下面几个技巧,本质都是在帮模型把注意力放在对的地方。

lost-in-the-middle 现象

2023 年,Liu 等人发表了一篇影响很大的论文《Lost in the Middle: How Language Models Use Long Contexts》(arXiv:2307.03172,发表于 TACL 2023)。他们在两项需要「从输入中找出相关信息」的任务上测试模型:多文档问答和键值检索。

核心发现是:当关键信息在上下文中的位置发生变化时,模型表现会显著波动。性能通常在两种位置最高——相关信息出现在输入的开头,或者出现在输入的结尾;而当相关信息被放在长上下文的中间位置时,即使模型本身号称支持长上下文,表现也会明显下滑。

这个现象对提示工程的直接含义是:

  • 不要默认模型会「公平地」读完所有内容。
  • 关键指令、关键事实、关键约束,尽量放在提示的开头或结尾。
  • 长材料的中间部分适合放「背景」和「次要支撑」,不适合放你最在意的那一条信息。

需要强调,这篇论文测试的是当时的一批模型,后续模型在长上下文利用上已有改进,但「位置偏好」仍然是实践中反复被观察到的真实问题,应当作为默认防范措施。

材料组织:分块、摘要与重排

当你要投喂的素材本身很长,第一步往往不是「全部粘贴」,而是先做一次组织。

分块

把超长材料切成有语义边界的块,例如按章节、按函数、按段落。分块的好处是每块都短而完整,便于你控制顺序,也便于后续做检索或重排。

摘要

对特别长的单份材料,先用模型生成一段结构化摘要,再把摘要放进主提示,原始长文作为可回溯的附件。这样主提示保持精简,模型先看到骨架,需要细节时再去翻原文。

重排

根据任务把材料重新排顺序,而不是机械地按文件名或时间顺序排列。常用策略:

  • 与当前问题最相关的材料排到最前。
  • 互相矛盾的材料相邻放置,方便模型对比而不是把它们隔开。
  • 把「任务指令」与「输出格式要求」固定在提示头部和尾部,不穿插在材料中间。

下面是一段把多份检索结果重排后再拼进提示的示例:

def reorder_for_prompt(query, docs, top_k=5):
    # docs: 已按相关性初排的 [(score, text)]
    # 策略:最相关放最前,同时保留一份放到结尾做强调
    ranked = sorted(docs, key=lambda x: x[0], reverse=True)[:top_k]
    head = ranked[0]            # 最重要,置顶
    middle = ranked[1:-1]       # 中间材料
    tail = ranked[-1]           # 次重要,置底收尾
    ordered = [head] + middle + [tail]
    return "\n\n".join(text for _, text in ordered)

prompt = "请基于以下材料回答问题,相关材料已按重要性排序:\n\n" + reorder_for_prompt(q, docs)

把关键内容放在头尾

这是 lost-in-the-middle 最直接的应对手段,也是成本最低的技巧。

  • 系统指令写头部:角色、目标、硬性约束、输出格式,全部放在提示最前面。
  • 最终要求写尾部:例如「请只依据上面材料作答,不得编造,并标注每条结论对应的材料编号」,放在材料之后、请求收尾处。
  • 真正决定答案的那一条事实,如果只有一条,优先放头部;如果有两条,一条头一条尾,避免挤在中部。
  • 长列表、长表格、长代码,尽量让「待回答的问题」紧贴在它们之后,减少模型需要回跳的距离。

一个常见的反面教材是:先贴 80 页文档,最后一句才说「请回答第 12 页提到的那个参数」。更好的写法是开头就声明任务,文档紧随其后,结尾再次复述问题。

长上下文与 RAG 的取舍

长上下文崛起后,一个常见疑问是:是不是有了百万 token,就不需要 RAG(检索增强生成)了?现实里两者不是替代关系,而是互补关系。

维度长上下文RAG
适合的材料规模数十到数百份文档、一个中型代码库海量知识库、持续更新的文档集
成本输入越长,费用与延迟越高只检索相关片段,成本更可控
新鲜度取决于你投喂的内容,需自行更新可接实时索引,天然适配变化
抗噪声材料越多噪声越多,容易被带偏只取相关片段,信噪比更高
跨库全局理解强,适合综合对比弱,受检索召回限制

实践中的组合方式:

  • 先用 RAG 从大知识库里召回最相关的若干片段,缩小范围。
  • 再把召回片段连同明确任务一起放进长上下文模型,做深度综合与推理。
  • 对超长单文档(如一份长合同),可整份投喂长上下文模型,省去切分检索的工程成本。

简言之:材料会持续增长、需要实时性,用 RAG 做第一道筛选;材料规模可控、需要整体理解,直接用长上下文更高效。

代码库与文档场景示例

场景一:让模型理解一个代码库

不要直接把整个仓库压缩成一个文件丢进去。更稳的做法是分三层:

  1. 目录结构与模块说明放在最前,先给模型一张地图。
  2. 与问题相关的核心文件全文放在中部,按相关性排序。
  3. 函数签名清单、接口约定这类「契约」放在结尾,作为模型作答时的硬约束。
【系统指令】你是资深工程师,仅依据下面仓库材料回答,指出改动会影响哪些模块。

【仓库地图】
src/auth/        鉴权相关
src/api/         接口层
src/db/          数据访问

【相关文件:auth.py】
(全文)

【相关文件:api.py】
(全文)

【接口契约】
login() 返回 token;refresh() 接受 token。任何改动不得改变这两个函数签名。

【任务】若在 auth.py 增加双因子校验,哪些模块需要同步修改?请说明原因。

场景二:长文档核对

把整份文档投喂后,把「你要核对的清单」放在头部和尾部各出现一次,让模型在长文首尾都能看到目标,降低遗漏概率。

场景三:多文档对比

多份竞品报告对比时,先为每份生成一句话定位摘要置于顶部,再附全文,结尾用固定表格模板要求输出,确保格式稳定。

小结

长上下文窗口让「一次投喂大量材料」成为现实,但模型对信息的利用并不均匀。关键要点:

  • 长上下文解决容量问题,不自动解决注意力问题。
  • lost-in-the-middle 意味着中部信息最易被忽略,关键内容放头尾。
  • 投喂前先做分块、摘要、重排,控制材料的顺序与信噪比。
  • 系统指令置顶、最终要求置底,问题紧贴材料。
  • 长上下文与 RAG 互补:RAG 做筛选与实时性,长上下文做整体理解与综合。
  • 代码库与文档场景里,先给地图、再给相关全文、结尾给契约,是最稳的组织方式。

参考与延伸阅读

  1. Liu, N. F., Lin, K., Hewitt, J., Paranjape, A., Bevilacqua, M., Petroni, F., Liang, P. 《Lost in the Middle: How Language Models Use Long Contexts》. arXiv:2307.03172,TACL 2023。核心结论:模型在长上下文中间位置利用信息的能力显著下降。
  2. Anthropic.《Introducing the Claude 3 family》. 官方说明 Claude 3 默认 200K 上下文窗口,并具备接收超过 100 万 token 输入的能力。
  3. OpenAI.《Models》文档(platform.openai.com/docs/models)。GPT-5.6 系列上下文窗口为 1.05M token。
  4. Google.《Gemini API Models》文档(ai.google.dev/gemini-api/docs/models)。Gemini 2.0 Flash 上下文窗口为 1M token。
  5. 本教程站内文章《RAG 提示技巧》(tutorials/prompt-engineering/rag-prompting.md),进一步讲解检索增强与长上下文的配合方式。
本文累计阅读