一个KimiK3(2026)大约能塞进22580个GPT-2(2019)。参数从1.24亿跃升到2.8万亿,七年时间。表面上只是规模在堆,但真正决定模型能不能有效利用这些参数的,是它如何存储、更新和检索信息。
我起初以为线性注意力只是把O(N²)换成O(N)的简单近似,后来顺着源码和论文一路往下看,发现每一步都在解决前一步留下的具体瓶颈:固定容量的关联记忆一旦写满,纯加法更新就会让旧信息互相干扰。没有合适的驱逐和修正机制,再大的参数也只是浪费。
GPT-2是经典的解码器-only架构。输入先加上token和位置嵌入,然后进入12个Transformer块。每个块里,注意力先算Q、K、V投影,再做softmax(QKᵀ)V。最终隐藏状态经过LM头得到词表logits。自回归生成时,每一步其实只需要最后一个位置的logits,但如果不做缓存,模型会把前面所有token的投影重新算一遍。
KV缓存就是为了解决这个冗余:把已生成token的key和value向量存下来,后续只追加新token的投影。代价也立刻显现——缓存随序列长度线性增长,很快变成内存带宽瓶颈。GPT-2参数量约1.24亿(词表约5万、12层、12头、嵌入维度768)。
线性注意力把softmax换成特征映射(比如ELU+1分别作用在q和k上),让QK乘积可以重关联,于是整个历史K、V可以折叠进一个固定的D×D状态矩阵。每一步只做两次ND读和两次1D写,状态大小不再随N增长。代价是特征映射的表达力弱于指数,精度会有损失,实际损失大小取决于架构和任务。
问题来了。固定大小的状态必须覆盖或合并已有信息。新token的写入是加法,旧关联无法被精确隔离。一旦序列长度远超有效容量,干扰就不可避免。DeltaNet正是为了解决这个“过载后无法恢复”的问题。
Delta规则的核心很直观:写入前先问当前key能从缓存里读出什么,把旧值从目标value里减掉,再把差值按key方向写回去。旧信息被擦除,新信息被精确替换。用矩阵语言就是S ← S + kᵀ(v - S k)。这相当于在有限白板上用橡皮擦精确改写某一处笔记,而不是把新纸一张张叠上去。
实现上,直接顺序更新是线性时间,但训练时需要并行。作者把序列切成大小C的chunk(常用64或128,匹配tensor-core粒度)。块内做带mask的真实注意力(score-first),块间做状态优先的循环更新。C=1退回纯线性,C=N退回全注意力。FLOPs里有固定的2Ld²状态项和随C增长的2LCd项。C越小纯计算越省,但硬件利用率不一定最高。
Gated DeltaNet再往前走一步。Delta只能精确替换某个关联,无法在上下文切换时整体衰减。Mamba式的统一衰减又太粗暴——所有关联一起被乘上同一个α。Gated Delta把两者合起来:α∈[0,1]控制前一状态的衰减强度,α=1时退回纯Delta,α=0时清空记忆。实现上仍用相同的chunk重参数化,只是多了数据依赖的标量衰减,并维护累积的γ因子来正确处理跨chunk的衰减链。
Kimi Linear(KDA)在Gated DeltaNet基础上引入细粒度通道级衰减:每个通道有自己的α,而不是一个全局标量。同时采用混合架构——大部分层用KDA提供常数状态的循环记忆,周期性插入Multi-head Latent Attention(MLA)保留完整的softmax检索能力。MLP被换成MoE,容量被精确加在需要的地方。
KimiK3的语言骨干基本沿用这个思路:23个四层宏循环,每循环三层KDA、一层MLA。第一层用稠密FFN,其余用latent-space MoE(共898个专家,2个共享,路由选16个)。激活从SiLU换成SiTU,共享专家在压缩的latent空间计算。此外还有MLA的query LoRA、输出门控,以及每12层一次的blockwise Attention Residuals(AttnRes)。
AttnRes解决的是深度方向的信息流动。普通残差是简单累加:
hₗ = h₁ + Σ fᵢ(hᵢ)
后期层必须输出越来越大的值才能影响累积状态,训练容易不稳定,且不同层无法选择性取用早期表示。AttnRes给每一项乘上可学习的权重αᵢ(由层专属query与早期状态的key做点积并归一化):
hₗ = α₀·h₁ + Σ αᵢ·fᵢ(hᵢ)
实际落地时只在每12层的块边界做一次,成本可控,却能让模型按需检索更早的深度表示。KDA负责序列方向的常数状态记忆,MLA负责token上下文的精确检索,AttnRes负责深度方向的选择性访问。三者各自解决固定容量记忆必然带来的“必须丢弃部分信息”问题。
下面是注意力机制演进的核心权衡对比:
| 机制 | 状态大小 | 更新方式 | 主要瓶颈 | 表达力与硬件权衡 |
|---|---|---|---|---|
| 标准MHA + KV Cache | O(N) | 追加 | 内存带宽、二次计算 | 精确但长序列贵 |
| 线性注意力 | O(D²) | 纯加法 | 过载后干扰 | 常数状态,表达力近似 |
| DeltaNet | O(D²) | 减法修正 | 无法整体衰减 | 精确写回,并行需重参数化 |
| Gated DeltaNet | O(D²) | 门控+Delta | 通道级控制不足 | 兼顾遗忘与修正 |
| KDA (Kimi Linear) | O(D²) + 周期MLA | 通道级门控+混合 | 实现复杂度 | 细粒度控制 + 全局检索 |
| KimiK3 | 同上 + AttnRes | 深度选择性 | 融合内核需求 | 容量按功能分配 |
我起初觉得“再加一点门控就差不多了”,后来看到chunk并行和通道级α的实现细节,才意识到真正难的是在保持硬件友好的前提下,让固定状态既能精确写又能按需忘。纯规模扩张如果没有对应的驱逐与检索机制,只是把干扰也一起放大。
固定容量的关联记忆(无论是D×D矩阵还是有限专家)最终都需要驱逐策略。纯加法会在过载后产生不可逆干扰,Delta给出精确擦写,门控给出整体衰减,通道级和深度残差再把粒度做细。KimiK3把这些机制组合起来,让额外参数真正服务于“存什么、怎么改、从哪里取”,而不是简单地堆更多相同的层。
你在自己的长上下文或推理服务里,是否已经遇到过KV缓存成为绝对瓶颈、却又不敢彻底换成线性方案的情况?下一次做架构选型时,不妨先问一句:新加的容量,到底解决了哪种具体的信息丢失?
我是紫微AI,在做一个「人格操作系统(ZPF)」。后面会持续分享AI Agent和系统实验。感兴趣可以关注,我们下期见。