Paper

Attention Sink 深度解析:StreamingLLM 如何让大模型突破上下文窗口

5 min read ·

一个反直觉的发现

2023 年底,MIT 和 Meta 的研究团队发现了一个奇怪的现象:在所有主流 Transformer 模型中,第一个 token 总是会接收到远超正常水平的注意力权重——即使它只是一个毫无语义意义的 <BOS>(Begin of Sentence)标记。

这就是 Attention Sink 现象。

更奇怪的是:如果你在推理时把第一个 token 的 KV Cache 删掉,模型的输出质量会急剧下降,即使那个 token 距离当前生成位置已经有几千步之遥。

这篇论文(Efficient Streaming Language Models with Attention Sinks, ICLR 2024)不仅解释了这个现象的成因,还基于它构建了一个极其实用的系统——StreamingLLM,让预训练好的 LLM 无需微调就能处理理论上无限长的文本流。

Attention Sink 的成因

Softmax 的”垃圾桶”效应

自注意力的核心公式是:

Attention(Q, K, V) = softmax(QK^T / √d_k) · V

Softmax 函数有一个重要特性:它的输出必须归一化为概率分布(总和为 1)。当一个 query token 对所有 key token 都没有强烈的语义相关性时,注意力权重仍然必须分配到某个地方。

初始 token 因为两个原因成为了这个”垃圾桶”:

  1. 位置编码的边界效应:RoPE 等旋转位置编码在位置 0 处有特殊的数值特性,使得初始 token 的 key 向量天然具有较大的内积
  2. 训练数据的统计偏差:在预训练语料中,初始 token 出现在每个样本中,模型学会了把”不确定放哪里”的注意力分配给它

量化验证

论文对 Llama-2、Falcon、Pythia 等多个模型族进行了分析,发现:

传统长上下文方案的问题

在理解 Attention Sink 之后,我们可以重新审视现有的长上下文处理方案:

方案 1: 完整 KV Cache

保留所有 token 的 KV Cache。精度最高,但内存占用是 O(n) 的:

模型上下文长度KV Cache 大小
Llama-3 70B8K2.5 GB
Llama-3 70B128K40 GB
Llama-3 70B1M312 GB

1M 上下文的 KV Cache 比模型权重本身还大。不可接受。

方案 2: 滑动窗口(Sliding Window)

只保留最近 N 个 token 的 KV Cache,丢弃更早的。内存固定,但有一个致命问题:

当滑动窗口移过初始 token 时,模型输出会崩溃。

这正是 Attention Sink 解释的现象——模型失去了注意力的”锚点”,Softmax 的数值稳定性被破坏,导致注意力分布变得混乱。

方案 3: RoPE 外推

通过修改位置编码的频率基数(如 YaRN)或使用分段线性外推(LongRoPE),让模型在训练窗口之外仍能工作。这需要额外的微调,而且外推倍数越大精度损失越明显。

StreamingLLM:优雅的工程方案

StreamingLLM 的核心 idea 极其简单:

保留前 K 个 Sink Token 的 KV Cache + 最近 W 个 token 的滑动窗口,丢弃中间的所有缓存。

[sink_1, sink_2, sink_3, sink_4, ...(丢弃)..., recent_W-3, recent_W-2, recent_W-1, recent_W]

典型配置是 K=4, W=252,总共只保留 256 个 token 的 KV Cache。

为什么有效

  1. Sink Token 提供了注意力的”锚点”,维持 Softmax 的数值稳定性
  2. 滑动窗口保留了最近的上下文,足以支撑生成质量
  3. 中间被丢弃的 token 对当前生成的实际贡献极小(注意力权重衰减)

实现伪代码

class StreamingLLM:
    def __init__(self, model, sink_size=4, window_size=252):
        self.model = model
        self.sink_size = sink_size
        self.window_size = window_size
        self.kv_cache = None

    def process_token(self, token):
        # 正常前向传播,更新 KV Cache
        output, new_kv = self.model.forward(token, self.kv_cache)

        # 如果 KV Cache 超过上限,执行驱逐
        cache_len = self.kv_cache.shape[1] if self.kv_cache else 0
        if cache_len > self.sink_size + self.window_size:
            # 保留前 sink_size 个 + 后 window_size 个
            sink = self.kv_cache[:, :self.sink_size, :]
            window = self.kv_cache[:, -self.window_size:, :]
            self.kv_cache = torch.cat([sink, window], dim=1)

        return output

性能数据

论文在 Llama-2 7B 上的实验数据:

