--- language: - en - zh library_name: mlx license: apache-2.0 base_model: Nanbeige/Nanbeige4.2-3B pipeline_tag: text-generation tags: - mlx - jang - mxfp8 - quantized - apple-silicon - nanbeige - looped-transformer - reasoning - osaurus ---
# OsaurusAI/Nanbeige4.2-3B-MXFP8 MXFP8 build of [Nanbeige/Nanbeige4.2-3B](https://huggingface.co/Nanbeige/Nanbeige4.2-3B) — a 4.17B-parameter **Looped Transformer** reasoning model (en + zh, 256K context), quantized for Apple Silicon with uniform MXFP8 (e4m3) weights. This is format coverage — see the fidelity table before choosing it. > ### ⚠️ This architecture needs a loader that knows about the loop > > `num_loops = 2`: the same 22 decoder layers run **twice** over shared weights, > for an effective depth of 44. Two consequences a generic loader gets wrong: > > - **The KV cache has 44 slots, not 22** (slot = `layer_idx + loop_idx * num_hidden_layers`). > A 22-slot cache does not crash — it emits fluent, confident, **wrong** tokens > from the first one. This is verified with a negative control, not theory. > - **The final norm runs at the end of every loop**, not once at the end > (`skip_loop_final_norm = false`). Loop 0's normed output is loop 1's input. > > `mlx_lm` 0.31.x has no `nanbeige` model class, so `mlx_lm.generate` alone will > not load this bundle. Use a runtime that implements the loop (see **Usage**). ## Bundle | Field | Value | |---|---| | Source | `Nanbeige/Nanbeige4.2-3B` @ `fab06df` (Apache-2.0) | | Architecture | `nanbeige` — 22 layers × 2 loops (effective depth 44), 4.17B params, 256K ctx | | On-disk size | 4.0 GB (1 shard) | | Quantization | uniform 8-bit MX, no per-module overrides, group size 32 | | Norms, router bias | fp16 passthrough — plain Llama RMSNorm, **no +1 shift** | | Attention | 48 heads / 8 KV heads (GQA), `head_dim` 128 — note `n_heads × head_dim` (6144) ≠ `hidden_size` (3072) | | RoPE | θ = 7e7, NeoX half-rotation, full 128 dims, no scaling | | Modality | text-only (verified from the tensor index) | ## Measured (M5 Max, 4-turn gate with a persistent 44-slot cache) | Metric | Thinking on | Thinking off | |---|---|---| | Decode | 34.6 tok/s | 27.9 tok/s | | Peak memory | 5.3 GB | 4.5 GB | Fidelity vs the bf16 source (5-prompt logit sweep): top-1 agreement **4/5**, mean KL **0.1446**, max KL 0.6844. ## Profile comparison | Bundle | Size | Top-1 agreement vs bf16 | Mean KL | Max KL | Decode (thinking) | |---|---|---|---|---|---| | [`Nanbeige4.2-3B-JANG_6M`](https://huggingface.co/OsaurusAI/Nanbeige4.2-3B-JANG_6M) | 3.6 GB | **5/5** | **0.0010** | **0.0030** | 29.3 tok/s | | [`Nanbeige4.2-3B-JANG_4M`](https://huggingface.co/OsaurusAI/Nanbeige4.2-3B-JANG_4M) | 2.9 GB | 5/5 | 0.0192 | 0.0398 | **44.7 tok/s** | | [`Nanbeige4.2-3B-MXFP8`](https://huggingface.co/OsaurusAI/Nanbeige4.2-3B-MXFP8) | 4.0 GB | 4/5 | 0.1446 | 0.6844 | 34.6 tok/s | **Both JANG affine profiles beat MXFP8 on fidelity while being smaller** — the opposite of what the bit counts suggest. MXFP8's e4m3 elements carry ~3 mantissa bits each, so "8-bit MX" is not strictly better than 6-bit or 4-bit affine with a per-group scale **and** bias on this weight distribution. It showed up in behaviour too: in the multi-turn gate MXFP8 dated Tokyo's capital move to 1936, where both JANG builds said 1868. ## Chat / reasoning - **Thinking is ON by default.** The generation prompt ends with an *open* `