LLM LENS · 模型结构笔记

DeepSeek-V4.1-Flash 结构说明

552B 主干参数的原生多模态 MoE 模型:非对称 Causal Encoder–Decoder(CED)+ 压缩稀疏注意力 CSA² + FP4 KV Cache + Hyper-Connections + Engram 参数化记忆。 核心收益:Prefill 计算量近乎减半、Global KV Cache 从 3514 → 890 Bytes/token(降低约 75%)。

✅ 已与官方开源发布(HuggingFace)逐项核对: config.json、inference/model.py / engram.py / vision.py、 model.safetensors.index.json(96,085 张量 / 475.24 GiB / 48 分片,全部一致); 并补充了阅读推理代码才能确认的实现级细节。

1总体架构

模型类型 DeepseekV41ForCausalLM,由语言主干(40 层)、ViT 视觉塔(32 层)、 aligner 与 3 层 DSpark MTP 草稿层组成。语言主干被切成两段: L0–L19 是 Causal Encoder,L20–L39 是 Decoder——这是理解全模型所有设计的出发点。

图像输入
vision.*:32 层 ViT(hidden 1024、16 头、patch 14)→ aligner(3×3 邻域拼 9216 → 5120),经 image_start/end/newline 边界嵌入插入文本流
文本输入
embed.weight:129,280 × 5120(BF16,与 LM Head 不共享)
↓
Causal Encoder
L0–L19
20 层 Block(latent attention + MoE)。L0–L1 纯滑窗(SWA 128); L2–L19 压缩率 m=2。
CSA² 源层:compressor / indexer 在 L2、L8、L14(Full 模式),逐层产 main KV 与 Top-512; Engram 哈希记忆挂在 L1、L14。
↓ encoder 末层输出 H₂₀ 经 L20 的 compressor 投影为 decoder 全部 global KV(仅一份,全 decoder 共享)
Decoder
L20–L39
20 层 Block,压缩率 m=1(不压缩 main KV)。global KV 全 decoder 共享一份: 仅 L20 为 Full(compressor 吃第 20 层注意力子层输入); L24、L28、L32、L36 为 Reindex(复用 KV,本层 indexer Q 重选 Top-K); 其余 15 层为 Reuse(KV 与 Top-K 全复用)。
↓
输出
先用 hc_pre 把 4 份 HC 副本合并回单流 → norm(最终 RMSNorm)→ head.weight:129,280 × 5120(logits 以 fp32 计算)
草稿(推理加速)
mtp.0/1/2:3 层 DSpark MTP(block_size=5 块级草稿,各含注意力 + 128 专家 MoE);mtp.2 独有 markov_head(一阶马尔可夫 logit 偏置)与 confidence_head(草稿置信度)
Encoder(L0–L19) Decoder(L20–L39) Engram DSpark MTP 视觉塔
六项架构技术的分工:CED 降低 Prefill 计算;CSA² 跨层复用 KV 与稀疏索引; FP4 Main KV 压缩单个 KV Entry;Single-Pass mHC 把激活内存流量降到理论下界; Engram 把静态局部知识从主干计算中解耦;DSpark 做推测解码。

1.2 逐层依赖详图(悬停格子,查看该层的产出与跨层依赖)

每层都自产(不跨层共享):64 头低秩 Q(wq_a→q_norm→wq_b)、SWA 滑窗 KV(128 槽环形,FP8)、 MoE FFN(384 选 6 + 1 共享专家)、HC 混合系数。跨层共享的只有 CSA² 四件套:main KV / index K / Top-512 / 候选池, 且总是由组首的 Full / Reindex 层产出、组内后续层复用——虚线框即共享范围。

Encoder
L0–L19
纯 SWA 层(compress_ratio=0,θ=10000 无 YaRN)
L0
纯 SWA
L0 · Encoder · 纯滑窗
  • compress_ratio=0:只有 128 滑窗,无压缩 KV / indexer
  • RoPE:θ=10000,禁用 YaRN
  • 不依赖任何前序层的 KV / 索引
E
L1
纯 SWA
L1 · Encoder · 纯滑窗 + Engram
  • 同 L0:纯 SWA,θ=10000 无 YaRN
  • 块入口(attention 之前)先执行 Engram:n-gram 哈希查表(3.84 亿 × 256,FP8)门控写入 4 份 HC 残差流
组 1 · m=2(源层 L2)
L2
Full
L2 · Encoder · Full(组 1 首层)
  • m=2:compressor 把 2 个 token 经 softmax 门控池化成 1 个 512 维 latent
  • 产出:main KV(FP4,288 B/条)+ index K(128 维,FP4,68 B/条)+ Top-512
  • 产出供 L3–L7 复用
  • RoPE:θ=160000 + YaRN(整层共用)
L3
Reuse
L3 · Encoder · Reuse(组 1)
  • m=2;复用 L2 的 main KV / index K / Top-512
  • 不跑 compressor / indexer
L4
Reuse
L4 · Encoder · Reuse(组 1)
  • 复用 L2 的 main KV / index K / Top-512
L5
Reuse
L5 · Encoder · Reuse(组 1)
  • 复用 L2 的 main KV / index K / Top-512
L6
Reuse
L6 · Encoder · Reuse(组 1)
  • 复用 L2 的 main KV / index K / Top-512
L7
Reuse
L7 · Encoder · Reuse(组 1)
  • 复用 L2 的 main KV / index K / Top-512
组 2 · m=2(源层 L8)
L8
Full
L8 · Encoder · Full(组 2 首层)
  • m=2;自产 main KV / index K / Top-512(覆盖 L2 的缓存槽位)
  • 产出供 L9–L13 复用
L9
Reuse
L9 · Encoder · Reuse(组 2)
  • 复用 L8 的 main KV / index K / Top-512
L10
Reuse
L10 · Encoder · Reuse(组 2)
  • 复用 L8 的 main KV / index K / Top-512
L11
Reuse
L11 · Encoder · Reuse(组 2)
  • 复用 L8 的 main KV / index K / Top-512
L12
Reuse
L12 · Encoder · Reuse(组 2)
  • 复用 L8 的 main KV / index K / Top-512
L13
Reuse
L13 · Encoder · Reuse(组 2)
  • 复用 L8 的 main KV / index K / Top-512
组 3 · m=2(源层 L14)
E
L14
Full
L14 · Encoder · Full(组 3 首层)+ Engram
  • 块入口先执行第二个 Engram(位置更深,留出更长的 Host Memory 预取隐藏窗口)
  • m=2;自产 main KV / index K / Top-512,供 L15–L19 复用
