本站内容由 AI 生成,可能存在错误。如发现问题,欢迎到 GitHub Issues 反馈。

Qwen3-Coder-Next 架构解析:当 SSM、Attention 与 MoE 三合一

Qwen3-Coder-Next 架构解析:当 SSM、Attention 与 MoE 三合一

更新于 2026-04-23

前三篇文章分别介绍了 MoESSMHybrid 架构 的基本原理。本文以一个真实的生产模型 Qwen3-Coder-Next 80B 为案例,展示这三种技术如何在同一个模型中协同工作。

Qwen3-Coder-Next 是一个 79.7B 参数的 Hybrid MoE 模型,每个 token 仅激活约 3B 参数——参数利用率仅 3.8%。它将 GatedDeltaNet(一种基于 delta rule 的线性注意力)、标准全注意力和 512-expert MoE 融合在 48 层中,是当前最复杂的混合架构之一。


1. 架构全景

Qwen3 3:1 混合层堆叠模式48 层混合堆叠:3:1 GatedDeltaNet / Full AttentionLayer0GatedDeltaNet1GatedDeltaNet2GatedDeltaNet3Full Attention4GatedDeltaNet5GatedDeltaNet6GatedDeltaNet7Full Attention44GatedDeltaNet45GatedDeltaNet46GatedDeltaNet47Full Attention36 层 GatedDeltaNet (75%)12 层 Full Attention (25%)3:1 混合比例 — 每 4 层为一个循环所有 48 层共享相同的 MoE FFN 结构,差异仅在注意力部分

1.1 核心参数

参数备注
总层数48block_count=48
层类型36 recurrent + 12 full attention3:1 交替
隐藏维度2048远小于典型 LLM(LLaMA-70B 为 8192)
总参数79.7B
活跃参数/token~3B仅 3.8% 被激活
MoE 配置512 experts, top-10+ 1 shared expert
Expert FFN 维度512小但多
上下文长度262,144256K tokens

1.2 3:1 混合层模式

48 层按固定模式交替——每 4 层为一个循环,前 3 层用 GatedDeltaNet(线性注意力),第 4 层用全注意力

Layer  0: GatedDeltaNet    ← recurrent
Layer  1: GatedDeltaNet
Layer  2: GatedDeltaNet
Layer  3: Full Attention    ← 每 4 层插入 1 层
Layer  4: GatedDeltaNet
...
Layer 47: Full Attention    ← 最后一层也是全注意力

这种 3:1 比例是 Hybrid 架构 中交替式范式的变体。对比 Jamba 的 7:1(Mamba:Attention),Qwen3-Coder-Next 给予全注意力更高的权重(25% vs 12.5%),这可能有助于 coding 任务中频繁需要的精确 token 检索。

关键设计:所有 48 层无论注意力类型如何,都共享相同的 MoE FFN 结构。层类型的差异仅在注意力部分。

1.3 GGUF 视角:一层长什么样?

在 llama.cpp 的 GGUF 格式中,模型的每一层由一组具名张量构成。以下是从实际 GGUF 文件中提取的两个代表性 block——一个 GatedDeltaNet 层和一个 Full Attention 层——让你直观看到每层的”物理构成”。

Block 0(GatedDeltaNet 层):

张量名                            形状              量化    用途
───────────────────────────────────────────────────────────────────
  # ── 注意力/SSM 部分 ──
blk.0.attn_norm.weight           [2048]            F32    注意力前 RMSNorm
blk.0.attn_qkv.weight           [2048, 8192]      Q4_K   Q+K+V 合并投影
blk.0.attn_gate.weight           [2048, 4096]      Q4_K   输出门控向量 z
blk.0.ssm_ba.weight              [2048, 64]        Q4_K   β+α 合并投影
blk.0.ssm_conv1d.weight          [4, 8192]         F32    1D 因果卷积核
blk.0.ssm_dt                     [32]              F32    时间步偏置 (dt_bias)
blk.0.ssm_a                      [32]              F32    状态衰减系数 (-exp(A))
blk.0.ssm_norm.weight            [128]             F32    SSM 输出 RMSNorm
blk.0.ssm_out.weight             [4096, 2048]      Q4_K   输出投影

  # ── MoE 部分(所有层相同结构)──
blk.0.post_attention_norm.weight [2048]            F32    MoE 前 RMSNorm
blk.0.ffn_gate_inp.weight        [2048, 512]       F32    Router(512 expert 打分)
blk.0.ffn_gate_exps.weight       [2048, 512, 512]  Q4_K   512 Expert gate 投影
blk.0.ffn_up_exps.weight         [2048, 512, 512]  Q4_K   512 Expert up 投影
blk.0.ffn_down_exps.weight       [512, 2048, 512]  Q6_K   512 Expert down 投影
blk.0.ffn_gate_shexp.weight      [2048, 512]       Q4_K   Shared Expert gate
blk.0.ffn_up_shexp.weight        [2048, 512]       Q4_K   Shared Expert up
blk.0.ffn_down_shexp.weight      [512, 2048]       Q6_K   Shared Expert down
blk.0.ffn_gate_inp_shexp.weight  [2048, 1]         F16    Shared Expert sigmoid 门控

