论文的赌注是:在任意位置使用长上下文信息的能力,在 4K 预训练时就已经基本具备,持续预训练只需要把它「解锁」出来。做法不改架构,只调 RoPE base,改的是数据——在保持领域比例不变的前提下,按领域把长文档挑出来上采样,再训 1–5B token。注意长度口径:7B 实际在 80K 上训练、在 128K 文档上测试;Figure 3/§5.2 显示 100–500M token 时模型在 80K 内检索尚可,但泛化不到 80K–128K,需训到 5B 才能外推到 128K。
开源模型号称支持 100K,但在 Needle-in-a-Haystack(NIAH)上塌掉:LongLoRA 100K 70.0、YaRN Mistral 128K 57.4,而 GPT-4-Turbo 128K 是 87.1(Table 3)。论文认为差距主要不在架构;数据量也只要 1–5B token,远低于前人动辄数百 B 的持续预训练。
关键在「喂什么样的数据」,而非堆数据量:Figure 3 里 token 从 100M(NIAH 37.8)加到 500M(81.1)就解锁了 80K 内的大部分检索,但未能外推到 80K–128K;5B 达到峰值 88.0 并泛化到 128K,10B 反而回落到 84.0(Figure 3)。推断(Figure 3、§5.2 明确说 500M–1B 不泛化到 80K–128K,故「解锁 128K」这一结论需 5B 才成立)。
数据质量 = 领域平衡 × 长度上采样:在各领域内部把长于 4K 的序列占比从约 30% 提到约 70%,领域比例沿用 SlimPajama(网页 82%、代码 4.5%、Wikipedia 4.5%、书 4.5%、Arxiv 2.5%、StackExchange 2.0%)。
代价很直白:全参数持续预训练,7B 训 80K 长度(13B 训 64K),8×80G A100 上约 5 天。短上下文能力用 MMLU 兜底:7B 43.3、13B 52.4。
读完后你应该知道:为什么业界的共识是用几百 B token 去「注入」长上下文能力,以及论文为什么认为这是花错了力气。
NIAH 把一句话(needle)随机插进一篇长文(haystack)的任意位置,要求模型原样复述(Kamradt, 2023)。Figure 1 把结果画成网格:横轴是文档长度 1K→128K,纵轴是针所在深度 0%→100%,绿格=找到,红格=没找到,胜利条件几乎是全绿。
2023 年底的现实是:LongLoRA 100K 的 NIAH 只有 70.0,YaRN Mistral 128K 只有 57.4,LongChat v1.5 32K 只有 18.0(Table 3),前沿级别的表现只见于 GPT-4 128K(87.1)。同时,LLaMA Long 与并行的 XVERSE 采用约 5000 亿 token(§1 原文 500 billion)做持续预训练,成本接近从头预训练。
论文的出发点是一个可证伪的假设:在 128K 内任意位置使用信息的能力,大部分在 4K 的大规模预训练里已经获得,持续预训练只是把它「解锁」(原文 unlock,§1、§5.2)。如果假设成立,需要的不是 5000 亿 token,而是一小份能把这个能力接出来的数据。
读完后你应该知道:Table 1 把各家的差异归结为「训练长度」「数据混合」「长度上采样」三件事,本文在每一行上都选了另一项。
只用 PG19 书籍数据持续预训练(Table 1)。长文管够了,但领域被单一化。Table 5 里作者用 Book↑ 方法验证了同一现象:书域 loss 降 0.175,GitHub 域升 0.029。
NIAH 128K 恰为 57.4(Table 3),比它的通用能力(MMLU 59.4)低 2.0 个百分点。
把文档切到 128K、不做长度上采样(Table 1),并使用稀疏注意力。论文认为它的问题在于「只靠自然存在的长依赖不够」(§3)。
NIAH 100K 为 70.0(Table 3),MMLU 37.9;两个数分别比 Ours 7B 低 18.0 与 5.4 个百分点。Figure 4 里「原始混合 vs 按源上采样」的对照,补的正是长度上采样这一格。
Together LLaMA-2 32K 与 LongChat v1.5 32K 输在训练长度:32K 训练只泛化到约 40K(§2),NIAH 分别为 27.9 与 18.0(Table 3)。
| 工作 | 训练长度 | 数据混合 | 长度上采样 | NIAH | MMLU |
|---|---|---|---|---|---|
| Together LLaMA-2 7B | 32K | 与本文相似 | — | 27.9 | 44.8 |
| LongChat v1.5 7B | 32K,对话数据 | 对话 | — | 18.0 | 42.3 |
| YaRN Mistral 7B | — | PG19 书 | — | 57.4 | 59.4 |
| LongLoRA 7B | 100K | RedPajama | 无 | 70.0 | 37.9 |
| Ours LLaMA-2 7B | 80K | SlimPajama | 按源上采样 | 88.0 | 43.3 |
NIAH 与 MMLU 两列逐字取自 Table 3;前三列的信息取自 Table 1、§2。YaRN 的训练长度原文未给出,以「—」表示。
读完后你应该知道:五种数据策略分别动了「长度分布」和「领域分布」中的哪一个,以及为什么只有按源上采样两头都不破坏。
§3 把文档长度与来源领域拆成两个可以分别操纵的因素:书和 GitHub 代码最长,其次是 Arxiv,C4 与 StackExchange 偏短;动长度就会动领域,反之亦然。在这个二维平面上,五种策略各站一个位置(Figure 2 画的就是它们的长度与领域分布):
| 策略 | 长度分布 | 领域分布 | 检索表现 |
|---|---|---|---|
| Cut at 4K | 截断到 4K | 不变 | 预训练的常规做法,会切掉约 30% 天然长文 |
| Cut at 128K | 保留自然长文 | 不变 | Figure 4 上排:loss 与本文接近,精确检索失败 |
| Global Upsampling | 长文增多 | 被轻微改变 | Together 采用;Table 5 中短上下文六个域变差 |
| Upsample Arxiv / Book / GitHub | 长文增多 | 大幅改变 | YaRN、MPT-storyteller 采用;跨域不迁移 |
| Per-source Upsampling(本文) | 各域内长于 4K 的占比约 30% → 约 70% | 保持 SlimPajama 原比例 | Figure 4 下排:同样 loss,检索接近全绿 |
前三列取自 §3、Figure 2 的图注与 Table 5 的结论;「检索表现」一列是文字读数,不是表内数字。
Figure 4 是两个 LLaMA-2 7B、同样 80K 长度、同样 5B token,只差数据混合的对照。原始混合的验证 loss 在 1K / 16K / 32K / 64K / 128K 为 1.80 / 1.56 / 1.42 / 1.33 / 1.37,按源上采样为 1.80 / 1.56 / 1.41 / 1.32 / 1.36——每列差不超过 0.01,但 NIAH 是上排(原始混合)在约 64K 之后大面积变红、下排(按源上采样)接近全绿。
Table 5 则用 逐域 loss 变化衡量各策略相对原始混合的伤害,门槛是 ±0.01(>+0.01 为变差,<−0.01 为变好,中间为无显著差异)。4K–128K 段的 Book↑ 把自己的书域 loss 压低了 0.175,却把 GitHub 抬高了 0.029,导致越界;按源上采样在这一段七个域里六个变好或持平——C4 −0.010、CC −0.010、Stack −0.006、Arxiv −0.011、Wiki −0.044、Book −0.014——只有 GitHub 高出 0.002,落在无显著差异区。
| 策略 | C4 | CC | Stack | Arxiv | Wiki | Book | Github |
|---|---|---|---|---|---|---|---|
| 0–4K 上下文:原始混合 loss | |||||||
| Original | 2.038 | 1.760 | 1.519 | 1.660 | 1.424 | 2.085 | 0.907 |
| 0–4K 上下文:相对原始混合的变化(正号=变差) | |||||||
| v.s. Per-source | +0.002 | +0.008 | −0.001 | −0.008 | −0.040 | −0.065 | −0.008 |
| v.s. Global | +0.008 | +0.010 | +0.015 | −0.020 | −0.020 | −0.140 | +0.015 |
| v.s. Code↑ | +0.010 | +0.016 | +0.010 | +0.006 | −0.026 | +0.030 | −0.023 |
| v.s. Book↑ | +0.010 | +0.016 | +0.021 | +0.000 | −0.010 | −0.175 | +0.029 |
| v.s. Arxiv↑ | +0.006 | +0.016 | +0.013 | −0.060 | −0.030 | +0.040 | +0.025 |
| 4K–128K 上下文:原始混合 loss | |||||||
| Original | 1.560 | 1.650 | 0.786 | 1.075 | 1.313 | 1.852 | 0.447 |
| 4K–128K 上下文:相对原始混合的变化(正号=变差) | |||||||
| v.s. Per-source | −0.010 | −0.010 | −0.006 | −0.011 | −0.044 | −0.014 | +0.002 |
| v.s. Global | −0.010 | −0.006 | −0.001 | −0.016 | −0.040 | −0.018 | −0.007 |
| v.s. Code↑ | −0.008 | −0.002 | −0.003 | −0.007 | −0.042 | −0.010 | −0.029 |
| v.s. Book↑ | −0.010 | −0.006 | +0.001 | −0.007 | −0.037 | −0.30 | +0.000 |
| v.s. Arxiv↑ | −0.008 | −0.002 | +0.002 | −0.036 | −0.039 | −0.010 | −0.004 |
逐格照抄 Table 5。原文 4K–128K 段 Book↑ × Book 一格印作「− 0.30」,按其余各格的统一精度保留为 −0.30。
Figure 3 是同一配方、只改训练 token 数的六张 NIAH 网格。切换 token 数,看准确率先快后慢、并在 10B 处回落。本页网格是按顶部准确率换算出的示意:每行失败格数 r = round(100 − 准确率),封顶 12(每行 12 列),失败格从最右列往左填。100–500M 三档的 round(100 − acc)(62 / 41 / 19)都超过 12 被封顶,所以网格在前五档看起来一样「整行失败」,差异只能从读数与 Figure 3 的真实准确率读出。
0% / 50% / 100%
论文在 Figure 3 的每张网格上方只给一个总体准确率(37.8 / 59.0 / 81.1 / 85.3 / 88.0 / 84.0),没有逐格数值。本页的示意规则:
r = round(100 − 准确率)(取整、封顶 12);失败格总数 = 3r,每行成功格 = 12 − r,读数里的「成功格 / 36」= (12 − r) × 3。各档 round(100 − acc):100M 62、300M 41、500M 19、1B 15、5B 12、10B 16;封顶后 r 全部为 12。推断(由 Figure 3 顶部准确率换算)。因此本页网格在六档下形状相同,只作趋势示意,不映射准确率;各档差异请看读数里的真实准确率与第二组交互。
「成功格 / 36」是示意图内部计数的结果,不等于论文网格顶部的准确率(后者是论文自己统计的,本页不重算)。失败格落在哪几列是构造的。推断(失败格位置按论文「文档越长越难」的一般现象布置,图中并未逐格核对)。
用滑块选择 token 数,读出这一点的准确率、相对上一档的差和相对 5B(88.0)的差。注意六档并不等距:100M → 300M → 500M 是等距的,之后跳到 1B、5B、10B。
口径:相对上一档的差 = acc[i] − acc[i−1](单位:百分点);Δ vs 5B = acc[i] − 88.0。两项都是差值,不是速率;因为起始几档等距(各差 200M),前三个 Δ 才恰好等于「每 200M」的斜率。保留 2 位小数,JS 与这里逐位一致。
+22.10 个百分点;相对 5B:81.1 − 88.0 = −6.90。+4.20 个百分点;相对 5B:85.3 − 88.0 = −2.70。−4.00 个百分点;相对 5B 同样是 −4.00(上一档就是 5B)。标准差:本交互只做加减,不涉及均值或标准差,故不涉及 ÷N 与 ÷(N−1) 的口径选择。
读完后你应该知道:为什么二次复杂度的注意力没让 80K 训练变得不可承受,以及论文给出的完整训练配置。
注意力是二次复杂度,直觉上 80K 该比 4K 慢约 400 倍。论文的解释是:训练时间的大头是 IO——CPU→GPU(offloading)、GPU→GPU(NVLink)、HBM→SM(FlashAttention 式分块)——这些都与序列长度线性相关;真正的二次注意力计算在 SM 上高度并行,被线性 IO 成本掩盖,于是「训 80K 只比训 4K 慢 3x」(§4)。
代价落在显存上:这套 HuggingFace Transformers + DeepSpeed Zero3 的配置已是框架上限,再长就 OOM;Zero 优化器是数据并行,加 GPU 也换不来更长上下文,显存主要被 KV cache 吃掉。要上 200K 得换序列并行(§4)。
训练本身很朴素:数据无视文档边界打包成 80K 块(跨文档拼接),batch 固定 4M token——原文强调这与 4K 训练的 batch 相同,靠「每块更长、每 batch 块数更少」保证一致;7B 在 80K 下训 5B token;恒定学习率 2e-5;唯一的架构改动是调 RoPE base(沿用 Xiong et al., 2023)。13B 只训 64K。
步数口径(§4):原文写「5B(数据量)/ 4M(batch size)= 2000 optimization steps」,这个算式本身在算术上不成立——5B / 4M = 1250,要得到 2000 步需 5B / 2.5M。页面不改写原文的 2000,但也不把 1250 硬说成论文口径,两组数并列标注。若按 7B 80K 的实际配置(batch 4M token ÷ 80K/块 = 50 块)计,1250 步对应的正是 5B token:4M × 1250 = 5B。推断(2000 可能来自 batch 2.5M 或含其他行的统计;v1 §4 未给 2000 的解释,Figure 3 的 token 分档按比例换算与 1250 步/5B 自洽:100M ≈ 125 步、300M ≈ 375 步、500M ≈ 625 步、1B = 250 步、10B = 2500 步,见折叠)。
| 数据量 | batch | 块大小 / 每 batch 块数 | 步数 = 数据 / batch |
|---|---|---|---|
| 100M | 4M token | 80K / 50 块 | 100M / 4M = 25A |
| 300M | 4M token | 80K / 50 块 | 300M / 4M = 75A |
| 500M | 4M token | 80K / 50 块 | 500M / 4M = 125A |
| 1B | 4M token | 80K / 50 块 | 1B / 4M = 250A |
| 5B | 4M token | 80K / 50 块 | 5B / 4M = 1250A(原文写 2000,算式不成立) |
| 10B | 4M token | 80K / 50 块 | 10B / 4M = 2500A |
注「A」:步数=数据 token 数 ÷ batch token 数,全部按 4M token/步推算;Figure 3 各档 token 数取自图头上方标注,步数为换算而非原文给出。原文只对 5B 一档给了 5B / 4M = 2000 的算式,其余各档原文未写步数。若误用 80K 序列长度作除数(即把 1 步当成 1 个 80K 块),5B / 80K ≈ 62500,与任何原文数字都不对应,故采用 4M batch 口径。
Table 2 列出每个(模型,上下文)组合在两种硬件配置下的耗时,均按 10B token 记账(实际训练 5B):
| 硬件 | 模型 | 上下文 | 时间 / 10B token |
|---|---|---|---|
| 8 × 80G A100 | LLaMA-2 7B | 4K | 3 天 |
| 8 × 80G A100 | LLaMA-2 7B | 80K | 10 天 |
| 8 × 80G A100 | LLaMA-2 13B | 4K | 5 天 |
| 8 × 80G A100 | LLaMA-2 13B | 64K | 13 天 |
| 2 × 8 × 80G A100 | LLaMA-2 7B | 4K | 2 天 |
| 2 × 8 × 80G A100 | LLaMA-2 7B | 80K | 7 天 |
| 2 × 8 × 80G A100 | LLaMA-2 13B | 4K | 4 天 |
| 2 × 8 × 80G A100 | LLaMA-2 13B | 64K | 10 天 |
逐行照抄 Table 2。按同表计算慢倍数:7B 的 80K÷4K = 10 / 3 ≈ 3.3 倍;13B 的 64K÷4K = 13 / 5 = 2.6 倍。
读完后你应该知道:配方里哪一步是论文真正验证过的变量,哪些只是工程实现细节。
这条流程解释了一个容易被忽略的点:Table 5 与 Figure 3、4 测的都是验证 loss,但论文反复强调,只看 loss 会掩盖检索能力的差别(§5.3)。同一配方下 loss 只差 0.01 的两份数据,NIAH 一个上排红、一个下排绿。
读完后你应该知道:88.0 与 90.0 是在什么条件下取得的,以及它们与通用能力之间的取舍。
主结果 Table 3:7B 用 80K 训练、13B 用 64K。「Ctx.」一列是各模型自己声明的上下文,Ours 两行写的是训练长度;NIAH 统一在 128K 文档上测,MMLU 是短上下文通用能力测试。
| 模型 | Ctx. | NIAH | MMLU |
|---|---|---|---|
| GPT-4-Turbo | 128K | 87.1 | 86.4 |
| GPT-3.5-Turbo | 16K | — | 67.3 |
| YaRN Mistral 7B | 128K | 57.4 | 59.4 |
| Together LLaMA-2 7B | 32K | 27.9 | 44.8 |
| LongChat v1.5 7B | 32K | 18.0 | 42.3 |
| LongLoRA 7B | 100K | 70.0 | 37.9 |
| Ours LLaMA-2 7B | 80K | 88.0 | 43.3 |
| LongLoRA 13B | 64K | 54.1 | 50.1 |
| Ours LLaMA-2 13B | 64K | 90.0 | 52.4 |
88.0 − 87.1 = +0.9;7B 比 YaRN Mistral 7B 高 30.6 个百分点(相对后者 +53.3%)。13B 90.0,比同为 64K 训练的 LongLoRA 13B(54.1)高 35.9 个百分点。
7B 43.3,比 LongLoRA 7B(37.9)高 5.4 个百分点;13B 52.4,比 LongLoRA 13B(50.1)高 2.3 个百分点。但都远低于 GPT-4-Turbo 的 86.4。
128K InfiniBench BookQA(Table 4):Ours 7B 27.4、Ours 13B 31.1;GPT-4-Turbo 37.4。13B 距 GPT-4 仍有 6.3 个百分点(相对 16.8%)。
Figure 3 固定配方、只改训练 token 数:100M → 500M 把 NIAH 从 37.8 拉到 81.1(+43.3 个百分点);500M → 5B 只再多 6.9(到 88.0);5B → 10B 反而降 4.0 到 84.0。论文据此判定 500M 就「解锁了大部分能力」,5B 是饱和点,10B 开始在 80K 训练区间上过拟合。
但 Figure 3 的 loss 不配合这个叙事:10B 那一格的 loss 在 1K–128K 为 1.79 / 1.55 / 1.40 / 1.31 / 1.35,5B 是 1.80 / 1.56 / 1.41 / 1.32 / 1.36,几乎逐列相同,NIAH 却从 88.0 掉到 84.0——又一次「loss 看不出差别」。
Ours 7B(27.4)高于 LongLoRA 7B(24.3,+3.1 个百分点)与 YaRN Mistral 7B(26.3,+1.1 个百分点),而 YaRN 的基底 Mistral 7B 本身比 LLaMA-2 7B 强(§5 的说法);Ours 13B(31.1)比 YaRN(26.3)高 4.8 个百分点,相对 +18.3%。
读完后你应该知道:这套方案的适用条件是什么,哪些场景不宜直接套用它的结论。
主结论建立在单句检索上,真实长文任务只报了 BookQA。论文自己把 100K 级指令微调列为未解问题(§6),并指出目前还没有开源的 100K 指令微调模型。把 88.0 外推到长文档推理、多文档问答,超出了原文的范围。
「能力已在预训练中获得」是针对这个基座的假设,论文没有证明它对 Mistral、MoE 或更大模型同样成立。数据量结论(500M 解锁、5B 饱和、10B 过拟合)也只在 80K 训练长度、4M batch、lr 2e-5 这组设定下得到,换尺度未必复现。
训练长度受限于 HF+DeepSpeed Zero3 的显存,论文明确说更长会 OOM,且加 GPU 无法延长上下文(§4)。所谓「128K 能力」实际是 80K 训练 + 长度外推,Figure 1 的网格也显示 100K 之后开始变红。
按源上采样把 0–4K 的 Wiki(−0.040)与 Book(−0.065)loss 压下去了,但 C4 与 CC 各 +0.008、Stack −0.001、Github −0.008——都贴着 ±0.01 的门槛。这组数说明的是「不破坏领域平衡」,而不是「短上下文毫无代价」推断(由 Table 5 中 0–4K 段 Per-source 行的符号与门槛反推)。
一句话收束:这篇工作的贡献是证明「长上下文是一条数据工程问题」,而不是给出长上下文能力本身的上限。