L15
Reuse
L15 · Encoder · Reuse(组 3)
  • 复用 L14 的 main KV / index K / Top-512
L16
Reuse
L16 · Encoder · Reuse(组 3)
  • 复用 L14 的 main KV / index K / Top-512
L17
Reuse
L17 · Encoder · Reuse(组 3)
  • 复用 L14 的 main KV / index K / Top-512
L18
Reuse
L18 · Encoder · Reuse(组 3)
  • 复用 L14 的 main KV / index K / Top-512
L19
Reuse
L19 · Encoder · Reuse(组 3)
  • 复用 L14 的 main KV / index K / Top-512
  • Encoder 最后一层:其输出 H₂₀ 是 Decoder 全部 global KV 的唯一来源(CED)
Decoder
L20–L39
组 4 · m=1 · 全 Decoder 共享一份 global KV(源层 L20)
L20
Full·候选池
L20 · Decoder · Full(组 4 首层 · 候选池源)
  • m=1:不压缩,每 token 一条 latent
  • compressor 吃本层注意力子层输入(即 Encoder 末层输出 H₂₀)——CED 的落地:全 Decoder 的 global KV 都由这里产出(唯一一份)
  • 产出:main KV + index K + Top-512,供 L21–L39 复用
  • 同时扫描全部可见上下文,产出共享候选池(2048 块 × 8 = 16,384 位置),供 L24/28/32/36 的 Reindex 使用
L21
Reuse
L21 · Decoder · Reuse
  • m=1;复用 L20 的 main KV / index K / Top-512
L22
Reuse
L22 · Decoder · Reuse
  • 复用 L20 的 main KV / index K / Top-512
L23
Reuse
L23 · Decoder · Reuse
  • 复用 L20 的 main KV / index K / Top-512
L24
Reindex
L24 · Decoder · Reindex
  • 复用 L20 的 main KV / index K
  • 用本层 indexer Q(wq_b 1280→4096)在 L20 的候选池(16,384 位置)内重选 Top-512
  • 新 Top-512 供 L25–L27 复用
L25
Reuse
L25 · Decoder · Reuse
  • 复用 L20 的 KV + L24 的 Top-512
L26
Reuse
L26 · Decoder · Reuse
  • 复用 L20 的 KV + L24 的 Top-512
L27
Reuse
L27 · Decoder · Reuse
  • 复用 L20 的 KV + L24 的 Top-512
L28
Reindex
L28 · Decoder · Reindex
  • 复用 L20 的 main KV / index K;本层 indexer Q 重选 Top-512
  • 新 Top-512 供 L29–L31 复用
L29
Reuse
L29 · Decoder · Reuse
  • 复用 L20 的 KV + L28 的 Top-512
L30
Reuse
L30 · Decoder · Reuse
  • 复用 L20 的 KV + L28 的 Top-512
L31
Reuse
L31 · Decoder · Reuse
  • 复用 L20 的 KV + L28 的 Top-512
L32
Reindex
L32 · Decoder · Reindex
  • 复用 L20 的 main KV / index K;本层 indexer Q 重选 Top-512
  • 新 Top-512 供 L33–L35 复用
L33
Reuse
L33 · Decoder · Reuse
  • 复用 L20 的 KV + L32 的 Top-512
L34
Reuse
L34 · Decoder · Reuse
  • 复用 L20 的 KV + L32 的 Top-512
L35
Reuse
L35 · Decoder · Reuse
  • 复用 L20 的 KV + L32 的 Top-512
L36
Reindex
L36 · Decoder · Reindex
  • 复用 L20 的 main KV / index K;本层 indexer Q 重选 Top-512
  • 新 Top-512 供 L37–L39 复用
T
L37
Reuse
L37 · Decoder · Reuse + DSpark target(1/3)
  • 复用 L20 的 KV + L36 的 Top-512
  • 块入口残差流(4 份 HC 副本求 mean)被收集,拼进 mtp.0.main_proj 的输入
T
L38
Reuse
L38 · Decoder · Reuse + DSpark target(2/3)
  • 复用 L20 的 KV + L36 的 Top-512
  • 块入口残差流同样被收集给 MTP
T
L39
Reuse
L39 · Decoder · Reuse + DSpark target(3/3)
  • 复用 L20 的 KV + L36 的 Top-512;块入口残差流被收集给 MTP
  • 主干最后一层:输出经 hc_pre 合并 4 副本 → norm → head 产出 logits
MTP 草稿
L40–L42
DSpark · 块级草稿(block_size=5,纯 SWA,θ=10000;embed/head 与主干共享)
mtp.0
L40 · 投影
mtp.0 · DSpark 草稿 1/3
  • main_proj(15360→5120)+ main_norm:拼接 L37/38/39 的块入口残差流(注意力输入,非输出)投影成草稿流
  • 草稿块 5 个输入位置:首位是真实 token,其余填 noise token(128799)
  • DSparkAttention:可见范围 = 主干 128 滑窗 + 本块 5 位置;MoE 缩版(128 专家选 3)
  • prefill 时只 seed 滑窗 KV,不产生草稿
mtp.1
L41 · 中间
mtp.1 · DSpark 草稿 2/3
  • 完整 Block(DSparkAttention + 128 选 3 MoE + HC),无 main_proj / 输出头
  • 同样吃 mtp.0 投影出的 main_x 做滑窗 KV
mtp.2
L42 · 输出
mtp.2 · DSpark 草稿 3/3(输出段)
  • 独有 norm + markov_head(embed/head 各 129280×256:一阶马尔可夫 logit 加性偏置,逐位采样下一位)
  • confidence_head.proj(5376→1):hidden ⊕ markov_embed → 每个草稿 token 的置信度
  • 一次产出 5 个草稿 token,交主干验证(推测解码)
Full(encoder 组首) Full(decoder 组首 L20) Reindex(重选 Top-K) Reuse(encoder) Reuse(decoder) 纯 SWA DSpark MTP E = Engram 写入 T = DSpark target

2关键参数

项值
主干参数 / Engram 参数552B / 196B
层数40(20 Encoder + 20 Decoder)+ 3 MTP
hidden_size5120
词表129,280
最大上下文1,048,576(YaRN factor 16,原始 65,536)
Prefill / Decode 激活参数8B / 16B 每 token
项值
注意力头64 头 × 512 维(448 nope + 64 rope)
KV单 KV 头,512 维 latent,K=V 共享
路由 / 共享专家384 选 6 / 1 个必过
SWA 窗口 / Top-K128 / 512
Global KV Cache890 B/token(V4-Flash 为 3514)
预训练数据45T 多模态 tokens