Block 3(Full Attention 层):

张量名                            形状              量化    用途
───────────────────────────────────────────────────────────────────
  # ── 注意力部分(与 Block 0 完全不同)──
blk.3.attn_norm.weight           [2048]            F32    注意力前 RMSNorm
blk.3.attn_q.weight              [2048, 8192]      Q4_K   Q 投影(含 sigmoid gate)
blk.3.attn_k.weight              [2048, 512]       Q4_K   K 投影(2 heads × 256)
blk.3.attn_v.weight              [2048, 512]       Q6_K   V 投影(2 heads × 256)
blk.3.attn_q_norm.weight         [256]             F32    Q RMSNorm
blk.3.attn_k_norm.weight         [256]             F32    K RMSNorm
blk.3.attn_output.weight         [4096, 2048]      Q4_K   注意力输出投影

  # ── MoE 部分(与 Block 0 完全相同,省略)──
blk.3.ffn_*                      ...                      (同上)

对比两种层类型的关键差异:

差异GatedDeltaNet (Block 0)Full Attention (Block 3)
QKV 投影合并 attn_qkv [2048→8192]分开 attn_q/k/v
门控attn_gate(输出门控 z)Q 内置 sigmoid gate
独有张量ssm_*(6 个 SSM 相关张量)attn_q/k_norm(QK 归一化)
输出投影ssm_out [4096→2048]attn_output [4096→2048]
F32 敏感参数ssm_a, ssm_dt, ssm_conv1dattn_v 使用 Q6_K

注意 MoE 部分(ffn_* 开头的张量)在两种层中完全一致——这就是上文提到的”层类型差异仅在注意力部分”的具体体现。


2. GatedDeltaNet:线性注意力层

GatedDeltaNet 五步前向传播GatedDeltaNet 五步前向传播 衰减exp(α)⊙H 检索H̃·kₜ 差值vₜ − H̃kₜ 写入H̃ + β·k·δᵀ 读取Hₜ·qₜ隐藏状态矩阵 SS ∈ ℝ^(d_k × d_v) — 固定大小联想记忆S → 衰减+更新 → S' → 输出O(d²) 每步 — 无 N² 注意力矩阵Delta Rule:不直接写入 v,而是只写入修正量 v − Hk(精确覆写)

36 层 recurrent 层使用的不是标准 Mamba,而是 GatedDeltaNet——一种基于 delta rule 的线性注意力机制,状态是矩阵而非向量。

2.1 从 Mamba 到 Delta Rule

回顾 SSM 文章 中 Mamba 的状态更新:

ht=Aˉtht1+Bˉtxth_t = \bar{A}_t \cdot h_{t-1} + \bar{B}_t \cdot x_t

状态 hth_t 是一个 向量RN\mathbb{R}^N),新信息通过加法叠加到衰减后的旧状态上——这是 “additive update”。

DeltaNet (Yang et al., 2024) 将状态提升为 矩阵 HtRdk×dvH_t \in \mathbb{R}^{d_k \times d_v},使用 delta rule 更新:

Ht=(Iβtktkt)Ht1+βtvtktH_t = (I - \beta_t k_t k_t^\top) H_{t-1} + \beta_t v_t k_t^\top

状态矩阵 HH 可以看作一个联想记忆(associative memory)——“模糊的 key-value 存储”。将上式展开为等价的 delta 形式更容易理解更新的含义:

Ht=Ht1+βtkt(vtHt1kt)H_t = H_{t-1} + \beta_t \cdot k_t \left(v_t - H_{t-1} k_t\right)^\top

其中每一项都有明确的语义:

  • Ht1ktRdvH_{t-1} k_t \in \mathbb{R}^{d_v}:用当前 key ktk_t 查询状态矩阵,检索出”记忆中当前与 ktk_t 关联的旧 value”
  • vtRdvv_t \in \mathbb{R}^{d_v}:当前 token 投影得到的新 value——希望与 ktk_t 关联的目标值
  • vtHt1ktv_t - H_{t-1} k_t差值(delta)——新目标与旧记忆之间的误差
  • βtkt()\beta_t \cdot k_t (\cdots)^\top:将这个误差修正以外积形式写回状态矩阵

这就是 “delta rule” 名称的由来——不直接写入新 value vtv_t,而是只写入修正量 vtHt1ktv_t - H_{t-1}k_t。注意这里的 vtv_tHt1ktH_{t-1}k_t 虽然都是 Rdv\mathbb{R}^{d_v} 向量,但含义完全不同:前者来自当前输入的投影,后者是从历史压缩状态中检索出的旧值。

