长上下文模型
扩展上下文窗口通常需要做哪些模型层面的改动?¶
扩展上下文窗口不只是增加序列长度,还需解决位置编码失效、注意力计算爆发、训练数据分布偏移等问题。模型层面常需以下改动:
- 位置编码适配或替换:
- 原绝对位置编码(如学习式、正弦)无法外推到未训练长度,需替换为外推友好的相对位置编码(如 RoPE、ALiBi)或对已有位置编码进行插值、缩放。
- RoPE 场景常用位置插值(Position Interpolation, PI):将测试时的位置索引按比例缩小到训练窗口内;或 NTK-aware 缩放:调高 RoPE 基频,让高频分量旋转变慢以适应更长距离。
-
YaRN 进一步结合了 NTK 缩放和温度调优,解决插值导致的相邻 token 区分度下降问题。
-
注意力机制优化:
- 引入高效注意力,如 FlashAttention-2/3,以在长序列上将显存和耗时压到线性或近似线性。
- 采用滑动窗口或稀疏注意力(如 Mistral、Longformer),或混合全局+局部注意力,降低计算量。
-
实现 PagedAttention 或类似的 KV 缓存分页机制,以便在推理时高效管理海量缓存块。
-
训练策略调整:
- 从短序列预训练模型出发,进行长序列继续训练(Continual Pretraining)。需要设计长短混合的数据集,逐步增加序列长度,防止模型遗忘短文本能力。
-
使用分阶段训练或 LongLoRA 等低成本微调方案,只微调部分权重或引入轻量适配器。
-
归一化与稳定性:
- 长序列训练容易出现数值不稳定,需使用更稳定的归一化(如 RMSNorm 预归一化),并采用 bf16 混合精度。
-
有时需要调整优化器(如 Adafactor)或引入 Z-loss 等稳定技巧。
-
并行策略适配:
- 长序列训练显存激增,必须结合张量并行(TP)、序列并行(SP)(如 Megatron-LM 的 SP、DeepSpeed Ulysses),将单序列切分到多卡以分散激活显存。
位置编码外推方法(PI, NTK, YaRN)各自如何与微调结合?¶
这些方法通常是在预训练好的短上下文模型上进行轻量微调,以恢复因插值导致的性能损失,并巩固长上下文能力。
- 位置插值 (PI):