权重侧:48 个 safetensors 分片,96,085 个张量,约 475 GiB;dtype 分布 BF16 520 / F32 387 / F8_E4M3 357 / F8_E8M0 47,589 / I8(FP4 打包)47,232。权重名没有 model. 前缀。

3CED:因果编码器—解码器

传统 40 层 Decoder-only 模型,Prefill 时每个 Prompt token 都要完整通过 40 层,每层还要自产 KV。 CED 的做法:Decoder 的 global KV 不由各层自己的隐状态生成,而是统一由 Encoder 末层输出 H₂₀ 经 L20 的 compressor 投影得到:

C = H₂₀ · WKV  (checkpoint 中只有 L20 一份 compressor 权重,全 Decoder 共享一份缓存)

L21–L39 没有 compressor / indexer 权重,global KV 纯读 L20 的缓存,层间差异由各自的 Q 承担 (存储只需一份,这正是 890 B/token 里 decoder 只占 356 B 的原因)。 于是长度为 S 的 Prompt 只需完整跑前 20 层 Encoder; 只有 Prompt 末尾窗口内的 token 需要继续跑 Decoder 的 SWA Bounded Replay 来构建局部 SWA KV (最后一个 token 走完 40 层,产出第一个回答 token)。

4Latent Attention 与 SWA 分支

4.1 核心认知:SWA × CSA²,一次注意力 = 两路 KV 拼接

SWA 与 CSA² 不是两种互斥的注意力模式,而是每次注意力同时存在的两路 KV 来源: L2–L39 的每个注意力层,本层自产的滑窗 KV 与组内共享的压缩检索 KV 拼接后,由 Q 统一打分、 同一个 softmax 归一(分母外加 attn_sink 一项)、统一加权求和——一次 sparse_attn 完成:

SWA 分支(局部,细)压缩检索分支(全局,粗,即 CSA² 管的就是它)
覆盖范围最近 128 个 token全部历史中检索出的 Top-512 个压缩位置
KV 来源本层现算:wkv(5120→512),40 层各自独立权重、独立缓存仅组首 Full 层(L2/L8/L14/L20)的 compressor 产出,组内其余层纯读缓存
精度FP8FP4(main KV 288 B/条 + index K 68 B/条)
缓存形态每层 128 槽环形缓冲(40 层 ≈ 2.6 MB/序列,与上下文长度无关;挂起时丢弃,恢复时 replay 最近 128 token 重建)随长度增长的全局缓存(合计 890 B/token,推导见 §7)
L0/L1/MTP有(是唯一分支,故称"纯 SWA 层")无(compress_ratio=0,整支跳过)

即每个 query 最多看 128 + 512 = 640 个位置:近处是"本层视角"的细粒度原始 KV, 远处是"组首/encoder 视角"的粗粒度压缩 latent。两路位置有重叠——最近 128 个 token 在两路各有一份 副本(投影不同、不去重,都进同一个 softmax);唯一的可见性限制是组级因果掩码:一个压缩组要等 query 越过组内最后一个 token 才对它可见。

控制这条全局分支粒度的旋钮是逐层配置的 compress_ratios(43 项,含 3 个 MTP)。 它身兼两职:全局分支的开关 + 源层的 token 合并比:

取值层含义
0L0/L1/MTP全局分支整支关闭,纯 SWA。开头两层隐状态近词嵌入、上下文未整合,全局检索没有意义;局部的交给滑窗 + Engram(L1),还省了 indexer 计算与 Top-512 读取的开销;MTP 草稿天然只看局部
2L2–L19encoder 组:源层 compressor 把 2 个 token 池化成 1 条 latent,条目数减半(浅层全局注意力容忍度高)
1L20–L39decoder 组:逐 token 一条、不合并(wgate 退化为无,纯投影)——最接近输出的 20 层唯一的长程记忆,不再压序列维;压缩靠通道(5120→512)、层共享(20→1)、FP4 三个维度承担

连带影响:压缩缓存条目数 = S/m;压缩条目的 RoPE 取组首 token 位置(第 j 组取 j×m);indexer 打分粒度 = 压缩条目; r=0 的层禁用 YaRN(θ=10000),r>0 的层整层用 θ=160000 + YaRN。注意 m 与 latent attention(通道压缩)、 CSA² 层间共享是三个独立旋钮,别混为一谈。

边界细节(奇数长度怎么办):m>1 时末尾凑不满一组的 token 不硬压——余数落进 compressor 的 kv_state/score_state 状态缓冲,等下一个 token 凑满再池化(组边界是纯位置性的, 一条 latent 可以横跨 prompt/生成边界,如"prompt 末 token + 首个生成 token")。 落单期间它不进压缩缓存、不参与全局分支检索,但必然躺在每层的 SWA 窗内:组最晚在下一个 token 到达时凑满, 而滑窗要 128 步后才把它覆盖——两套缓存有 ~127 步的交接重叠带,任何时刻都不存在"谁都看不见"的 token (新靠 SWA、老靠压缩缓存,交接期两路都在)。

4.2 单层结构:latent attention(layers.N.attn.*)

4.3 SWA × 全局分支:两套独立的投影矩阵

SWA 与全局(压缩检索)分支共用 Q 打分与同一个 softmax,但 KV 的投影矩阵完全独立、互不共享—— 同一份隐状态 h,经两套不同的权重产生两种视角的 512 维 latent:

SWA KV(每层私有)全局压缩 KV(组内共享)
投影权重attn.wkv(5120→512)+ kv_normattn.compressor.wkv + wgate(仅 m>1)+ compressor.norm
持有层全部 43 层(40 主干 + 3 MTP),逐层独立、互不相同仅 4 个源层 L2/L8/L14/L20;Reuse / Reindex 层连权重都没有
权重精度FP8 块量化(32×32)bf16(wgate 为 fp32)
写入粒度每个 token 一条,逐层各写各的m=2:2 个 token 经学习到的 softmax 门控池化成 1 条;m=1:退化为纯投影(无 wgate)
缓存精度FP8(对 post-RoPE 整向量量化)FP4 E2M1(MXFP4)

因此"只有 L2/L8/L14/L20 计算并缓存 KV"这个说法只对全局分支成立;SWA 分支每层都在产、都在缓存。 两路缓存在结构上互不读取(对方的 cache 不在自己的数据通路上:wkv 与 compressor.wkv 都只是对 h 的纯投影),但在数值上互相渗透:h 由前序各层堆出, 而每层的注意力输出都融合了两路检索结果——深层的 SWA 条目里早已蒸馏了全局信息,反之亦然。 这个"结构分离、数值交融"的格局,正是下面 replay 敢做近似的前提。