为什么 Ht1ktH_{t-1}k_t 能检索出”旧 value”?

如果你熟悉标准 Attention 的 softmax(QK)V\text{softmax}(QK^\top) \cdot V,可能会疑惑:以前不是先算 QK 相似度,再乘 V 才得到 value 吗?为什么这里 HH 乘以 kk 就直接得到 value 了?

关键在于 HH 是如何构建的。以最简单的累加更新为例:Ht=Ht1+ktvtH_t = H_{t-1} + k_t v_t^\top,展开后 HH 就是所有历史 key-value 对的外积之和

Ht1=i=1t1kiviH_{t-1} = \sum_{i=1}^{t-1} k_i \, v_i^\top

当你用当前 ktk_t 去查询时:

Ht1kt=(i=1t1kivi)kt=i=1t1(kikt)key 相似度viH_{t-1} k_t = \left(\sum_{i=1}^{t-1} k_i v_i^\top\right) k_t = \sum_{i=1}^{t-1} \underbrace{(k_i^\top k_t)}_{\text{key 相似度}} \, v_i

最右边正是用 key 之间的点积相似度对所有历史 value 做加权求和——这与标准 Attention 的 softmax(qki)vi\sum \text{softmax}(q^\top k_i) \cdot v_i 本质相同,区别仅在于:(1) 没有 softmax 归一化;(2) 所有历史 K/V 被压缩进了固定大小的矩阵 HH,一次矩阵-向量乘法就完成了检索,复杂度 O(1)O(1) 而非 O(n)O(n)

对比两种更新策略:

策略更新方式效果
Additive(Mamba)H+=vkH \mathrel{+}= v \cdot k^\top新旧值叠加,信息逐渐模糊
Delta ruleH+=βk(vnewHk)H \mathrel{+}= \beta \cdot k(v_{new} - Hk)^\top旧值被修正为新值,精确覆写

βt=1\beta_t = 1 时,更新后 Htkt=vtH_t k_t = v_t——完美覆写。这使 DeltaNet 在需要精确记住最近 key-value 对的任务(如 in-context recall)中优于 Mamba。

Gated DeltaNet (Yang, Kautz & Hatamizadeh, 2024) 在 delta rule 基础上增加逐元素衰减门控:

H~t1=exp(αt)Ht1,Ht=H~t1+βtkt(vtH~t1kt),ot=Htqt\tilde{H}_{t-1} = \exp(\alpha_t) \odot H_{t-1}, \quad H_t = \tilde{H}_{t-1} + \beta_t \cdot k_t \left(v_t - \tilde{H}_{t-1} k_t\right)^\top, \quad o_t = H_t \, q_t

与 DeltaNet 的区别:更新前先对旧状态施加逐元素指数衰减(αt\alpha_t 依赖输入,每个状态元素有独立衰减速率),然后在衰减后的状态上执行 delta rule 更新,最后用查询向量 qtq_t 读取输出。完整的五步流程:

  1. 衰减H~t1=exp(αt)Ht1\tilde{H}_{t-1} = \exp(\alpha_t) \odot H_{t-1} — 对旧状态施加逐元素指数衰减
  2. 检索旧值H~t1kt\tilde{H}_{t-1} k_t — 用 ktk_t 从衰减后的状态中查询旧 value
  3. 计算差值vtH~t1ktv_t - \tilde{H}_{t-1} k_t — 新目标与旧记忆之间的误差(delta)
  4. 写入修正Ht=H~t1+βtkt()H_t = \tilde{H}_{t-1} + \beta_t \cdot k_t (\cdots)^\top — 将修正以外积写回状态
  5. 读取输出ot=Htqto_t = H_t \, q_t — 用 qtq_t 从更新后的状态中检索本层输出

注意 qtq_tktk_t 虽然都来自同一个投影(attn_qkv),但角色不同:ktk_t 是写入地址(决定 value 存到状态矩阵的哪个位置),qtq_t 是读取地址(决定从状态矩阵中检索什么信息作为输出)。两者分离使写入和读取可以关注不同的特征——这与标准 Attention 中 Q(查询)和 K(被查询)的分工一致。

衰减门控使模型能主动遗忘不再需要的信息(exp(αt)<1\exp(\alpha_t) < 1 使旧状态逐渐衰减),同时 delta rule 保证了对需要记住的信息的精确覆写——灵活遗忘 + 精确覆写,这是 GatedDeltaNet 相比纯 Mamba 的核心优势。

2.2 完整数据流与输入处理

2.1 节给出了 Gated DeltaNet 的完整公式(五步:衰减 → 检索 → 差值 → 写入 → 读取),但公式与实际模型之间还有一段距离:每个 GGUF 张量对应哪一步?数据从输入到输出经过了哪些变换?本节先给出整体流程图,后续各节(2.3–2.7)再逐一展开每个环节的细节。

