3 CSA + HCA 混合注意力 / V4 最大的创新

V4 的注意力核心是两种 KV cache 压缩策略交替排列,再加一层滑动窗口兜底。 这一节用交互式可视化把每个细节拆开讲清楚。

3.1 整体架构:三种 KV 视野协同工作

V4-Pro 主干 Transformer 一共 61 层,配置文件 config.jsoncompress_ratios 字段直接写明:

// V4-Pro compress_ratios(前两层都是 128 HCA,之后严格交替)
[128, 128, 4, 128, 4, 128, 4, ..., 4, 128, 4, 0]
//   ↑    ↑    ↑                          ↑
//   HCA  HCA  CSA                        MTP(仅滑窗)

// 主干:31 层 HCA + 30 层 CSA
// 末尾 MTP block: compress_ratio = 0(不压缩,只保留最近 128 token)

HCA 层(31 层)

compress_ratio = 128
每 128 个 token 压成 1 条
不重叠 · 全看(不做稀疏)
用极低成本扫一遍全局大意

CSA 层(30 层)

compress_ratio = 4
每 4 个 token 压成 1 条
重叠压缩 · 再用 Indexer 选 top-1024
从全局历史精选最相关细节

滑动窗口(每层都有)

n_win = 128
最近 128 个 token 原样保留
不压缩 · 不稀疏
兜底最近上下文一个不丢

3.2 交互可视化①:50K token 上下文,CSA / HCA / 滑窗各自看到什么?

下面这条彩色带是一段 10000 个 token 的上下文。拖动当前 token 位置、切换层类型,观察每个 query 在不同层"看到"了哪些 KV:

6000 / 10000
每一格 = 1 个 token;高亮 = 当前 query;亮色 = 实际参与本层 attention 计算的 KV
压缩前的 token(不存储) CSA 压缩后 KV(Indexer 选中) 压缩后 KV(未被选中) HCA 压缩后 KV 滑动窗口(最近 128) Query token

本层实际参与计算的 KV 数

vs 标准全注意力

3.3 Compressor 在干什么?—— 学习的加权平均

CSA 和 HCA 在代码里是同一个 Compressor,区别只有一个参数 compress_ratio。 它做的事不是降采样(每 m 个取 1 个),也不是简单平均(每 m 个加起来除以 m),而是学习的加权平均

# Compressor 核心(简化版,来自 inference/model.py)
kv    = self.wkv(x)        # ① 每个 token 投影成一条 latent (MLA 的遗产)
score = self.wgate(x)      # ② 同时给每个 token 算一个"重要度分数"
score += self.ape          #    + 可学习的位置偏置(块内第几位)

# ③ 形状 [B, 组数, m, 512],softmax 沿 dim=2(组内 m 个分数归一化)
#    然后用这些权重对 m 条 latent 加权求和 → m 条变 1 条
kv = (kv * score.softmax(dim=2)).sum(dim=2)

哪个 token 更重要、权重更高,是模型自己学出来的self.ape 是可学习的位置偏置—— 块内第 1、2、3、4 个 token 各有不同的偏置项,让模型能学会"块内哪个位置通常更重要"。 压缩后的 1 条 latent 是原始 m 条的"智能摘要"

Si = Softmaxrow( Zami:m(i+1) + Ba ; Zbm(i-1):mi + Bb )
CCompi = Σ Sj ⊙ Cj (论文式 11、12)

3.4 CSA 的精巧细节:重叠压缩(HCA 没有)

HCA:不重叠

Token: [t1..t128] [t129..t256] [t257..t384]
压缩:      c1          c2           c3

块边界清晰
每条 c_i 看 128 个原 token

CSA:重叠

Token: [t1 t2 t3 t4][t5 t6 t7 t8][t9..t12]
            ↓             ↓           ↓
重叠压缩:   c1            c2'         c3'
                          ↑  c2' 同时看 t1~t8

每条 c_i 实际融合 8 个 token 的信息
压缩比仍是 4:1
为什么差别这么大?

所以 CSA 重叠、HCA 不重叠,不是设计偏好,是数学算账

3.5 Lightning Indexer:FP4 全程的 top-k 选择器

CSA 层压完之后还要再选 top-k。这一步由 Lightning Indexer 完成:

主路径 vs Indexer 路径的精度分工

主路径(CSA 内容)Indexer 路径(打分)
Q / K 精度FP8FP4
压缩 KV cache 精度FP8FP4
能不能再砍精度不能(CSA 压缩已有损,再砍内容就没了)能(只排序,容错高)
对应代码CoreAttn(...)rotate_activation + fp4_act_quant

3.6 滑动窗口:兜底的"短期记忆"

CSA 和 HCA 都需要"凑满一个块"才能压缩。CSA 要凑 4 个,HCA 要凑 128 个。在凑满之前呢? 凑不满的尾巴必须原样保留——这就是滑动窗口的作用。

为什么是 128?因为 HCA 最多有 127 个 token 还在等压缩,128 刚好把最坏情况覆盖。 CSA 层虽然只需要 3 个,但统一一个数字简化实现,多存几十条的开销可以忽略(128 × 576 字节 ≈ 0.07 MB/层)。

3.7 交互可视化②:算笔账——50K 上下文每层 KV cache 多少?

调节上下文长度,看 CSA 层、HCA 层、滑窗、Indexer 各自占多少:

50K tokens
CSA 层(30 层)
HCA 层(31 层)
V4-Pro 合计
vs MHA 标准

3.8 Other Details(论文 2.3.3):三个容易忽略的小设计

Query / KV Entry Normalization

对 Query 和压缩 KV entries 做额外 RMSNorm,避免 attention logits 爆炸。 这是 V4 不需要再用 QK-Clip 技巧的原因。

Partial RoPE

只在每条 KV 的最后 64 维应用 RoPE。Core attention 输出会带绝对位置嵌入, 所以对 output 也施加位置 -i 的 RoPE,让"距离"重新注入。

Attention Sink

在 softmax 分母里加可学习的 exp(sink)——给模型一个"弃权票箱"。 对长上下文几乎是必需品,OpenAI GPT-5 也用了。

sh,i,j = exp(zh,i,j) / ( Σk exp(zh,i,k) + exp(z'h) ) ← 多出来的 exp(z'h) 就是弃权票箱

3.9 训练 vs 推理:一个比喻

V3.2 DSA:戴眼镜上街

一个看惯了高清电视的人,平时戴个轻便的近视眼镜上街。眼镜让他看世界省力, 但他大脑里"世界长什么样"的模型来自高清电视。眼镜和大脑会有微妙的不一致。

V4 CSA/HCA:眼镜长在脑子里

一个从小就近视、从小就戴这副眼镜的人。他大脑里"世界长什么样"就是这副眼镜下的样子。 眼镜和大脑长在一起。

这就是 V4 推理 FLOPs 砍到 V3.2 的 27%、KV cache 砍到 10% 的根本原因—— 不是眼镜更好,是眼镜从一开始就长在脑子里