4.4 SWA 的构建(代码级)与 Bounded Replay(部署级)

构建发生在每层的 Attention._window_kv,四步:

  1. 投影:kv_norm(wkv(x)) 得 512 维 latent,RoPE 只旋末 64 维;
  2. 量化:对 post-RoPE 整向量做 FP8 量化(RoPE 尾维在内);
  3. 写入环形缓冲 window_kv_cache[batch, 128, 512](persistent=False,不进 checkpoint): prefill 时序列 ≤128 则整段写入;更长则只取 kv[:, -128:],按 seqlen % 128 旋转对齐填入; decode 时按 start_pos % 128 覆盖单个槽位;
  4. 可见性:get_window_topk_idxs 给每个 query 发其因果窗口内的槽位列表, 窗口未满的位置标 -1 屏蔽(prefill 第 k 个 query 只见 k 条;稳态 decode 见整个环,环未填满时旧槽同样标 -1)。

Replay(挂起恢复时的重建):这是部署层的过程——发布的 minimal inference 里没有 replay / restore 函数,只有"多 token 的 chunk 从 start_pos=0 进、单 token 覆盖环槽"两条路径; 真正的重建由 serving 层完成,官方技术报告给出的机制是: 以缓存命中位置 s 为起点、用真实绝对位置重放最近 n_win(=128)个 token, 截断规则为位置 i 的 query 只看 [max(s, i−W+1), i];重放段只重算 SWA KV, 全局压缩 KV 直接复用缓存、既不重算也不覆写(位置基准一旦被重置,持久化的全局缓存与 RoPE 相位就对不上了)。过程要点:

为什么一个窗口就够:官方明确这是近似,并且给了两档口径。 精确重建的代价,官方口径是重放 L×n_win = 40×128 = 5120 个 token (decoder 侧为 L/2×n_win);按感受野精算更紧一点:第 l 层的 KV 条目依赖 128 + 127·l 个 token (每层滑窗把感受野向前扩 127;Engram 的 4-gram 哈希再多要 ≤3 个 token id),顶层 L39 ≈ 5081—— 与官方口径同量级,两者互相印证。官方选择只重放一个窗口(128),并明确承认这是近似重建 (原文 "approximately reconstructs"、"accepting approximate states"、"not mathematically equivalent"), 依据是先验观察"SWA 的实际有效感受野远小于理论值 n_win × L/2"; 为兜底,后训练阶段会模拟同样的 replay 做 train-aware 适配,让模型适应这种非严格一致的状态。 支撑这个近似的安全网有三:全局分支持久化且精确(长程锚定)、两路在最近 128 token 上的重叠冗余 (交接带设计)、以及"污染最重的条目死得最快"的 FIFO 自愈。

5CSA²:压缩检索与跨层复用

5.1 三种静态模式:Full / Reindex / Reuse

每个注意力层仍然计算自己的 Main Query 和 SWA(128)KV,但全局稀疏注意力所用的 main KV、indexer K、Top-K 索引可以跨层共享。三种静态模式逐层指定:

模式做什么本模型对应层
Full自产 main KV;indexer K 由 main KV 投影;跑 indexer 产 Top-512(唯一能产出可复用 cache 的模式)kv_source_layer_ids = {2, 8, 14, 20}
Reindexmain KV 与 indexer K 复用前序层,用本层 indexer Q 重算 Top-K{24, 28, 32, 36}
Reusemain KV、indexer K、Top-K 全复用,不跑 indexer其余 30 层

Encoder 侧:18 个 CSA² 层(L2–L19)分 3 组,每组一个 Full 层,压缩率 m=2。 Decoder 侧:仅 L20 为 Full(其 compressor 吃第 20 层注意力子层输入,即 CED 公式的实现), 4 个 Reindex + 15 个 Reuse,m=1。与上一代 CSA 相比,CSA² 删掉了压缩窗口重叠、 压缩阶段的绝对位置编码,indexer K 直接从 main KV 投影,并把 KV 共享与 Top-K 复用解耦。

5.2 分层稀疏索引(Hierarchical Sparse Indexer)

indexer(32 头 × 128 维:indexer.wq_b 1280→4096、wk 512→128、k_norm、weights_proj 5120→32) 若每次扫全部百万 token 自身也会成为瓶颈。因此 Decoder 的第一个 Full 层(L20)扫描全部可见位置时, 除了自己的 Top-512,还按 8 token 一块取最大 indexer score,选出得分最高的 2048 块 = 16,384 个位置 组成共享候选池(candidate_source_layer=20)。后续 Reindex 层只在候选池内打分选 Top-512—— 索引计算量从随上下文线性增长变成近似常数。 实现上,块得分取块内最大 indexer score;含最新位置的未满块会被强制保留(pin 为 +inf), 防止它因位置不满而被老的满块挤出候选池。

5.3 FP4 Main KV Cache 与 compressor

实现上,compressor 的工作方式是:m>1 的层(L2–L19)用 compressor.wkv/wgate(fp32)把 m 个连续 token 经学习到的 softmax 门控池化成一个 latent;m=1 的层(L20–L39)退化为纯投影(bf16,无 wgate)。 compressor 输出的是未加 RoPE 的 latent:indexer 先拿它投影出 index K 写入缓存,然后才对 latent 施加 RoPE、 量化 FP4 写入 main KV 缓存——同一份存储先读后写,两种用途各取所需形态。

6位置编码:部分维 RoPE + 分频段 YaRN

6.1 施加范围:512 维里只有末 64 维旋转

6.2 频率配置:每层一组,共两档

层base θYaRN理由
L0 / L1 / MTP(compress_ratio=0)10,000禁用只看 128 滑窗,没有长程外推需求
L2–L39(compress_ratio>0)160,000启用(factor 16,原始 65,536)全局分支要面对 1M 上下文;整层(Q、SWA KV、压缩 KV)共用这一组频率

压缩条目的旋转位置取组首 token(第 j 组取位置 j×m,"一个 latent 代表组内第一个 token")—— 压缩 KV 的"位置间隔更大"由此体现,而非单独的 θ;config 里 compress_rope_theta 的名字有误导性, 它实际是"所有带压缩分支的层的 θ"。

6.3 YaRN:按频段分别插值(65,536 → 1,048,576)