前向传播流程

┌───────────────── GatedDeltaNet 层前向传播 ──────────────────┐
│                                                              │
│  ① 三路并行投影                                              │
│     x ─→ attn_qkv  [2048→8192] ─→ qkv [8192]              │
│     x ─→ attn_gate [2048→4096] ─→ z [4096]    (输出门控)   │
│     x ─→ ssm_ba    [2048→64]  ─→ β+α [64]    (衰减+写入)  │
│                                                              │
│  ② Conv1d 时序融合                                           │
│     [conv_state; qkv] ─→ Conv1d(k=4) ─→ SiLU ─→ qkv'      │
│      ↑ 前 3 token 缓存                                      │
│                                                              │
│  ③ 拆分 + 预处理                                             │
│     qkv' → Q [128×16] + K [128×16] + V [128×32]            │
│     Q ← L2Norm(Q) / √d_v     → 公式中 q_t                  │
│     K ← L2Norm(K)            → 公式中 k_t                  │
│     Q, K repeat 16→32 heads  → 与 V 的 32 heads 对齐        │
│     β ← sigmoid(β_raw)       → 公式中 β_t ∈ [0,1]          │
│     gate ← softplus(α + dt_bias) × (-A)                     │
│                               → 公式中 exp(α_t)             │
│                                                              │
│  ④ Delta Rule 状态更新                                       │
│     H̃ = exp(gate) ⊙ H_{t-1}       ← delta_state [128,4096]│
│     H_t = H̃ + β · k_t(v_t − H̃k_t)ᵀ                       │
│     out_t = H_t · q_t                                        │
│                                                              │
│  ⑤ 输出门控                                                  │
│     output = ssm_out( ssm_norm(out) ⊙ SiLU(z) )             │
│                                                              │
└──────────────────────────────────────────────────────────────┘

张量与公式的对应关系

GGUF 张量形状量化对应公式 / 作用
attn_qkv[2048,8192][2048, 8192]Q4_K生成 q,k,vq, k, v 的原始值(经 Conv1d 后拆分)
attn_gate[2048,4096][2048, 4096]Q4_K输出门控 zz,步骤⑤中控制 SSM 输出的信息流
ssm_conv1d[4,8192][4, 8192]F32因果卷积核,步骤②中融合前 3 token 的局部上下文
ssm_ba[2048,64][2048, 64]Q4_K生成 βt\beta_t(写入强度)和 αt\alpha_t(衰减率)
ssm_dt[32][32]F32时间步偏置 dt_bias\text{dt\_bias},步骤③中加到 α\alpha
ssm_a[32][32]F32exp(Alog)-\exp(A_{\log}),确保 exp(gate)<1\exp(\text{gate}) < 1 实现衰减
ssm_norm[128][128]F32步骤⑤中输出的 RMSNorm(注意:不是 zero-centered 变体)
ssm_out[4096,2048][4096, 2048]Q4_K步骤⑤中将门控后的输出投影回隐藏维度

输入投影(步骤①)

每层对输入 xx 做三路并行投影:

投影维度量化输出拆分
attn_qkv204881922048 \to 8192Q4_KQ [128×16][128 \times 16] + K [128×16][128 \times 16] + V [128×32][128 \times 32]
attn_gate204840962048 \to 4096Q4_K门控向量 zz [128×32][128 \times 32]
ssm_ba2048642048 \to 64Q4_KBeta + Alpha 合并(按 K-head 分组)

注意 非对称头结构:Q heads = K heads = 16, V heads = 32,head_dim = 128。Q 和 K 的 head 数量相同,但 V 是它们的 2 倍。

这会带来一个问题:delta rule 的状态更新是 per-head 操作,Q/K/V 的 head 数必须对齐。代码中的解决方案是将 Q 和 K 从 16 heads repeat 扩展到 32 heads——每个 Q/K-head 复制 2 次,使其与 V 的 32 heads 一一对应。这与全注意力中 GQA 的思路相同:少量 K-head 共享给多个 “工作 head”,节省 Q/K 投影的参数量。

扩展后,模型有 32 组独立的 delta rule 状态,每组状态矩阵为 H(i)R128×128H^{(i)} \in \mathbb{R}^{128 \times 128},总状态大小为 32×128×128=128×409632 \times 128 \times 128 = 128 \times 4096。更多 V-heads 意味着更大的状态容量,而 Q/K 只是”地址”,用更少的参数即可。

为什么需要 Conv1d?(步骤②)

attn_qkv 投影后得到 8192 维的 QKV 向量,但它仅包含当前 token xtx_t 的信息。然而在步骤④的 delta rule 状态更新中,ktk_tvtv_t 的质量直接决定了写入状态矩阵的 key-value 关联有多好。如果 kt,vtk_t, v_t 完全依赖单个 token,表达力就会受限。

