Dual Chunk Attention
Dual Chunk Attention 来自于论文 Training-Free Long-Context Scaling of Large Language Models 的核心算法,是由阿里提出的,旨在无需任何额外训练或微调,就能将现有大语言模型(如 Llama)的上下文窗口扩展到超长长度。
现有的大语言模型(LLM)大多在一个固定的上下文长度(如 2k, 4k)上进行预训练。当你试图输入一个超过这个长度的文本时,模型的性能会急剧下降,甚至输出无意义的内容。这个问题的根源在于位置编码(Positional Encoding)。
现有的大语言模型(LLM)大多在一个固定的上下文长度(如 2k, 4k)上进行预训练。当你试图输入一个超过这个长度的文本时,模型的性能会急剧下降,甚至输出无意义的内容。这个问题的根源在于位置编码(Positional Encoding)。
- 位置编码的作用:Transformer 模型本身不包含序列中单词的顺序信息。位置编码就是给每个单词(Token)一个“坐标”,告诉模型它在句子中的位置。
- 旋转位置编码(RoPE):像 Llama、Mistral 等主流模型都使用 RoPE。它的原理是通过对词向量进行“旋转”来编码位置信息,位置越靠后,旋转的角度越大。
- 核心问题(Out-of-Distribution, OOD):模型在预训练时,只见过特定范围内的旋转角度(例如,对应 0 到 4095 的位置)。当你输入一个长度为 8000 的文本时,第 8000 个单词的位置会产生一个模型从未见过的、非常大的旋转角度。这会让模型感到“困惑”,无法准确理解这个单词的位置和它与其他单词的关系,导致模型性能崩溃。
- 现有解决方案的局限性 在 DCA 出现之前,主流的长文本扩展方案有:
- 位置插值(Positional Interpolation, PI):将长文本的位置“压缩”到模型预训练的范围内。比如把 0-8k 的位置线性插值到 0-4k 的范围内。效果不错,但需要少量微调。
- NTK-aware Scaling:修改 RoPE 的旋转基数,使其能适应更长的文本。无需训练,但效果在极长文本下会衰减。
- 全量微调(Full Fine-tuning):用长文本数据从头开始继续训练模型。效果最好,但成本极其高昂。
3. 本文的突破口:Training-Free(免训练) 这篇论文的目标是找到一种方法,既能达到很好的长文本效果,又完全不需要任何训练或微调,实现“即插即用”。
Dual Chunk Atttention
前提设定
- l: 输入序列的总长度。
- c: 模型的预训练上下文长度(比如 4096)。
- s: DCA 使用的块大小(Chunk Size),必须小于 c(比如 s=2048)。
- i: 当前 Query 的绝对位置。
- j: 某个 Key 的绝对位置 (j <= i)。
⌊i/s⌋: i 所在的块编号。
第一步:对 Key 的位置编码处理
这是整个算法的基石。所有的 Key 不再使用它们的绝对位置 [0, 1, 2, ..., l-1],而是使用一个周期性的、在 [0, s-1] 范围内循环的位置编码。
Pk = [0, 1, ..., s-1, 0, 1, ..., s-1, 0, 1, ...] 这可以用公式 Pk[j] = j mod s 来表示。
这样做可以确保任何 Key 的位置编码值都不会超过 s-1,从而避免了 Key 侧的 OOD 问题。现在,所有的挑战都转移到了如何为 Query (q_i) 设计一个合适的位置编码,以便它能正确地与这些“周期性”的 Key 进行交互。
块间注意力
- 触发条件:Query 和 Key 在同一个块内,即
⌊i/s⌋ == ⌊j/s⌋。 - Query 位置编码策略 (
Pq_Intra):Query 也使用和 Key 一样的周期性位置编码。Pq_Intra[i] = i mod s - 相对距离计算:
M[i][j] = (i mod s) - (j mod s)。因为 i 和 j 在同一块,这个结果就等于 i - j。
连续块注意力
- 触发条件:Query 在紧邻 Key 的后一个块中,即
⌊i/s⌋ - ⌊j/s⌋ == 1。 - 问题:如果直接使用其他策略,会导致紧邻的 Token 相对距离失真。例如,
q_6(在块1) 和k_5(在块0),它们的真实距离是 1。但如果q_6使用块内编码 (6 mod 6 = 0),相对距离是 0-5=-5,错了。如果使用下面的块间编码c-1,相对距离是(c-1)-5,也远大于 1。这破坏了模型的“局部性”假设。 - Query 位置编码策略 (
Pq_Succ):为了修复这个问题,对于每个块开头的w个 Query,给它们赋予一个“连续”的位置编码,即s, s+1, ..., s+w-1。w 通常可以设为c-s。对于块中剩下的 Query,则使用一个较大的常数c-1。Pq_Succ = [s, s+1, ..., s+w-1, c-1, ..., c-1](这个模式对每个块都重复) - 效果:当
q_6(块1的第一个) 去关注k_5(块0的最后一个) 时,q_6使用的位置编码是s(即6),k_5的位置编码是s-1(即5)。它们的相对距离信息近似为s - (s-1) = 1,精确地保留了局部性!这对于模型的连贯性至关重要。
块间注意力
- 触发条件:Query 和 Key 相隔一个以上的块,即
⌊i/s⌋ - ⌊j/s⌋ > 1。 - 问题:这些 Token 相距很远,精确的相对位置已经不那么重要,更重要的是让模型知道“这个
Query在这个Key的后面很远的地方”。 - Query 位置编码策略 (
Pq_Inter):给Query分配一个固定的、非常大的位置编码,即预训练长度的末尾c-1。Pq_Inter = [c-1, c-1, ..., c-1] - 效果:当
q_i去关注一个遥远的k_j时,相对距离是(c-1) - (j mod s)。这是一个很大的正数,且j在其块内的位置越靠后,这个值就越小。这提供了一种粗粒度的、远距离的相对顺序信息。模型知道q_i在k_j的“下游”,但无法知道精确距离。对于远距离依赖,这种粗粒度信息通常已经足够。