对 32 个频率按"该维在训练长度 65,536 内转几圈"分三段(precompute_freqs_cis 的 original_seq_len > 0 分支):

频段判据(训练长度内圈数)处理
高频> 32 圈(beta_fast=32)频率不动——波长远小于训练长度,没有外推问题,保住局部位置区分度
低频< 1 圈(beta_slow=1)频率 ÷ 16——一圈都没转完的纯外推段,直接位置插值
中间1–32 圈线性 ramp 渐变过渡(两段之间不平滑切换会引入伪周期)

注意:本模型没有采用原版 YaRN 论文的 attention 温度缩放——softmax_scale = 512−0.5 固定不变, 温度补偿可能已在训练中吸收。

6.4 视觉塔:独立的 2D RoPE

ViT 用二维 RoPE:head_dim 64 对半分,前 32 维编码 h 方向、后 32 维编码 w 方向(θ=10,000,fp32 计算),双向注意力; 配对方式是"前后半配对"(chunk 两半)而非语言侧的"相邻两维配对",两套实现各自独立 (vision.py 的 apply_rotary vs model.py 的 apply_rotary_emb)。

7KV Cache 显存账:890 B/token 的推导

项通道数值格式缩放字节/条目
main KV / 压缩 latent512FP4 E2M1(0.5 B/通道)每 16 通道 1 个 E4M3 scale → 32 B288
indexer K128FP4 E2M1每 32 通道 1 个 E8M0 scale → 4 B68

每 token 的条目数:Encoder 的 3 组 Full 各按 m=2 摊(3 × 1/2 = 1.5); Decoder 20 层共享 1 份且 m=1(1 × 1 = 1);合计 2.5 条/token:

Encoder 3×½×356 = 534 B  +  Decoder 1×1×356 = 356 B  =  890 B/token

对照 DeepSeek-V4-Flash 的 3514 B/token:890 / 3514 ≈ 25.3%,即 降低约 75%, 同显存理论上可容纳 ≈ 3.95 倍上下文。口径是随序列长度增长的那部分(global KV); SWA KV(每层 128 槽 × 512 维 FP8,40 层 ≈ 2.6 MB/序列)是与长度无关的环形缓冲,不计入 per-token 口径。

8Hyper-Connections(Single-Pass mHC)

残差流不是单向量,而是 hc_mult=4 份并行副本(layers.N.hc_{attn,ffn}_{fn,base,scale},fp32):

9Engram:参数化 n-gram 记忆

对固定短语、实体名、代码模式等高度重复的局部知识,不必让 Transformer 每次用多层 attention + MoE 重新推导——直接拿最近几个 token 去巨型可训练 embedding 表里查。 MoE 是 Conditional Computation(按隐状态选专家),Engram 是 Conditional Memory (按 n-gram 查记忆);不是 RAG,是端到端训练的内部记忆表。

一个准确的心智模型:Engram ≈ 在 L1、L14 两个 Block 前面各"硬插"了一个记忆层。 代码上就是 h = engram(h, hash_ids) 之后原样 h = block(h)——L1/L14 本身是 完全标准的 Block(latent attention + MoE + HC),结构与权重上零改动(Block.forward 里没有 任何 engram 逻辑,调用点在 Transformer 主循环);当然,该层及其后的所有计算都运行在注入后的残差流上 (这正是目的——包括该 Block 用注入后的 h 算出的 HC 混合系数)。 这个插入层与正常 Block 的差别只在:输入只依赖当前位置最近 3 个 token 的 id(哈希查表, 不读隐状态)、计算量恒定(24 次 lookup + 一次投影,不随上下文增长)、写入是纯加法 (h += gate × value)。上下文感知只剩 gate 一个标量;图像 token 处 gate=0 直接跳过。

9.1 计算流程(五步)

  1. Tokenizer 压缩:原始 token id 经规范化管道映射为压缩 id(只用于构造查询键,不改模型 tokenizer);管道为 NFKC → NFD → 去口音 → 小写 → 空白合并(含"单空格 token"哨兵保护),129,280 个 token 收敛出 99,092 个唯一 key(config 的 engram_compressed_vocab_size,哈希乘子由它导出,不匹配会静默重哈希整张表);
  2. 后缀 n-gram:当前位置取最近 token 构造 2/3/4-gram(不含未来 token,保持因果;n-gram 不跨越图像 span——遇到 dead token 即截断填 pad);
  3. 多头哈希:每种阶数 8 个 hash head,共 24 次 lookup,拼接出 24×256 = 6144 维——碰撞在 8 个独立 head 下同时撞上的概率极低;哈希为"奇数乘子 × 压缩 id 后 XOR 滚动"(每层的乘子由 seed=10007×layer_id 的 RNG 生成),每个 (阶数, head) 占有自己质数大小、互不相交的桶区间(从 1600 万起依次取未用过的质数);
  4. 投影 + 上下文门控:engram.wkv(6144→25600)投出 4 份 HC 副本各自的 key + 1 份共享 value;门控 = sigmoid(signed_sqrt(归一化点积))——n-gram 提供候选记忆,当前隐状态决定写不写;
  5. 门控写入残差流(V4.1 删除了原论文门控后的短因果卷积);图像 token 不参与(engram_mask 关门)。

9.2 本模型配置

项值
位置 / 数量第 1、14 层各一个(零起始编号)
哈希表FP8 E4M3,3.84 亿 × 256 / 层(逐行 1×32 UE8M0 缩放),两层合计 ≈ 196 GB,占全模型近一半体积
多分支用法所有 HC 分支共享记忆表与 value 投影,各分支有自己的 key 通路(wkv 一次投出 4 key + 1 value)
推理部署记忆表主要驻留 Host Memory,后台 RDMA 预取;第二个模块放 L14 留出更长通信隐藏窗口
注入位置在 L1/L14 所属 Block 的入口(attention 之前)直接写入 4 份 HC 残差流:h = engram(h, hash_ids);门控的归一化点积逐 (token, hc 副本) 计算,不跨副本联合归一

收益(官方/原论文):释放早期网络深度与 attention 容量(Multi-Query NIAH 84.2 → 97.0); 参数扩容但不同比增加每 token 计算——一条不同于扩 dense / MoE 的 scaling 路径。

9.3 哈希查表:代码级演示

整个哈希是纯整数运算,输入只有 token id 序列,不碰隐状态——numpy 即可完整复现 (下面对照 inference/engram.py 的 NgramHashState,省略 tokenizer 压缩映射与图像 dead-token 处理;完整可运行脚本见仓库 analysis/ds_v4_1_flash/engram_hash_demo.py)。 这也说明哈希索引完全可以搬去 CPU 预查,GPU 只需要查表结果。