Conv1d 弥补了这个缺陷:通过 kernel=4 的因果卷积,当前 token 的 QKV 在进入 delta rule 之前就融合了前 3 个 token 的信息

qkv=SiLU ⁣(Conv1ddepthwise ⁣([conv_state前 3 token;  qkv当前 token],  kernel=4))\text{qkv}' = \text{SiLU}\!\left(\text{Conv1d}_{\text{depthwise}}\!\left([\underbrace{\text{conv\_state}}_{\text{前 3 token}};\; \underbrace{\text{qkv}}_{\text{当前 token}}],\; \text{kernel}=4\right)\right)

这带来两个关键好处:

  1. 无损的短程上下文:最近 3 个 token 的信息通过卷积直接注入 Q/K/V,无需经过状态矩阵 HH 的有损压缩。这意味着对于 4-token 窗口内的依赖,模型拥有精确的原始信息
  2. 与递推互补:Conv1d 负责精确的短程依赖(4 token 窗口),delta rule 负责长程依赖(通过状态矩阵 HH 压缩表示)——两种机制分工明确

ssm_conv1d.weight [4, 8192]逐通道(depthwise)卷积核——8192 个通道各有独立的 4 元素卷积核,不混合 Q/K/V 之间的信息,只在时间维度上做局部融合。运行时需要维护 conv_state [3, 8192] 缓存(见 2.7 节),存储前 3 个 token 的 qkv 值。

这种 project → conv1d → recurrence 的三段式设计继承自 Mamba——在 SSM 文章 中介绍的相同模式。Conv1d + SiLU 之后,输出被拆分为 Q、K、V 三组向量,进入后续的归一化和状态更新流程。

2.3 Q/K 归一化与 Beta 激活

对应 2.1 公式qt,ktq_t, k_t 的归一化和 βt[0,1]\beta_t \in [0,1] 的激活——进入 delta rule 之前的预处理。

Conv1d 拆分出 Q、K、V 后,还需经过几步关键处理才能进入 delta rule:

  • L2 归一化:Q 和 K 各自做 L2 norm,将向量投射到单位球面上,稳定 delta rule 的 key-value 关联
  • Q 缩放QQ/dvQ \leftarrow Q / \sqrt{d_v},防止点积随维度增大而过大
  • Beta sigmoidβtσ(βt)\beta_t \leftarrow \sigma(\beta_t),将写入强度限制在 [0,1][0, 1] 范围内

2.4 衰减门控

对应 2.1 公式:步骤 1 的 H~t1=exp(αt)Ht1\tilde{H}_{t-1} = \exp(\alpha_t) \odot H_{t-1} — 构造衰减系数 exp(αt)\exp(\alpha_t),控制旧状态的逐元素遗忘程度。

门控 αt\alpha_t 和写入强度 βt\beta_t 来自同一个投影:

参数形状含义
ssm_ba2048642048 \to 64Beta 和 Alpha 的合并投影(按 K-head 分组)
ssm_dt[32][32]时间步偏置(可学习 bias)
ssm_a[32][32]状态衰减系数,存储为 exp(Alog)-\exp(A_{\log})

ssm_ba 的 64 维输出按 K-head 分组后拆分:16 个 K-head × 4 维 = 64,每组 4 维中前 2 维是 beta(对应该 K-head 的 2 个 V-head),后 2 维是 alpha。拆分后 beta 和 alpha 各有 32 个值(每个 V-head 一个)。

gatet=softplus(αt+dt_bias)×(A)\text{gate}_t = \text{softplus}(\alpha_t + \text{dt\_bias}) \times (-A)

其中 softplus(x)=ln(1+ex)\text{softplus}(x) = \ln(1 + e^x)A-A 确保门控值为负,使 exp(gatet)<1\exp(\text{gate}_t) < 1 实现指数衰减。这类似于 Mamba 中 Δ\Delta 参数的作用——控制每步的信息保留程度。

2.5 分块并行计算

分块并行计算分块并行计算(Prefill 模式)输入序列 [tok₀ ... tok₂₅₅] → 4 个 chunk × 64 tokensChunk 064×64intra-chunk 注意力SChunk 164×64intra-chunk 注意力SChunk 264×64intra-chunk 注意力SChunk 364×64intra-chunk 注意力inter-chunk: 状态 S 串行传递Prefill并行 intra-chunk + 串行 state 传递Decode纯 recurrence, O(d²) per token

对应 2.1 公式:步骤 1–5 的实际执行——衰减、状态更新 Ht=H~+βtkt(vtH~kt)H_t = \tilde{H} + \beta_t k_t(v_t - \tilde{H}k_t)^\top、输出读取 ot=Htqto_t = H_t q_t

自回归模式(decode,每次 1 token)直接递推状态:

