Skip to content

上下文与长文本

本页速览 上下文窗口决定模型一次能"看"多长。本文讲清上下文窗口的构成、位置编码外推的本质(RoPE/ALiBi/YaRN/NTK-aware)、注意力 O(n²) 与 KV Cache 的工程挑战(FlashAttention)、长上下文训练配比与测试时扩展,并用大海捞针等评测梳理长上下文的真实边界及与 RAG 的权衡。

上下文与长文本

上下文窗口(context window)是模型单次前向能处理的 token 总数——输入 token 加上后续生成的输出 token 都占用这个窗口。 它决定了一次对话能携带多少材料、文档、历史;从 GPT-3 的 2K、到 Gemini 1.5 的百万级,上下文是 2023 年以来竞争最激烈的能力维度之一。但"窗口很大"和"真的能用好"是两回事——本页拆解窗口的结构、扩展方法与真实边界。

一句话定位:上下文窗口 = 位置编码允许的范围 × 注意力能算得动的长度 × 显存装得下的 KV Cache,三者共同决定的"一次性视野"。 它的实现依赖 Transformer 架构详解 中的位置编码与注意力机制。

一、上下文窗口由什么决定

决定因素角色说明
位置编码范围结构上限RoPE 等在训练窗口外分数崩坏,是"最长能写多少"的第一约束
注意力 O(n²) 计算速度上限序列翻倍,注意力计算翻 4 倍(见下文复杂度)
KV Cache 显存物理上限缓存随长度线性增长,序列太长直接 OOM
训练数据的长度分布能力上限只在短文本上训练过的模型,长文本"不会用"(见预训练:数据与目标

因此"宣称的上下文"(如 128K)与"实际可靠工作的上下文"(常常远小于此)之间存在显著差距——这是评估长上下文模型时必须记住的事实。

二、位置编码外推:长上下文的第一个难题

1. 问题本质

训练时模型只见过窗口内(如 4096)的位置索引。**外推(extrapolation)**指直接给超出训练范围的更大位置——RoPE 下角度继续增大,注意力分数分布偏移,模型输出迅速退化。**插值(interpolation)**则指把更大的位置范围"压缩"回训练过的角度区间。

text
RoPE 外推困境(示意):
  训练:位置 0..4096,旋转角度 θ = m·base^{-2i/d}
  外推:直接给位置 8192 → 未见过的大角度 → 分数分布崩坏
  插值:把新范围 [0, 8192) 线性/非线性映射回 [0, 4096) 的角度
        → 模型"见过"的角度分布,但相邻位置区分度变低

位置插值(PI):θ'_m = θ_m · (训练窗口 / 目标窗口)   # 线性压缩
NTK-aware:按 base 的缩放做"高频保真、低频压缩"的非线性插值,
           保留局部细节 → 多数场景效果好于线性 PI
YaRN:结合 NTK 思路与注意力温度缩放,进一步缓解"插值后注意力变钝"

2. 主流的三种策略对比

方案思路是否需微调典型效果
ALiBi注意力分数线性减距离惩罚,天然外推训练 1K 可外推到更长(但长程信息利用弱)
线性/动态插值把新范围压缩回旧角度需短微调(或动态 NTK 免微调)外推数倍窗口
NTK-aware / YaRN高频成分保真 + 低频压缩,注意力重缩放推荐轻量微调数倍~十数倍窗口

为什么"插值要好于外推"

RoPE 的绝对角度与频率是训练时确定的;插值让模型看到的角度分布仍在训练分布内,只是压缩了范围。因此插值路线(NTK/YaRN)成为行业主流——Llama 3.1 的 128K、许多开源模型的 8K→32K 扩展都基于此。

3. 两种扩展路径

text
测试时扩展(不改权重):
  直接对已有模型做位置插值/动态缩放 → 便宜、见效快,但能力上限受训练数据限制

训练时扩展(改权重):
  在超长序列上继续预训练(或"长上下文续训"),
  配合旋转基频(RoPE base)调整与数据配比 → 能力更扎实,成本高
  代表:Llama 3.1 128K、DeepSeek-V3 128K 等

两条路径的成本与效果对比:

路径成本稳定性上限典型场景
测试时插值低(分钟~小时级)中等(可能局部退化)受训练分布限制快速外推到 2~4 倍窗口
训练时续训高(GPU·天以上)高(能真正学会长距离)更高产品级长上下文模型

实际产品往往先用测试时插值快速验证需求,再决定是否投入续训。注意:续训也可能损害短文本能力("灾难性遗忘"的长程变体),因此续训数据需要混入适量短文本,并持续监控短窗口基准。

三、注意力 O(n²) 与 FlashAttention

长上下文的第二个硬约束是自注意力的 O(n²) 复杂度:序列 n 翻倍,注意力计算量翻 4 倍,且中间分数矩阵也需要 O(n²) 显存。FlashAttention(Dao et al., 2022)没有改变渐进复杂度,却通过"IO 感知"把常数因子和显存需求大幅压缩,成为长上下文训练的基石:

text
标准注意力:QK^T 的 [n, n] 分数矩阵必须完整落回显存(HBM),
            再读回来做 softmax 与加权 → 显存 O(n²)、访存昂贵
FlashAttention:
  ① 分块(tiling):把 Q/K/V 切成小块,在片上 SRAM 内
     逐块计算并更新输出,[n, n] 大矩阵从不完整物化
  ② 在线 softmax:块间用"running max 与归一化因子"合并结果,
     得到与标准 softmax 完全一致的精确结果
  ③ 反向传播重计算:不存前向的注意力矩阵,反向时重算 → 显存更省
效果:训练与推理提速数倍、显存从 O(n²) 降到 O(n)(仅常数级成本)

FlashAttention 已经是所有主流训练/推理框架的默认实现(FlashAttention-2/3、vLLM/SGLang 的 attention backend)。它的存在让"64K~1M 上下文训练"成为现实——长上下文工程 = FlashAttention + 位置编码扩展 + 数据配比三件套。

FlashAttention 解决的是"算得动",不是"学得会"

工程上把 128K 跑起来不难;难的是模型真的学会利用很远的上下文。研究(如 Lost in the Middle)发现模型倾向于过度依赖开头和结尾,中间部分的召回明显更差——"窗口大"不等于"全都用得上"。

四、长上下文训练:数据配比与续训

模型对长文本的"利用能力"必须在训练中习得:

  • 长度上采样:训练数据里显著提高长序列(8K+、32K+)的占比。直接用大量长文本从头训练太贵,常见做法是短数据为主 + 长数据按比例混入,或先短后长的两阶段课程。
  • 长上下文续训:在短窗口预训练完成后,用数亿~数百亿 token 的长序列继续训练(常同时调 RoPE base),如 Llama 3.1、Qwen2.5 的长上下文版本。
  • 长度与学习率:长序列训练更吃显存,常需梯度累积、序列并行(sequence parallelism)等分布式技巧。
  • 配比权衡:长文本往往语义密度低、重复多;过度上采样会稀释知识密度——长文本语料需要与知识型短文本保持健康比例。

长上下文的典型应用形态也在快速分化:多轮 Agent 记忆(把整场对话/历史工具调用放进窗口)、整本书/长文档问答代码仓库级理解法律/医疗长文审阅。每种形态对"有效长度"的要求不同:有的只要求"末尾能用"(对话),有的要求"中间也记得"(文档精读)——选型前先明确自己需要的是哪种长度质量。

五、长上下文评测:从大海捞针到综合基准

1. 大海捞针(Needle-in-a-Haystack)

长上下文评测最著名的测试:在几万~百万 token 的无关文本中随机位置埋入一句话事实("needle"),然后提问该事实,看模型能否取出。它直观检验"模型是否真的读了并记住窗口内任意位置的信息":

text
构造(示意):
  haystack:长文档/随机文本拼接,总长 L
  needle:"在旧金山的金色大门公园,最受喜爱的狗狗是斑点犬 Sassy"(自定义)
  埋入位置:随机选深度(开头/中间/末尾)
  提问:"旧金山金色大门公园最受喜爱的狗狗是什么?"
评分:回答是否包含"斑点犬 Sassy" → 得到一张"长度 × 深度"的热力图

用途与局限:
  + 快速、低成本、可复现,业界事实标准(Greg Kamradt 2023 引入)
  − 只测"检索式召回",不测推理/多跳/理解
  − 完美通过 ≠ 长上下文"真的好用"

结果如何解读:通常画一张"深度(埋针位置)× 总长度"的热力图,横轴是上下文长度、纵轴是埋针深度,颜色代表是否答对。理想模型是"整片全绿";常见病态是右上角发黄(长度变长后召回下降)与中间横带发黄(埋在中间的针更容易被漏掉)。注意:"全绿"只说明"能检索",不代表"会推理"——大海捞针是高灵敏的筛选器,不是能力的证明

2. 更严格的长文本基准

基准测什么特点
LongBench14 类任务(单文档 QA、多文档 QA、摘要、代码等)中英双语、综合性最强之一
RULER检索、多跳、聚合、问答等合成任务比大海捞针更难、可控
Lost in the Middle(论文研究)信息位置对召回的影响揭示"开头/结尾优势、中间劣势"
LongBench-Chat / 人工评测真实场景长对话、长文档问答更贴近产品形态

评测的完整方法论见评测与基准

六、长上下文 vs RAG:什么时候用哪个

长上下文与RAG:检索增强生成是"给模型更多信息"的两条互补路线,各有适用面:

维度长上下文RAG
机制全部原文塞进窗口先检索出相关片段再拼接
成本随输入 token 线性增长(且 KV Cache 吃显存)索引/检索成本 + 更少的生成输入
新鲜度受训练/注入数据截止限制可接实时数据源
可溯源弱(信息埋在大段原文里)强(可指出命中片段)
长文档处理直接读全文,简单粗暴需分块(chunking)与检索质量保障
典型场景单次大量材料、需要全局理解库/语料持续更新、规模超窗口、要引用来源

组合使用是常态

成熟产品通常"检索 + 长上下文"并用:用 RAG 把候选压缩到可读范围,再把较长的候选集整段放入长上下文做精读——两条路线的能力互补,而不是二选一。

七、主流模型上下文一览(dataAsOf: 2025-06,以官方发布为准)

模型宣称上下文备注
GPT-3 / GPT-3.52K / 4K~16K早期代表
GPT-4 / GPT-4o8K~32K / 128KGPT-4 后期支持 128K
Claude 2 / Claude 3 系列100K / 200KClaude 3 为 200K
Gemini 1.5 Pro / Flash约 100 万(1M)公开演示到 1M+
Llama 2 / Llama 34K / 8K(原生)Llama 3 官方提供 128K 微调版
Llama 3.1128K官方预训练即支持
Qwen2.5 / Qwen2.5-Long128K / 1M中文生态代表
DeepSeek-V2 / V3128KMoE + MLA 长上下文
Mixtral 8x7B32KMoE 开源代表

说明:宣称值 ≠ 有效值,且不同长度下质量衰减曲线差异很大;具体规格请以各厂商官方文档为准(汇总见主流模型档案)。

一笔成本账(感受量级):假设输入 0.3 美元/百万 token、输出 0.6 美元/百万 token,把 100 页 PDF(约 30 万 token)整段塞进上下文,单次调用输入成本约 0.09 美元,且 KV Cache 占用与首 token 延迟同步上升;若改用 RAG 只检索约 2000 token,成本约为前者的 1/150。长上下文贵在"全部塞入",RAG 便宜在"只带相关"——这是两种路线在成本维度上的核心差异。

八、权衡与边界

  • 窗口成本高企:百万 token 输入的单次调用成本与 KV Cache 显存开销都很大,长上下文 ≠ 免费午餐。
  • 有效利用是瓶颈:大海捞针热力图好看,多跳推理与中间信息利用才是真实能力差距所在。
  • 与推理系统的耦合:上下文越长,推理基础:自回归与采样中的预填充(prefill)阶段越慢,首 token 延迟越高。
  • 位置编码方案仍在演进:RoPE 的 base 选择、YaRN 参数、以及"是否还需要显式插值"都在被持续研究。
  • 与显存的直接冲突:窗口翻倍,KV Cache 显存近似翻倍(见推理基础:自回归与采样),百万 token 输入即使只算 KV Cache 也足以占满单卡——长上下文产品必须同时做 KV Cache 优化与显存规划。
  • "宣称窗口"是营销词,"有效窗口"才是规格:采购/选型时用大海捞针 + 业务样例双向验证,而不是只看宣传页上的数字。
  • 长上下文的替代路径正在出现:Mamba/状态空间模型以线性复杂度建模长序列、稀疏注意力(局部窗口 + 全局锚点)、以及"检索式扩展"(把长文档切成块按需读取)都在改写"长上下文必须全量塞入"的默认假设——未来"长"可能不再是唯一答案,而是多种机制的组合。

选型一句话

  • 要读很多文档、要全局理解 → 长上下文模型(128K+);
  • 库很大、更新频繁、要可溯源 → RAG;
  • 对话要长、历史要多轮 → 中等上下文 + 摘要/裁剪记忆;
  • 预算敏感 → 先算 token 成本账,再决定窗口与检索的配比。

一句话总结

上下文窗口是"位置编码 × 注意力工程 × 训练数据"三方的合力产物:插值解决"位置看不到",FlashAttention 解决"算不动/存不下",数据配比解决"学不会"。而评测(大海捞针到 LongBench)提醒我们:能放下 ≠ 用得好。

延伸阅读

参考资料