长不等于好,原理决定一切

2020 年 GPT-3 刚出来的时候上下文是 2K token,2023 年 Claude 推到 100K,2024 年 Gemini 1.5 一跃到 1M 并在内部测试 10M,到 2026 年主流模型窗口普遍在 200K 到 2M 之间。五年涨一千倍听着像定律,但这不是简单"把窗口变大"那么轻松,背后是几个硬仗——每一仗都改变了模型推理的物理形态。理解了这些技术,你就不会被营销口径的"超长上下文"忽悠,也能解释为什么你的长会话越来越慢、为什么 /clear 能省钱。

为什么窗口不能随便变大

Transformer 的 Self-Attention 要做的事很直白:序列里每个 token 都要和所有其他 token 计算一次相似度。这意味着计算量和显存占用都是 O(n²)。2K token 时是四百万次运算,100K 时已经是一百亿次,1M 时达到一万亿次。如果硬件按 n² 跟着涨,1M 上下文需要的资源是 2K 时代的二十五万倍——显然没有任何 GPU 跟得上。

所以每次上下文窗口向前迈进一个数量级,背后必然有算法或工程上的突破在"偷走"计算量。这十几年的主线研究,相当大一部分精力都花在了把 O(n²) 降下来或把已经算过的东西存起来复用。

KV Cache:让推理变快的基础设施

先从最关键的一块基础设施讲起,叫 KV Cache,它解决的问题是推理速度。

回想一下模型生成文本的过程:输出第 1 个 token、再输出第 2 个、第 3 个……每生成一个新 token,理论上都要对"已有的所有 token"算一遍 Attention。但稍微想一下就会发现,生成第 1000 个 token 时,前 999 个 token 的 K(Key)向量和 V(Value)向量早在之前那一步就算过了,没必要再算一次。

KV Cache 就是把这些已经算过的 K、V 向量存下来。生成下一个 token 时只需要算这个新 token 的 K、V,和已经存下来的一起做 Attention。时间复杂度从 O(n²) 降到 O(n),这是整个 LLM 推理能跑起来的底层支柱。如果没有 KV Cache,ChatGPT 那种流畅逐字输出的体验根本做不到。

但 KV Cache 有它的代价:它是显存大户。每个 token 要存一整套 K/V 向量(乘以层数、乘以注意力头数),100K 上下文的 KV Cache 动辄占用几十 GB 显存。这也是为什么运行长上下文模型需要大显存 GPU,为什么 vLLM 发明 PagedAttention 去做分块内存管理,以及为什么长对话会越来越慢——缓存命中变差、Attention 本身也变慢。

KV Cache 还解释了 Prompt Caching 的工作原理。OpenAI 和 Anthropic 提供的 prompt 缓存,背后的机制就是把稳定前缀的 KV Cache 在请求之间保留下来,下一次相同前缀的请求直接复用这部分计算。所以前缀只要改一个字符缓存就失效了——因为 Attention 是因果的,任何改动会让后面所有位置的 K/V 都需要重算。

位置编码:让模型知道先后

Transformer 本身对 token 顺序没有感知——你把 "我爱你" 和 "你爱我" 喂给一个没有位置信息的 Attention,它看到的是一样的词包。所以必须在输入里显式编码位置信息。

最早的方案叫绝对位置编码,给每个位置一个固定的向量加到 token embedding 上。这种做法在训练长度范围内工作得很好,但一旦推理时遇到更长的序列,模型会认不出"从没见过的位置",效果急剧崩溃。这个问题叫外推失败,一度是长上下文的天花板。

2021 年中国研究者苏剑林提出了 RoPE(Rotary Position Embedding),用复数旋转的方式编码位置。它的关键性质是相对位置自然地被建模——第 5 和第 10 位置的相对关系,跟第 105 和第 110 位置是一样的。这种对称性让模型可以外推到训练时没见过的长度,虽然不是完美的,但比绝对位置编码好得多。LLaMA、Qwen、GPT-NeoX、Gemini 这些后来的主流架构全部采用了 RoPE 或其变种。

即便有 RoPE,直接外推到十倍训练长度仍然会显著降质。所以扩窗口的实际工程是"RoPE + 长文本微调"的组合拳:先改变 RoPE 的频率分布(NTK-aware、YaRN 这些技巧),再拿一批真正的长文档继续训练一段时间,让模型适应新的位置分布。很多号称"支持 1M 上下文"的开源模型,实际上是基座模型再经过这套长上下文微调工序得到的。

Attention 本身的加速

除了缓存和位置编码,Attention 的计算本身也在被持续优化。

Flash Attention 是 2022 年 Tri Dao 的工作。它不改 Attention 的数学定义,但改了 GPU 上的算法——利用 SRAM 分块计算,减少 HBM(GPU 主存)的读写次数。结果是 2 到 4 倍加速,显存占用腰斩,而且数值上和标准 Attention 完全等价,不是近似。Flash Attention 2 和 3 在 2023、2024 继续深挖,到今天已经是事实标准,几乎所有主流推理引擎都在用。