H~=exp(gatet)Ht1,Ht=H~+βtkt(vtH~kt),outt=Htqt\tilde{H} = \exp(\text{gate}_t) \odot H_{t-1}, \quad H_t = \tilde{H} + \beta_t \cdot k_t (v_t - \tilde{H} k_t)^\top, \quad \text{out}_t = H_t \cdot q_t

分块并行模式(prefill,多 token)将序列分为长度 64 的 chunk。chunk 内构建带衰减的因果注意力矩阵:

Mij=exp ⁣(l=j+1igatel),ijM_{ij} = \exp\!\left(\sum_{l=j+1}^{i} \text{gate}_l\right), \quad i \geq j intra_chunk=(MQK)V\text{intra\_chunk} = (M \odot Q K^\top) \cdot V

chunk 之间通过状态矩阵累积传播。这种策略类似 Mamba-2 的 SSD 算法——在保持线性递推语义的同时利用 GPU 并行性。

2.6 输出门控

对应 2.1 公式ot=Htqto_t = H_t q_t 之后的后处理——delta rule 的原始输出需要经过门控和投影才能成为层输出。

SSM 输出先经过 RMSNorm,再与 SiLU 激活的门控向量 zz 逐元素相乘:

output=RMSNorm(attn_out)SiLU(z)\text{output} = \text{RMSNorm}(\text{attn\_out}) \odot \text{SiLU}(z)

最后通过输出投影 ssm_out (409620484096 \to 2048) 回到隐藏维度。

2.7 缓存

对应 2.1 公式:状态矩阵 HtH_t 和 Conv1d 历史在 token 之间的持久存储——递推机制跨 token 传递信息的基础。

每层维护两种固定大小的状态:

缓存类型形状大小(f32)用途
delta_state[128,4096,batch][128, 4096, \text{batch}]~2 MB/序列递推状态矩阵 HtH_t
conv_state[3,8192,batch][3, 8192, \text{batch}]~96 KB/序列Conv1d 历史(最近 3 token)

与全注意力的 KV cache(随序列长度线性增长)不同,delta_state 是 固定大小 的——这正是 SSM 的核心优势。代价是矩阵状态比 Mamba 的向量状态占用更多空间,但换来了更强的联想记忆能力。


3. 门控全注意力层

门控全注意力层门控全注意力层(每 4 层出现 1 次)Input x[2048]RMSNormQ proj → Q + G2×d_head, sigmoid 门控K proj2 heads × 256V proj2 heads × 256GQA Attentionsoftmax(Q·Kᵀ/√d)·Vσ(G)sigmoid 门控输出投影[4096 → 2048]关键差异• Sigmoid gate on Q• GQA 16:2 比例• Partial RoPE (64/256 dims)• QK RMSNorm

每 4 层出现一次的全注意力层使用 sigmoid 门控的 GQA,与标准 Transformer attention 有几个关键差异。

3.1 Gated Q 投影

Q 投影的输出维度是 head_dim 的 2 倍

attn_q(x)R8192QR256×16query+GR256×16gate\text{attn\_q}(x) \in \mathbb{R}^{8192} \to \underbrace{Q \in \mathbb{R}^{256 \times 16}}_{\text{query}} + \underbrace{G \in \mathbb{R}^{256 \times 16}}_{\text{gate}}

query 和 gate 各自独立经过 RMSNorm,query 再经过 RoPE。注意力计算完成后,输出乘以 gate 的 sigmoid:

attn_out=Attention(Q,K,V)σ(G)\text{attn\_out} = \text{Attention}(Q, K, V) \odot \sigma(G)

这种 sigmoid 门控 让每个 attention head 可以学习性地”关闭”某些输出维度——比固定的注意力输出更灵活。

3.2 GQA:16 Q Heads, 2 KV Heads

投影维度量化Head 配置
attn_k20485122048 \to 512Q4_K2 heads × 256 head_dim
attn_v20485122048 \to 512Q6_K2 heads × 256 head_dim

这是 8:1 的 GQAGrouped-Query Attention)——16 个 Q heads 共享 2 组 KV。极端的 GQA 比例大幅减少 KV cache,但由于全注意力层仅占 25%,且 recurrent 层不需要 KV cache,整体 cache 已经很小。

3.3 Partial RoPE

位置编码仅应用于 head_dim 的前 64 维(rope.dimension_count=64):

partial_rotary_factor=64256=0.25\text{partial\_rotary\_factor} = \frac{64}{256} = 0.25

75% 的 head dimensions 不参与位置编码,保持位置无关——这些维度专注于语义内容表征。RoPE 使用 NeoX 布局,θ=5×106\theta = 5 \times 10^6(高 base frequency 支持长上下文外推)。

3.4 QK Norm

Q 和 K 在 RoPE 之前都经过 RMSNorm:

Q=RoPE(RMSNorm(Q)),K=RoPE(RMSNorm(K))Q' = \text{RoPE}(\text{RMSNorm}(Q)), \quad K' = \text{RoPE}(\text{RMSNorm}(K))