# 配置(config.json): MAX_NGRAM=4, N_HEADS=8, LAYER_IDS=(1,14),
# ENGRAM_VOCAB_SIZE=1600万, COMPRESSED_VOCAB=99092, PAD_ID=2

# ① 桶区间分配: 每层 3 阶(2/3/4-gram) × 8 头,
#    从 1600万起 依次取 24 个互不重复的质数, 各占一段不相交的行区间
primes[layer][order][head]  = find_next_prime(...)   # 如 16000057, 16000079, ...
offsets[layer]              = cumsum(24 个质数)       # 各桶段在表内的起始行号

# ② 乘子: 每层 seed=10007×layer_id 的 RNG 生成, 强制为奇数,
#    上界 int64_max//vocab//2 保证 压缩id×乘子 不溢出 int64
multipliers[layer] = (rng.integers(0, bound, size=4)) * 2 + 1

# ③ 回看窗口: 每个位置取 [当前, 前1个, 前2个, 前3个], 越过序列开头填 pad
tokens = full((L, 4), PAD_ID)
for shift in range(4):
    tokens[shift:, shift] = seq[:L-shift]

# ④ 滚动 XOR: 第 i 步 XOR 完 = (i+1)-gram 的哈希 —— 三种阶数一条链算出
products = tokens * multipliers[layer]        # [L, 4]
rolling  = products[:, 0]
hashes   = []
for i in 1..3:
    rolling = rolling XOR products[:, i]
    hashes.append(rolling % primes[layer][i-1])  # 同一哈希值对 8 个质数分别取模 → 8 路 head

# ⑤ 加桶段 offset → 24 个表内行号, 去 embed 表取 24×256 维
row_ids = concat(hashes) + offsets[layer]     # [L, 24]

实际跑一遍(压缩 id 序列 [5231, 887, 40211, 96, 7712, 330],展开位置 4):

窗口 [当前,前1,前2,前3] = [7712, 96, 40211, 887]
× 层1乘子 [76632096046245, 4839876093313, 35959672319349, 73987337458391]
  ↓ 滚动 XOR
2-gram 哈希 = 7712·m₀                  =  590986724708641440
3-gram 哈希 = 上值 ⊕ 96·m₁             =  590602499734174400
4-gram 哈希 = 上值 ⊕ 40211·m₂ ⊕ 887·m₃ = 2074533117092600990
  ↓ 每个值 % 8 个质数 + offset
24 个行号: [8264676, 16730195, 32156052, ..., 371650938]

10MoE 与路由

11DSpark MTP(推测解码草稿)

num_nextn_predict_layers=3,前缀 mtp.0/1/2(layer_id 40/41/42),每层是完整 Block (DSparkAttention + 缩版 MoE + HC),embed/head 与主干共享。目标:每个 decode 步,一次前向产出 block_size=5 个草稿 token + 各自置信度,交主干并行验证。注意开源 repo 只实现前向 (forward_spec),accept/reject 的验证循环不在发布范围内(官方注释: "the speculative-decoding loop itself is out of scope for this repo")。

11.1 一步 decode 的数据流总览

主干(本步)
token t 正常过 40 层;在 L37 / L38 / L39 的块入口收集残差流(注意力输入,非输出),对 4 份 HC 副本求 mean → 各 5120 维(main_hiddens.append(h.mean(dim=2)))
↓ 按层序 cat → main_hidden [15360]
mtp.0 · 入口投影
main_proj(15360→5120)→ main_norm → main_x:主干信息流,供三层注意力各自产滑窗 KV
草稿输入 = [真实 token t, noise×4] → embed(与主干共享)→ 复制成 4 份 HC 残差流
↓
mtp.0 / mtp.1
两个标准 Block
DSparkAttention:Q = 草稿 5 位置;KV = 本层 128 滑窗环(由 main_x 经本层 wkv 现算写入)⊕ 本块 5 位置(互相可见,无块内因果掩码)→ 分组低秩输出;
MoE 缩版(128 专家选 3 + 共享)+ HC 混合,与主干 Block 同构
↓
mtp.2 · 输出段
同样的 Block → norm → head(与主干共享,fp32 logits)→ 5 个位置的 logits
逐位采样 i=0…4:markov_head(上一位 token)给 logits 加加性偏置 → sample → 草稿 token i+1
confidence_head:合并后 hidden(5120)⊕ 各位 markov_embed(256)→ proj(5376→1,fp32)→ 每个草稿 token 一个置信度
↓
输出
6 个 token id(真实 t + 5 个草稿)+ logits + 5 个置信度 → 交主干验证(实现不在本 repo)

11.2 三层内部结构:哪些权重各有几份

组件mtp.0(L40)mtp.1(L41)mtp.2(L42)
DSparkAttention(wq_a/wq_b/wkv/wo_a/wo_b/attn_sink)✓ 独立✓ 独立✓ 独立
MoE(128 路由专家选 3 + 1 共享)✓ 独立✓ 独立✓ 独立
HC 混合系数(hc_*)✓✓✓
main_proj(15360→5120)+ main_norm✓ 独有——
norm + markov_head + confidence_head——✓ 独有
embed / head与主干共享(挂在 mtp 模块上,词表 129,280)

即三层 Block 主体同构,差异只在首尾:mtp.0 多一条"主干 → 草稿流"的投影通路, mtp.2 多输出头三件套。中间层 mtp.1 是纯计算层,只加深草稿流的深度。

11.3 逐步走一遍:forward_spec 的执行顺序

  1. 收集:主干 forward 途中,target 层(37/38/39)块入口各存一份 h.mean(dim=2),末尾 cat 成 [15360];
  2. 入口(mtp.0.forward_embed):main_x = main_norm(main_proj(main_hidden)); 同时构造草稿输入 [t, noise, noise, noise, noise](noise_token_id=128799),过共享 embed 后复制成 4 份 HC 流;
  3. 三层 Block:每层 DSparkAttention 先用 main_x 经本层 wkv 现算 main_kv(RoPE 取主干位置 t,FP8 量化),写入本层自己的 128 槽滑窗环 start_pos % 128; 草稿 Q/KV 用未来位置 t+1…t+5 的 RoPE;然后 MoE、HC 与主干 Block 完全相同(草稿纯文本,不传 image_mask、不用 bias_vl);
  4. 输出头(mtp.2.forward_head):hc_pre 合流 → norm → 共享 head 得 5 位 logits; 逐位循环:markov_head(已采 token)产出 logit 偏置与 256 维 markov_embed,偏置加到当前位 logits 后采样出下一位—— 即草稿块内部依赖由马尔可夫链在头部串行化,而不是靠注意力掩码;
  5. 置信度:合并后 hidden 与 5 个 markov_embed 拼接(5120+256)经 confidence_head.proj(fp32)得每个草稿 token 的置信度,供验证阶段决定接受前缀长度;
  6. prefill 特例:start_pos=0 时三层只对 main_x 做 wkv seed 滑窗环,forward_spec 直接返回 None,不产生草稿。