还有一条思路叫稀疏 Attention,既然全连接的 Attention 贵,那就不让每个 token 都关注所有其他 token。最简单的叫滑动窗口(Mistral 用这个),每个 token 只看附近 W 个;Longformer 加了少量全局节点;BigBird 用滑窗加随机加全局的组合。代价是某些长距离依赖会丢失,所以稀疏 Attention 通常配合全局 Attention 使用,或者只在不太在意长距离的任务上使用。

再一条叫 Ring Attention,专门为超长上下文设计。它把序列切成块分布到多张 GPU 上,GPU 之间以环形拓扑传递,合作完成完整的 Attention 计算。Gemini 1.5 能做到 1M 上下文,背后的分布式推理底座跟 Ring Attention 思想一脉相承。这已经不是单机问题而是分布式系统问题了。

MoE:把模型做大而不把推理做贵

Mixture of Experts 严格说不是长上下文专属的技术,但它在近两年的模型扩张里扮演了关键角色。

思路是:模型里不是一套前馈网络,而是有 N 个"专家"网络,每个 token 通过一个路由器被送到其中 top-K 个专家处理。总参数可能有 671B(DeepSeek-V3),但每次推理只激活 37B。训练和推理成本按激活参数算,而模型的"能力天花板"按总参数算。同样的算力预算下,MoE 模型能达到的效果比密集模型更高。

DeepSeek、Mixtral、Grok、Qwen-MoE 都选择了 MoE 架构。它不直接扩展上下文窗口,但它让"在合理成本内训练超大模型、再给它配超长上下文"变得经济可行。这是整个产业规模能继续放大的经济基础。

有效上下文 vs 标称上下文

有了这套技术栈,把窗口推到 1M、2M 在工程上就可行了。但一个被忽视的问题是:窗口标称的长度,不等于模型能真正用好的长度。

Needle in a Haystack 测试是专门为这个问题设计的。方法很简单:在一长段文档里某个位置埋一句话(针),然后让模型回答关于这句话的问题。多数模型在文档开头和结尾的"针"都能找到,但埋在中间的位置召回率会掉。Liu 等人 2023 年的论文 Lost in the Middle 系统地揭示了这个现象:模型对长上下文的利用呈 U 型,开头和结尾的 token 影响力大,中间 40% 到 60% 位置的 token 经常被"视而不见"。

这个发现有两层含义。从使用者角度,关键信息应该放在上下文的头部或尾部(指令、问题、最重要的参考资料),而不是中间。从系统设计角度,对于大规模知识库场景不要指望"长上下文替代 RAG"——哪怕窗口足够装下整个知识库,实际的召回质量也不如 RAG 先筛选再塞入。

对前端开发者的实际影响

上面一堆技术细节最后落到你写代码时的决策,主要是这几点。

第一,理解长会话为什么越来越贵越慢。每次请求你都在重新发送完整的对话历史,而模型端又要重建 KV Cache 或者依赖缓存前缀。Token 数涨了、Attention 变重了、缓存命中变差了,慢和贵是必然的。这也是为什么主系列一再强调 /clear/compact 是省钱的基础操作。

第二,当你看到"我们把上下文推到 10M"之类的新闻,要多问几层:Needle 测试结果如何?定价是多少?推理延迟几秒?真正决定有没有用的不是窗口多大,而是这三个数字的组合。

第三,应用层的上下文管理设计。一个设计良好的对话系统应该混合三种机制——最近 N 轮保留原文(保证细节)、更早的内容用摘要压缩(保证连贯)、长期的知识用 RAG 按需检索(保证规模)。单纯靠"窗口够大"来解决所有问题,既昂贵又效果差。

第四,在选型时留意各家的区别。Gemini 在长上下文上领先(背后是 Ring Attention 那套分布式方案),Claude 和 GPT 在 200K 级别更成熟,开源模型的长上下文版要看具体的微调质量。同样标 1M 的模型,召回率可能差一大截。

一个记得住的类比

可以把上下文窗口想象成工作台。2K 时代是巴掌大的小桌子,只够摆下一个问题;100K 时代是书桌,能放下一本中篇小说;1M 时代是会议室,能摆下整套丛书,但东西一多反而乱。工作台能有多大由工程决定(KV Cache、Flash Attention、Ring Attention 这些),但能不能在大工作台上保持清晰思路,是另一个问题——这个问题目前还没被真正解决。

所以 LLM 的演进路线从"如何放得下"慢慢转向"如何找得着",未来几年的研究焦点会越来越集中在长上下文利用率、稀疏检索、分层记忆这些方向上。而前端应用层面的对应动作是:把记忆系统设计成多层结构,不要指望单靠一个大窗口解决所有问题。

参考资料

版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:番外 4:上下文窗口进化史——KV Cache 与长上下文

本文链接:https://www.sshipanoo.com/blog/ai/ai-for-frontend/番外04-上下文窗口/

本文最后一次更新为 天前,文章中的某些内容可能已过时!