在 head_dim = 256 这种大维度下,QK Norm 对稳定 attention score 至关重要——防止 QKQ \cdot K^\top 的方差随维度增长而过大。


4. MoE:512 Expert Top-10 路由

MoE 512 Expert Top-10 路由MoE 路由:512 Experts, Top-10 选择输入 token[2048]Routersoftmax512 expert 打分→ Top-1010 个选中 Expert 并行计算SiLU(W_gate·x) ⊙ W_up·x → W_down → 加权求和Shared Expert始终激活+MoE 输出512 experts × 1.1M params = 562M expert 参数,但每 token 仅激活 10 个总参数 79.7B → 活跃参数 ~3B (3.8%) — 内存存全部,计算仅用部分

所有 48 层(不论注意力类型)都使用相同的 MoE FFN 结构。

4.1 Router 机制

Router 是一个全精度(F32)线性投影,将隐藏状态映射到 512 维的 expert 空间:

logits=Wrouterx,WrouterR512×2048\text{logits} = W_{\text{router}} \cdot x, \quad W_{\text{router}} \in \mathbb{R}^{512 \times 2048} weights=softmax(logits),selected=TopK(weights,k=10)\text{weights} = \text{softmax}(\text{logits}), \quad \text{selected} = \text{TopK}(\text{weights}, k=10)

选中的 10 个 expert 的 routing weight 重新归一化(norm_top_k_prob=true):

wi=wijTopKwjw_i' = \frac{w_i}{\sum_{j \in \text{TopK}} w_j}

Router 使用 F32 精度是有意为之——routing 决策的微小误差会被 expert 选择放大,导致完全不同的计算路径。

4.2 Expert FFN

每个 expert 是标准的 SiLU-gated FFN,但维度极小:

experti(x)=Wdown(i)[SiLU ⁣(Wgate(i)x)Wup(i)x]\text{expert}_i(x) = W_{\text{down}}^{(i)} \left[ \text{SiLU}\!\left(W_{\text{gate}}^{(i)} x\right) \odot W_{\text{up}}^{(i)} x \right]
投影维度变换量化每层大小(×512 experts)
ffn_gate_exps20485122048 \to 512Q4_K288 MB
ffn_up_exps20485122048 \to 512Q4_K288 MB
ffn_down_exps5122048512 \to 2048Q6_K420 MB
合计996 MB

ffn_down_exps 使用更高精度的 Q6_K——因为 down projection 直接影响残差连接的数值精度。

4.3 Shared Expert

除 10 个 routed experts 外,每层还有一个 shared expertDeepSeek 风格),所有 token 必经:

投影维度量化
ffn_gate_shexp20485122048 \to 512Q4_K
ffn_up_shexp20485122048 \to 512Q4_K
ffn_down_shexp5122048512 \to 2048Q6_K

Shared expert 的输出还经过 sigmoid gate(ffn_gate_inp_shexp)控制贡献:

shared_out=σ(Wgatex)FFNshared(x)\text{shared\_out} = \sigma(W_{\text{gate}} \cdot x) \cdot \text{FFN}_{\text{shared}}(x)

最终 MoE 输出 = routed experts 加权和 + shared expert 输出。Shared expert 保证基础能力(通用知识、语法)不因 routing 分散而丢失。

4.4 稀疏度分析

指标Qwen3-Coder-NextDeepSeek-V3Mixtral
Expert 数量5122568
Top-K1082
激活比例1.95%3.1%25%
Shared expert11
总参数79.7B671B47B
活跃参数~3B~37B~13B

512 expert top-10 提供了极细粒度的 expert 专业化——每个 expert 的 FFN 仅 512 维,可以高度专精于特定的 token pattern。


5. 层结构与数据流

5.1 单层完整前向传播

每层遵循 Pre-Norm 双残差 结构:

h1=x+Attention(RMSNormattn(x))h2=h1+MoE(RMSNormpost(h1))\begin{aligned} h_1 &= x + \text{Attention}(\text{RMSNorm}_{\text{attn}}(x)) \\ h_2 &= h_1 + \text{MoE}(\text{RMSNorm}_{\text{post}}(h_1)) \end{aligned}

Attention 根据层类型切换为 GatedDeltaNet 或 Full Attention,MoE 在所有层中保持一致。

以 recurrent 层为例的完整数据流:

Input x [2048]

  ├─ RMSNorm (attn_norm)
  │    ├─ QKV Projection → Conv1d(k=4) + SiLU → Q, K, V
  │    ├─ Gate Projection → z
  │    ├─ Beta/Alpha → β, gate
  │    ├─ State Update: H = exp(gate) ⊙ H_prev + β·k·vᵀ
  │    ├─ Output: out = H · q
  │    ├─ Gated: RMSNorm(out) ⊙ SiLU(z)
  │    └─ SSM Out Projection [4096 → 2048]

  ├─ Residual: h₁ = x + attn_out

  ├─ RMSNorm (post_attention_norm)
  │    ├─ Router [2048 → 512] → Softmax → TopK(10)
  │    ├─ 10× Expert FFN: SiLU(gate·x) ⊙ up·x → down
  │    ├─ Weighted Sum (normalized weights)
  │    ├─ Shared Expert FFN + Sigmoid Gate
  │    └─ moe_out = routed + shared

  └─ Residual: h₂ = h₁ + moe_out → Output [2048]