- YaRN(Yet another RoPE extensioN method):
- 综合了 NTK 缩放和温度 t。对于长度比 ss,先做 NTK 缩放,再对注意力 logits 乘以一个温度系数 1/t。这样可以惩罚远距离注意力的分散,更接近训练时的分布。
- 微调结合:YaRN 作者提出训练时使用动态插值(如先不加温度,逐步引入温度),或者在微调中使用 YaRN 配置。实践上,YaRN 可以直接零微调外推到很长的长度(如 128K),但若在长数据上稍作微调,效果更为稳固。微调时依然可使用 YaRN 计算的动态缩放位置。
总结:这三种方法都可在微调时固定下来作为位置编码策略,PI 通常需要较多微调恢复局部性,NTK 和 YaRN 可以少量微调甚至零样本外推。
长上下文训练的数据混合策略是什么?如何构造长短混合的数据集?¶
纯粹的极长文本训练会破坏模型处理短序列的能力,因此需长短混合训练。策略如下:
- 数据分布设计:
- 遵循“短序列保基础,长序列扩展”原则。典型混合比例:约 50%~70% 短序列(原预训练窗口内),30%~50% 长序列(新的目标窗口长度)。
- 长序列数据可以从书籍、代码、学术论文、长对话中获取,确保来源的多样性。
-
部分工作使用 “长序列上采样”:对长文档赋予更高的采样权重,同时维持充足的短样本量。
-
构造方法:
- 拼接短文档:将多个短文档用分隔符(如
<|endoftext|>)拼接到目标长度。注意需保留分界 token,并禁止注意力跨越文档边界(使用注意力掩码或文档标识)。 - 自然长文档:直接使用长文本,如法律文档、长篇小说、维基百科完整页面等。
-
合成数据:用已有的长序列任务(如长程问答、摘要)生成预训练格式的文本。
-
训练调度:
- 分阶段逐步增加序列长度。例如,先在原长度(4K)微调一定步数,然后切换到混合长度(8K→32K→128K),每个阶段逐步提升最长长度。
-
动态 batch 序列长度:在一个 batch 内包含不同长度的序列,通过 packed sequence 方法组合,最小化 padding。实现时可用 Ragged Batch / 变长序列支持。
-
数据标签与模型调整:
- 使用特殊的位置标识(如 token type ids)或直接依赖位置编码,使得模型学习区分长度。
- 若使用 PI 等插值,可只在长序列数据上微调,短序列仍使用原位置编码,或者统一使用插值后位置。
如何测试一个长上下文模型的真实有效上下文长度?大海捞针实验具体怎么做?¶
大海捞针(Needle in a Haystack)实验是最广泛使用的评测方法,旨在检验模型能否从极长输入中检索出特定的“针”。
具体做法:
-
构造Haystack:用大量无关文本(如保罗·格雷厄姆的散文、歌词等)填充到目标长度(如 128K tokens)。
-
放置Needle:在上下文的不同深度(如 0%、25%、50%、75%、100%)插入一个特定的事实陈述句(“针”),如“神奇的水果是菠萝”。
-
提问:在末尾直接提问“神奇的水果是什么?”,要求模型回答“菠萝”。
-
评测矩阵:横轴为上下文长度,纵轴为“针”的插入深度,绘制正确率的 heatmap。深度越靠中间且长度越长,检索难度越大。
-
全面评估:记录模型正确找到“针”的频率,只有当在大部分深度和长度上高正确率时,才认为模型有效利用了长上下文。
真实有效上下文评估:
-
大海捞针仅测试检索,更全面的评测需结合长程推理:如长文档中抽取多段信息进行多跳问答(如“张三生于A地,后移居B地,他的母亲叫什么?”信息分散全文)。
-
使用长文本基准测试:如 L-Eval、LongBench、ZeroSCROLLS,包含单文档/多文档问答、摘要、few-shot 学习等任务。
-
测量困惑度(PPL):在长文档上预测下一个 token 的困惑度,应随长度增加而持续降低或保持稳定,而非上升(信息遗忘)。
除了大海捞针,还有哪些评测长上下文能力的方法?¶
- 长文档问答与推理:
- 多跳问答:如 HotpotQA(分散多篇文档),要求模型跨越长间隔链接证据。
-
叙事问答:如 NarrativeQA,基于整本书的内容回答问题。
-
长文本摘要:如 GovReport、SummScreen,评测生成对全文的理解。
-
合成长程任务:
- Passkey 检索:大海捞针的变体,检索随机数字串。
- KV 检索:输入中给出多个键值对,提问某个键的值。
-
代码理解与补全:超长代码库的理解。
-
语言模型困惑度(PPL):在长序列上预测下一个 token 的损失,尤其关注损失随位置的变化曲线。如果模型能保持低 PPL 直到序列末尾,说明有效。
-
上下文学习评测:许多示例(上下文学习)时需要容纳超长 prompt,评测模型是否能从海量示例中准确学习模式。
-
长程一致性:如 LAMBADA、Scrolls 等,检验生成内容是否与数百页前的设定一致。
结合这些评测,能全面了解模型的真实长上下文理解和利用能力。
长序列训练时,如何优化注意力计算来降低复杂度?使用 FlashAttention 足够吗?¶
优化方法:
-
FlashAttention 系列:通过 IO 感知和分块计算,将内存复杂度从 O(N2)O(N2) 降到 O(N)O(N) 级,实际加速显著。但仅靠 FlashAttention 不足以解决所有问题:虽然显存可行,长序列的时间复杂度仍是 O(N2)O(N2),当 N 达到 1M 时,计算耗时依然巨大。
-
稀疏/近似注意力:滑动窗口、全局+局部、Longformer、BigBird 等,将计算量降至线性。
-
线性注意力(Performer 等)和状态空间模型(Mamba):将复杂度降至线性或常数,但可能牺牲精度。
-
序列并行:将序列维度切分到多个 GPU(如 Megatron-LM 的序列并行、DeepSpeed-Ulysses、Ring Attention),每卡只计算序列的一段,用通信交换注意力所需块,实现超长序列的分布式训练。
-
激活检查点(Gradient Checkpointing):牺牲计算换显存,仅缓存部分中间激活。
-
混合精度:使用 bf16/fp16,减少带宽和存储。
结论:FlashAttention 是长序列训练的必要非充分条件。它处理了内存瓶颈,但超长序列还需结合序列并行、稀疏注意力或线性复杂度模型等方法来控制计算时间。
窗口注意力(Sliding Window)为什么在长上下文模型中有效?窗口大小如何设定?¶
有效性原理:
-
局部性假设:文本具有很强的局部依赖,窗口注意力天然覆盖了最重要的上下文。
-
多层感受野扩张:在 L 层 Transformer 中,第 L 层的 token 可间接接触到最初层中大约 L×(w/2)L×(w/2) 范围内的信息。即使窗口很小,深层也能捕获长程依赖。
-
恒定计算与内存:计算复杂度 O(N·w),与总长度 N 成线性,推理时只需缓存最近 w 个 KV,内存恒定。
-
信息瓶颈与泛化:强制模型专注于局部结构,有助于提取更稳健的特征,在许多长序列任务中证明效果与全注意力相当。
窗口大小的设定:
-
需要根据任务和序列长度选择。常见值:w=4096(如 Mistral 7B),w=32768 等。
-
太小:可能限制感受野,影响超长程依赖(如整本书的连贯性)。
-
太大:降低效率优势,接近全注意力。多层感受野扩大后,一般 w=4096 配合几十层就能覆盖很远的距离。
-
调优方法:实验不同 w,测量目标任务的困惑度或精度。通常 w 取 2 的幂且略大于平均句子/段落长度,以确保一层就能捕获完整局部模式。
为什么有些长上下文模型引入全局记忆 token(如 LongLLaMA)?它们的作用是什么?¶
全局记忆 token是一些专门的、可被所有位置关注的 token,它们作为模型内部的工作记忆。
作用:
-
信息中继:普通窗口注意力中,信息必须逐层传递才能跨越长距离。全局 token 可以直接关注到所有位置并汇总全局信息,然后所有 token 再关注这些全局 token,实现“广播”效果。这相当于在网络上添加了捷径,极大缩短了长程信息路径。
-
记忆压缩:模型可以将长序列的重要信息压缩编码到这些全局 token 的表示中。例如,LongLLaMA 使用 Focused Transformer 的微调方法,在长上下文中识别关键片段并将其压缩到记忆 token。
-
上下文扩展:在推理时,可以将历史序列分块,每块编码成记忆 token,随 KV 缓存一起保留,代替原始的全部 KV 缓存,从而突破有限窗口的限制,实现理论上无限的外推。
-
可解释性与控制:全局 token 提供了明确的记忆单元,便于分析和增强。
在 LongLLaMA 中,记忆 token 以一定间隔插入(如每 256 个 token),它们可以被后续所有 token 关注,从而作为外部记忆库。
在超长上下文(如 1M token)下,训练和推理的最大工程挑战是什么?¶
训练挑战:
-
显存爆炸:即使有 FlashAttention,激活和 KV 缓存依然需占用巨大显存,单卡无法容纳。必须依赖序列并行、张量并行和流水线并行,跨数百甚至数千 GPU 协同。
-
计算时间:全注意力 O(N²) 计算量难以接受,必须引入稀疏或线性注意力近似,同时保证训练质量不下降。
-
数值稳定性:超长序列的 softmax 求和容易溢出,online softmax 算法需要精心调校以在分段后保持精度。
-
通信瓶颈:序列并行模式下,需要大量的 all-gather / reduce-scatter 通信来拼接注意力块,网络带宽成为限制。
-
数据工程:构建海量高质量长文本数据集极具挑战,且需保证多样化以避免模型过拟合到特定长模式。
推理挑战:
-
KV 缓存管理:1M token 的 KV 缓存占用高达数百 GB,必须利用内存层次(CPU 卸载、SSD 交换)和压缩技术(量化、逐出策略)。
-
延迟:每次解码需要从 KV 缓存中检索信息,数据搬运成为主导。需要实现高效的块读取、投机解码或 Cache-Aware 调度。
-
请求调度:服务多个长序列请求时,内存的动态分配与抢占极为复杂,PagedAttention 等方案需扩展以处理巨大 page 表。
-
负载均衡:不同请求长度差异悬殊,混跑时需精细的调度以避免短请求被阻塞。
长上下文的 KV 缓存如何进行压缩或动态驱逐,而不损失重要信息?¶
-
窗口化丢弃:只保留最近 W 个 token 的 KV 缓存,简单高效,适合局部性强的任务,但会丢失全局信息。
-
带有全局 token 的窗口:保留窗口 KV + 少量全局记忆 token 的 KV,结合了局部和全局。
-
重要性驱逐(Eviction based on attention scores):根据历史注意力权重计算每个 KV 对的重要性,驱逐关注度低的 token。例如:
- H2O:通过累加注意力分数,保留“重击者”(Heavy Hitters)token 的 KV,驱逐轻量 token。
-
Scissorhands:基于注意力的累积重要性分数,结合滑动窗口,仅保留最重要的部分历史。
-
低秩压缩:将 KV 缓存投影到低秩空间(类似 MLA),或使用在线 PCA 压缩,动态减少存储维度。
-
量化:将缓存的 K、V 量化为 INT8 或 FP8,甚至 4-bit,极大降低内存带宽和占用,如 KIVI、FlexGen。
-
分页与交换:利用 PagedAttention 将不活跃的 KV 块换出到 CPU 内存或 SSD,需要时异步换入。
关键在于结合任务特性:对需精确定位远距离信息的任务,需保留高重要性 token;对局部流畅性要求高的,依赖窗口。许多方案混合使用多级缓存和智能驱逐策略。
LongLoRA 是如何低成本地扩展上下文窗口的?它核心的 Shifted Sparse Attention 是什么?¶
LongLoRA 的低成本扩展方案:
-
核心思想:受 LoRA 启发,它不微调全量模型参数,而是插入低秩适配器,并仅用极少的长文本数据进行轻量训练,将预训练短上下文模型扩展到长上下文。
-
Shifted Sparse Attention(S²-Attn):
- LongLoRA 发现,在长序列微调时,直接使用全注意力成本高,而普通窗口注意力会限制远距离交互。
- S²-Attn 将输入序列按头分组,不同注意力头分配不同的偏移量。例如,头 1 负责常规窗口(0 偏移),头 2 将窗口右移一半,头 3 再右移等。
-
每个 token 在其所在头的“偏移窗口”内计算注意力。通过多层积累和多个头的不同偏移组合,相当于用稀疏方式覆盖了远距离 token 的交互,成本仅为全注意力的一个很小的分数。
-
效果:配合低秩微调和归一化重参数化,LongLoRA 仅需在原模型 2% 的原始训练成本下,就能将 LLaMA 2 7B 的上下文窗口从 4K 扩展到 100K,且保持强性能。
S²-Attn 的重要意义:它提供了一种计算开销极低的长上下文适应方法,使得学术和小团队也能低成本训练长窗口模型。
你如何设计一个支持无限长度上下文的 Transformer 架构?¶
设计“无限”上下文需要从多个层面结合现有技术,核心是打破序列长度的限制,使计算、内存与长度解耦。
架构设计蓝图:
- 分层注意力与记忆:
- 引入外部记忆模块,使用全局记忆 token 定期压缩历史信息。记忆 token 通过交叉注意力从近期上下文中读取、写入。
- 类似于 Memformer 或 Infini-attention,将长期记忆表示为固定大小的压缩向量或记忆块,通过线性注意力或滑动窗口注意力的方式来更新和读取。
-
使用压缩 Transformer:以较高分辨率保持局部窗口,以低分辨率保存远期摘要。
-
递归/分块处理:
- 将超长序列分段,应用递归 Transformer(如 Transformer-XL 的段级递归),段与段之间传递隐状态或记忆 token,保持记忆连续性。
-
或采用状态空间模型(Mamba, RWKV),其状态更新与序列长度无关,天然支持无限长度。
-
自适应稀疏 + 检索:
- 结合检索增强:不在显存中保留所有 KV 缓存,而是将历史 token 的 K/V 存入可检索数据库(通过 KNN 索引)。在生成时,动态检索相关的历史 KV 参与注意力计算(类似于 Memorizing Transformers)。
-
同时保留局部滑动窗口,保证局部流利度。
-
动态位置编码:
- 使用 ALiBi 或 xPos 等可无限外推的位置偏置,不依赖固定长度。
-
或干脆不使用位置编码,完全依靠记忆 token 传递顺序信息。
-
推理引擎的无限性支持:
- 显存管理采用流式处理:KV 缓存自动换入换出到 CPU/SSD,结合重要性驱逐和异步预取,使显存占用恒定。
- 使用 PagedAttention 分配虚拟内存,通过页面错误处理透明地从外部存储加载历史块。
综合方案:一种可行的设计是 Mamba + 窗口注意力 + 记忆 token 检索 的混合体。局部由 Mamba 或窗口注意力处理,全局交互通过将压缩后的记忆 token 存入外部向量库,并在每层通过交叉注意力从检索到的相关记忆 token 中获取远距离信息。这种架构的复杂度与总长度呈线性或更优,理论上可支持无限上下文。