moe(wip): gpt-oss-20b groundwork — config fields, arch doc, MXFP4 tools
Phase 19 start. config.rs: explicit head_dim (gpt-oss=64) + MoE fields (num_local_experts, num_experts_per_tok, swiglu_limit, sliding_window, layer_types) with accessors; Qwen3/GPT-2 paths unchanged (fall back to hidden/num_heads when head_dim absent). docs/19-moe-gpt-oss.md: architecture + exact HF reference math (router softmax-after-topk, interleaved clamped (up+1)*glu experts, attention sinks, alternating sliding window, rotate_half RoPE theta=150000, head_dim 64), verified tensor layout, MXFP4 dequant plan. docs/MOE_PROGRESS.md: resume/handoff snapshot. tools/mxfp4_probe.py: inspect safetensors + validate MXFP4 decode (done). tools/gptoss_dequant.py: MXFP4 experts -> plain BF16 safetensors dir so the existing loader reads it (no MXFP4 in Rust for the first pass). Verified: llama.cpp (dash5, LLM_ARCH_OPENAI_MOE) runs the gpt-oss-20b MXFP4 GGUF correctly (17*24 -> 408) = the correctness oracle. MXFP4 decode validated in numpy. Model + GGUF staged on dash5. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,41 @@ o = (scores @ v) -> merge heads -> @Wo + bo
|
||||
与 Qwen3 的新增点:MoE FFN、MXFP4 反量化、attention sinks(softmax 多一列再丢)、
|
||||
交替 sliding window、q/k/v/o bias、head_dim=64、clamped `(up+1)*glu`、rope_theta=150000。
|
||||
|
||||
### 实测张量布局(layer 0,已用 `tools/mxfp4_probe.py` 核对)
|
||||
```
|
||||
self_attn.q_proj.weight [4096,2880] +bias[4096] # 64 heads*64
|
||||
self_attn.k_proj.weight [512,2880] +bias[512] # 8 kv*64
|
||||
self_attn.v_proj.weight [512,2880] +bias[512]
|
||||
self_attn.o_proj.weight [2880,4096] +bias[2880]
|
||||
self_attn.sinks [64] # 每 q-head 一个标量(BF16)
|
||||
input_layernorm.weight [2880]; post_attention_layernorm.weight [2880]
|
||||
mlp.router.weight [32,2880] +bias[32]
|
||||
mlp.experts.gate_up_proj_blocks [32,5760,90,16] U8 + _scales [32,5760,90] U8 + _bias[32,5760] BF16
|
||||
mlp.experts.down_proj_blocks [32,2880,90,16] U8 + _scales [32,2880,90] U8 + _bias[32,2880] BF16
|
||||
# 全局: model.embed_tokens.weight, model.norm.weight, lm_head.weight (BF16)
|
||||
```
|
||||
MXFP4 打包:`[..., nblk=90, 16]` U8,每 16 字节 = 32 个 FP4 码(低 nibble=偶 idx,高 nibble=奇 idx),
|
||||
每 block 一个 E8M0 scale;`90*32 = 2880 = 输入(hidden)维`。即 gate_up 每 expert 权重逻辑 shape
|
||||
`[5760 out, 2880 in]`(**已转置存储**:行=out,列=in,与 HF `nn.Linear` 一致 `y=x·Wᵀ`)。
|
||||
|
||||
### RoPE(**rotate_half,非 interleave**)
|
||||
```
|
||||
dim = head_dim = 64; base = rope_theta = 150000
|
||||
inv_freq = 1 / base^(arange(0,64,2)/64) # 32 项
|
||||
freqs = pos ⊗ inv_freq # [S, 32];cos/sin = cos(freqs)/sin(freqs) (不 doubling)
|
||||
# 应用: x=[.., 64], first=x[:32], second=x[32:]
|
||||
# out_first = first*cos - second*sin
|
||||
# out_second = second*cos + first*sin
|
||||
```
|
||||
> ⚠️ 与 Qwen3 的 RoPE kernel(interleave)不同 —— gptoss 走 rotate_half。需单独处理。
|
||||
|
||||
### Decoder layer(pre-norm 残差,结构同 Qwen3)
|
||||
```
|
||||
h = x + attn(input_norm(x)) # attn 含 sinks/bias/滑窗
|
||||
out = h + moe(post_norm(h)) # moe = router + top4 experts 加权和
|
||||
```
|
||||
最终:`logits = lm_head(norm(h_last))`。无 q_norm/k_norm(与 Qwen3 不同,gptoss 没有)。
|
||||
|
||||
## 3. MXFP4 反量化(expert 权重)
|
||||
|
||||
expert 张量名:`model.layers.{i}.mlp.experts.gate_up_proj_blocks/_scales`、
|
||||
|
||||
Reference in New Issue
Block a user