5.2 Zero-Centered RMSNorm

所有 RMSNorm 层(SSM 内部的 ssm_norm 除外)使用 zero-centered 变体:

RMSNorm(x)=xRMS(x)(1+w)\text{RMSNorm}(x) = \frac{x}{\text{RMS}(x)} \cdot (1 + w)

权重存储时已加 1(GGUF 中 wstored=woriginal+1w_{\text{stored}} = w_{\text{original}} + 1)。当 woriginal=0w_{\text{original}} = 0 时,归一化退化为恒等映射——使初始化时信号直接穿透,有助于训练稳定性。

5.3 Embedding 与 Output

组件维度量化
token_embd1519362048151936 \to 2048Q4_K
output_norm[2048][2048]F32
output20481519362048 \to 151936Q6_K

词汇表大小 151,936。输出投影使用 Q6_K 高精度量化——logits 精度直接影响 token 采样质量。


6. 量化与权重分布

Qwen3 权重分布权重分布:97% 是稀疏激活的 MoE ExpertMoE Experts96% — ~47.8 GBDense 层2.4% — ~1.2 GBEmbeddings0.8% — ~0.4 GB总参数79.7B每 token 活跃~3B (3.8%)Q4_K_M~18 GBDense 权重仅 1.2 GB — 可轻松放入任何 GPUMoE expert 占绝对主体,是 GPU/CPU offloading 策略的核心优化目标

6.1 Q4_K_M 混合量化策略

Q4_K_M 并非统一量化,而是根据组件敏感度选择不同级别:

组件量化原因
Expert gate/upQ4_K数量最多(512×48),积极压缩
Expert down, attn_vQ6_K直接影响残差/输出精度
Dense attention/SSMQ4_K参数量小
Router, NormsF32精度关键(routing 决策、归一化)
SSM 参数 (A, dt, conv1d)F32衰减率和卷积需要高精度
Shared expert gateF16标量门控,折中精度

6.2 权重分布:97% 是 MoE Expert

每层权重构成极度不对称:

组件每层大小占比
MoE Experts (512个)~996 MB97%
Dense (Attention/SSM + Shared Expert + Norms)~25 MB3%

全模型级别:

组件大小占比
48 层 MoE experts~47.8 GB96%
48 层 dense~1.2 GB2.4%
Embedding + Output~0.4 GB0.8%
总计~49.4 GB

这种极端分布意味着:dense 权重仅 1.2 GB,可以轻松全部放入任何 GPU。MoE expert 占绝对主体,是 GPU/CPU offloading 策略的核心优化目标。


7. 与其他 Hybrid 模型的对比

特征Jamba 52BZamba2 2.7BHymba 1.5BQwen3-CN 80B
SSM 类型MambaMamba2Mamba2GatedDeltaNet
融合方式交替 7:1共享 Attn并行 heads交替 3:1
MoE16E, top-2512E, top-10
总参数52B2.7B1.5B79.7B
活跃参数12B2.7B1.5B~3B
Attn 层占比12.5%~15%50%25%
状态类型向量向量向量+KV矩阵
KV cache 层数10/802 shared全部12/48

Qwen3-Coder-Next 的独特之处:

  1. GatedDeltaNet 替代 Mamba:矩阵状态 + delta rule 提供更强的联想记忆
  2. 极端 MoE 稀疏度:512 experts 是公开模型中最多的之一,配合极小的 expert FFN 维度(512)
  3. 3:1 非 7:1:更高的全注意力比例,可能为 coding 场景的精确检索优化
  4. 隐藏维度极小(2048):通过超大 expert 数量而非宽隐藏维度来扩展容量

总结

Qwen3-Coder-Next 80B 将 SSM、Attention 和 MoE 三种范式深度融合:

组件技术选择作用
36 层 GatedDeltaNet矩阵状态 + delta rule + 指数衰减门控线性复杂度的长序列建模
12 层 Full AttentionSigmoid 门控 + 8:1 GQA + Partial RoPE精确 token 检索与 ICL
48 层 MoE512 experts top-10 + shared expert参数效率:80B 参数, 3B 计算

这种设计反映了当前大模型架构的趋势:不再追求单一机制的极致,而是组合多种互补机制。线性注意力提供效率,全注意力提供精度,MoE 提供参数-计算解耦——每种技术补偿其他技术的弱点。

延伸阅读