11.4 DSparkAttention 的可见性与缓存细节

11.5 markov_head:三个关键点

① 本质是查一张一阶马尔可夫转移表,实现上做了低秩压缩。 理想形态是 V×V 的 bigram logit 表 B(B[x,y] = "上一位是 x、下一位是 y 的偏置"),V=129,280 时完整表 ≈ 33 GB; 实现压成 rank-256 分解 B = E·Hᵀ(两张 129280×256,bf16 ≈ 132 MB,约 250 倍压缩)。 查询时只需:上一位 token id → 取 E[x](256 维)→ 乘 H → 得到整行 B[x,:]。 只查 id、不读隐状态——这正是"一阶"的含义,也是它几乎零成本的原因。

② 串行链条:注意力并行算 5 位 logits,先后依赖由头部 5 步循环补上。 每一位的最终分布由两路相加得到:

最终 logits = head(隐状态) + markov_head(上一位 token id)
↑ 深层上下文理解     ↑ 浅层词序习惯

# DSparkBlock.forward_head(mtp.2);logits [B,5,V] 由共享 head 一次算出
output_ids[:, 0] = input_ids                               # 首位 = 主干刚采的真实 token
for i in range(block_size):                                # 逐位串行 0…4
    bias, mk_emb = self.markov_head(output_ids[:, i])      # 拿上一位 id 查转移表
    logits[:, i].add_(bias)                                # 偏置加到第 i 位 logits
    output_ids[:, i+1] = sample(logits[:, i], temperature) # 采出第 i+1 个草稿,成为下一步的键

这就是草稿块内可以不用因果掩码的原因:并行归注意力,串行归这个循环。 (副产品 mk_emb 逐位攒齐后拼进 confidence_head 输入。)

③ 为什么能直接相加:logit 空间相加 = 概率空间相乘。 softmax(z+b) ∝ softmax(z) ⊙ eᵇ,即"主干的概率分布 × 马尔可夫先验分布,再归一化"—— 贝叶斯式的"先验 × 似然 → 后验",也是经典的 Product of Experts: head 提供深层上下文证据,markov_head 提供局部词频证据,两个独立信息源的对数概率本来就该相加。 且偏置幅度是端到端训练校准的;再加上它只作用于草稿、主干验证兜底, 最坏情况只是接受率下降,不会影响最终输出的正确性。

注:checkpoint 配置 block_size=5、target 层 {37, 38, 39}(对应 main_proj 输入 15360 = 3×5120); 推理代码 __main__ 冒烟示例用的是 block_size=6、target (3,4),仅为演示参数,勿当作模型配置。

12视觉塔(ViT + aligner)

12.1 数据流总览:像素 → patch → ViT → aligner → 文本流

图像输入
RGB 像素,切成 14×14 patch(每 patch 3×14×14 = 588 维);单图 token 预算 max_image_tokens=1024(由 image_processor 侧执行,约束的是进入 LLM 的图像 token 数);patch 按行主序(光栅扫描)排成序列
↓
Patch 嵌入
patch_embed.proj:588 → 1024(裸 Linear,带 bias);无绝对位置嵌入——与经典 ViT 的关键差异
↓ ×32 层(pre-norm)
ViT Block
×32
双向注意力(非因果,SDPA 实现,无 CLS token):16 头 × 64 维,Q/K/V/O 投影带 bias;2D RoPE(θ=10000)只作用于 Q/K——head_dim 64 对半分,前 32 维编码 h、后 32 维编码 w;
SwiGLU MLP(SiLU 门控):w1 [5632,1024](gate/up 融合)→ w2 [1024,2816],无 bias;pre-norm,32 层之后还有最终 RMSNorm
全程 bf16 未量化(RoPE 与 RMSNorm 内部以 fp32 计算)——视觉塔是全模型少数完全没上 FP8/FP4 的部分
↓ N 个 1024 维 patch 特征
aligner
(3×3 折叠)
把特征图 reshape 回 2D 网格,右/下侧补零到 3 的倍数后做非重叠 3×3 分块(F.unfold,kernel=stride=3,非滑动邻域),每块的 9 个 patch 在通道维拼成 9216 维 → aligner.w1(9216→5120,带 bias)→ GELU → aligner.w2(5120→5120,带 bias)
效果:token 数 ≈ 减为 1/9,维度对齐语言模型 hidden_size 5120
↓ merge_image_embeddings:覆写图像 span 的 embedding
插入文本流
[image_start] 图像特征(行间插 [image_newline]) [image_end] —— 三个 5120 维可学习边界嵌入;
文本流中图像 span 的占位符是 image_token_id=129264,embed 后被 aligner 输出整段替换; 此后图像 token 在 LLM 注意力里就是普通位置(占滑窗、进压缩缓存)

记号对应:vision.* 为 ViT(含 patch_embed 与 32 层 Block),aligner.* 为跨模态投影, image_start/end/newline 挂在 embedding 侧。位置信息的处理方式见 12.4。

12.2 图片尺寸规划:token 预算、分辨率上限与超限处理

约束对象要分清:vision_max_n_token=1024 限制的是经 aligner 3×3 折叠后进入 LLM 的 token 数, 不是 ViT 侧的 patch 数。一格 LLM token 对应 42×42 像素(patch 14 × downsample_ratio 3), 即 n_llm_h × n_llm_w = ceil(H/42) × ceil(W/42),预算口径(含换行与边界):

num_image_tokens = n_llm_h × (n_llm_w + 1) + 2 ≤ 1024

式中 +1 是每行末尾各一个 image_newline(逐行插入,行数越多开销越大),+2 是 image_start/end。所以即使折叠后只有 1×1 格,序列也是 [start][IMAGE][newline][end] 共 4 个 token,而不是"1 + 前后 2 个"。

由此推出分辨率上限:方图最多 31×31 格 ≈ 1302×1302(约 170 万像素)——远比"1024 个 patch → 448×448"的直觉大。 vision_max_wh_ratio=null,不限制宽高比;极端长宽比有解析兜底(塌缩成单行/单列网格)。