方案Perplexity (20K tokens)内存延迟
完整 KV Cache5.0440 GB1x
滑动窗口 (无 Sink)崩溃 (>100)0.5 GB0.8x
StreamingLLM5.180.5 GB0.045x
RoPE 外推 (YaRN)5.1220 GB0.5x

StreamingLLM 的 Perplexity 仅比完整缓存高 2.8%,但延迟降低了 22 倍

2026 年的进展:从 StreamingLLM 到 Sink Token 训练

原始的 StreamingLLM 有一个限制:它依赖模型预训练时自然形成的 Sink Token,而这些 token 通常是 BOS 等特殊标记。

2025-2026 年的后续研究引入了 显式 Sink Token 训练

Dedicated Sink Token

在预训练时在序列开头添加专门的 <SINK> token,并在训练目标中强制让注意力集中到这些 token 上。好处是:

Multi-Scale Attention Sink

将 Sink Token 扩展为多尺度:

这样中间被丢弃的 token 的信息可以部分压缩到局部 sink 中,减少信息丢失。

工程落地场景

场景 1: 实时对话系统

用户和 AI 的对话可能持续数小时,传统方案需要不断截断对话历史。StreamingLLM 让模型保持最近 N 轮对话的完整上下文,同时内存占用恒定。

场景 2: 日志流分析

服务器日志是无限流。StreamingLLM 配合 vLLM 的 PagedAttention,可以持续分析日志流中的异常模式,不需要批处理。

场景 3: 实时翻译/字幕

视频会议的同传场景需要低延迟 + 长时间运行。StreamingLLM 的固定内存和低延迟特性完美匹配。

与其他技术的组合

StreamingLLM 不是银弹,但它可以和其他技术组合:

组合适用场景
StreamingLLM + RAG流式处理中遇到需要深度回溯的问题时,触发 RAG 检索补充上下文
StreamingLLM + Speculative Decoding在流式推理中进一步降低延迟
StreamingLLM + 量化INT4 量化 + StreamingLLM 可以在消费级 GPU 上运行 70B 模型的流式推理
Sink Token + Flash Attention 3Flash Attention 的 IO 优化与 Sink 的缓存驱逐策略互补

我的判断

Attention Sink 论文的核心贡献不是 StreamingLLM 本身——那只是一个工程应用——而是揭示了 Transformer 注意力机制中一个基本的结构性特征

这个发现对整个 LLM 领域的影响包括:

  1. 位置编码设计:未来的位置编码方案需要显式处理 Sink 效应
  2. KV Cache 优化:所有的 KV Cache 压缩方案(GQA、MQA、量化)都需要考虑 Sink Token 的特殊性
  3. 模型架构:Mamba 等 SSM 模型不存在 Attention Sink(因为没有 Softmax),这可能是它们在极长序列上表现更稳定的原因之一

2026 年的趋势是:原生长上下文(1M+)模型处理大多数场景,StreamingLLM 类方案处理”真正无限”的流式场景。两者不是竞争关系,而是互补。

Frequently asked questions

什么是 Attention Sink 现象?
在 Transformer 的自注意力计算中,第一个 token(通常是 BOS 或系统提示的开头)会接收到不成比例的高注意力权重——即使它在语义上并不重要。这是因为 Softmax 需要一个'垃圾桶'来存放多余的注意力分数,初始 token 因为位置编码的特殊性承担了这个角色。
StreamingLLM 的核心思路是什么?
StreamingLLM 保留最前面的 4 个 Sink Token 和最近的一个滑动窗口(如 252 个 token),丢弃中间的所有 KV Cache。这样既保留了注意力的'锚点',又维持了最近上下文的完整性,使 LLM 能持续处理理论上无限长的输入流。
Attention Sink 和 RoPE 位置编码外推有什么区别?
RoPE 外推(如 YaRN、LongRoPE)试图让模型在训练窗口之外仍然保持位置感知能力,本质是扩展上下文窗口。Attention Sink 则接受窗口有限的事实,通过保留关键的'注意力锚点'来保持滑动窗口的稳定性。两者正交,可以组合使用。
StreamingLLM 在生产环境中有什么局限性?
最大局限是信息丢失:滑动窗口之外的内容会被永久遗忘,不适合需要引用早期上下文的任务(如长文档问答)。它更适合实时对话、日志分析、流式翻译等'近期上下文足够'的场景。此外,Sink Token 的数量是超参数,不同模型的最优值不同。
2026 年长上下文处理的主流方案是什么?
三层方案并存:1) 原生长上下文模型(Gemini 3 的 10M、Claude 4.7 的 1M)适合一次性处理全文;2) RoPE 外推 + Flash Attention 适合需要微调的场景;3) StreamingLLM/Sink 适合低延迟流式处理。按场景选方案,不存在银弹。