情形处理(image_processor.py)
尺寸在预算内仅向上取整到 14 的倍数,原样进 ViT
超过 1024 token 预算solve_resize_ratio 解析求出保持宽高比、恰好塞进预算的最大像素尺寸(向下取整到 14 的倍数),再 ImageOps.pad 等比缩 + 灰边(127)letterbox——整幅缩小,不裁剪、不切 tile,一次编码
小于 vision_min_pixels=295936(544×544)等比放大到下限,保证 ViT 有足够 patch 数。例:40×40 的图按 √(295936/1600) ≈ 13.6 倍放大到 544×544(取整 546×546),ViT 网格 39×39、LLM 网格 13×13,编码后是 184 个 token 而非 1 个
这套方案没有 Qwen2-VL / InternVL 式的"大图切多块分别编码"机制:单图固定 ≤1024 token, 换来图像对上下文的开销有硬上界;代价是细节密集的超大图(文档扫描、高清截图、大表格)会因整体缩小而损失分辨率。

12.3 结构参数

  • vision.*:32 层 ViT(hidden 1024、16 头、patch 14 → patch_embed.proj 1024×588),MLP SwiGLU 融合(SiLU 门控,w1 [5632,1024]、w2 [1024,2816]),RMSNorm pre-norm + 末尾最终 RMSNorm,bf16 未量化(RoPE/norm 内部 fp32);注意力是双向的(SDPA,无 CLS token)并带 2D RoPE;patch_embed 与注意力投影带 bias,MLP 的 w1/w2 无 bias;max_image_tokens=1024、min_pixels=295936(544×544);
  • aligner.w1/w2(9216→5120→5120,带 bias):非重叠 3×3 分块(downsample_ratio=3,F.unfold kernel=stride=3,右/下侧补零 pad 到 3 的倍数)拼 9216 维投到语言模型;中间激活是 GELU;
  • image_start/image_end/image_newline:5120 维可学习边界嵌入;image_token_id=129264。

12.4 位置信息如何进入:不是"融进 token",而是"藏在特征里"

这个 ViT 没有经典 ViT 的绝对位置嵌入(patch_embed 是裸 Linear,无任何 additive position embedding)。 位置感经由两个间接渠道形成:

  • ViT 内部的 2D RoPE:只作用于每层注意力的 Q/K(影响 patch 间的关注模式),不改变特征向量的内容基底;
  • aligner 的 3×3 折叠:空间结构被折叠进通道维——每个输出 token 天然对应一个 3×3 patch 块,且按行主序(光栅扫描)排列。

因此进入 LLM 的图像 token 向量不带显式位置编码:图像内部的 2D 结构已由 ViT+aligner 预消化成特征与顺序; 进入文本流后,LLM 的 RoPE 按序列位置统一处理——跨 token 的位置关系归 LLM 管,图像内部的 2D 结构归 ViT 管。

12.5 LLM 侧如何区分图像 token 与文本 token

一切源于 image_processor 准备好的 token_types(文本 = −1,图像 span ≥ 0), 派生出 image_mask,在三处区别对待:

机制对图像 token 的区别对待
Embedding 替换图像 span 位置的 input_ids 全是 image_token_id(129264),embed 后整段被 aligner 特征覆写(merge_image_embeddings);span 边界位置填入可学习的 image_start/end/newline 向量
Engram 关门图像位置 gate=0,不写入 n-gram 记忆;且 n-gram 哈希遇图像 span 即截断(DEAD token),不跨图像组词
MoE 路由换 bias图像 span 内的 token 选专家时用 gate.bias_vl 而非 gate.bias(noaux_tc_for_vl)——图像 token 的专家偏好有独立校正

注意力本身不做特殊掩码:图像 token 在注意力里就是普通位置(占滑窗、进压缩缓存、可被检索)。 多模态的区分全部集中在"入口表示"(替换 embedding)与"路由/记忆"(bias_vl、engram_mask)两处。

13量化格式与权重命名

类别格式覆盖权重
直接可读(BF16/F32)未量化embed/head、全部 RMSNorm 增益、路由器、HC、attn_sink、compressor/indexer(个别 FP8)、视觉塔
FP8 E4M3 + UE8M0 块量化32×32 块,scale = 2^(e−127)wq_a/wq_b/wkv/wo_a/wo_b、共享专家 w{1,2,3}、engram.wkv、indexer.wq_b、mtp 对应项
FP4 E2M1 路由专家I8 打包(每字节 2 值,低半字节为偶数列)+ UE8M0 行块 1×32;值表 {0,±0.5,±1,±1.5,±2,±3,±4,±6}layers.N.ffn.experts.E.w{1,2,3}(+ .scale),mtp 128 专家同格式

反量化(llm_lens.dequant_block / unpack_fp4_e2m1)已与官方 inference/convert.py 对拍逐值一致。 最大的单体权重是两张 engram 哈希表(各 ~92 GiB),只建议按行抽样读取。

14优化器与后训练(官方)

参数类型优化器理由
RMSNorm 及非矩阵参数AdamW(wd=0.1)常规
主干线性矩阵Muon(wd=0.1,RMS rescale 0.18)矩阵参数的预条件更新
Q / K 矩阵Head-wise Muon按注意力头各配预条件器,适应头间梯度异质性
Engram / Embedding / HeadNesterov Momentum + Sinkhorn Balancing只需一份 momentum buffer,避免 Adam 两套状态吃掉超大表的显存(行列缩放使更新矩阵行/列 RMS ≈ 1)
  • 可控推理强度:任务 reward 之外加与 Reasoning Effort 相关的长度 reward——Effort 越低、单位 token 惩罚越重(Effort 25 对 1 万推理 token 的惩罚约是 Effort 100 的 20 倍);API 档位 Low/High/Max 对应 Effort 50/75/100;
  • 异步 RL:Sample-level Dispatch 解决长尾轨迹拖住整组的问题;控制并发缓解长度偏差;限制 off-policy 比例并 mask 掉过期 token 的 loss;rollout 可在任意 token 边界中断续跑(保留 KV 与路由);
  • 大规模 On-policy Distillation:40+ 个 teacher(可不同架构、动态切换),异步 rollout 中可改数据配比;
  • 效果:Effort 25→100,八项推理 benchmark 平均 Pass@1 67.1% → 76.3%,DeepSWE 66.0 → 74.2,Terminal-Bench 82.4 → 90.6(输出 token 约 ×2.5);提升集中在低中 Effort 段,80 以上性价比下降。