demon-zombie commited on
Commit
1075a4d
·
verified ·
1 Parent(s): 705350b

Rewrite README: minimal style, drop perf data, match nvidia M2.5 recipe details

Browse files
Files changed (1) hide show
  1. README.md +33 -164
README.md CHANGED
@@ -1,187 +1,56 @@
1
  ---
2
  base_model:
3
  - MiniMaxAI/MiniMax-M2.7
4
- base_model_relation: quantized
5
  license: mit
6
- pipeline_tag: text-generation
7
- library_name: vllm
8
- tags:
9
- - nvfp4
10
- - fp4
11
- - quantization
12
- - modelopt
13
- - tensorrt-model-optimizer
14
- - mixture-of-experts
15
- - moe
16
- - minimax
17
  ---
18
 
19
- # MiniMax-M2.7 — NVFP4 (experts-only) + FP8 KV cache
20
-
21
- NVFP4 quantization of [MiniMaxAI/MiniMax-M2.7](https://huggingface.co/MiniMaxAI/MiniMax-M2.7) produced with
22
- [NVIDIA TensorRT Model Optimizer](https://github.com/NVIDIA/TensorRT-Model-Optimizer) (`modelopt` 0.43.0rc3).
23
-
24
- - **Base model:** MiniMax-M2.7 (230B total / 10B active, 256-expert MoE, 62 layers)
25
- - **Weight quant:** NVFP4 (W4A4, group size 16) — MoE expert MLPs only (`w1`, `w2`, `w3`)
26
- - **Attention / router / lm_head:** BF16 (unquantized)
27
- - **KV cache:** FP8 E4M3 with **static baked scales** (all `k_scale`/`v_scale` = 1.0 after calibration)
28
- - **Target hardware:** NVIDIA Blackwell (SM100 B200, SM120 RTX Pro 6000) with native NVFP4 tensor cores
29
- - **On-disk size:** 139.89 GB across 29 safetensors shards (vs. ~460 GB BF16)
30
-
31
- ## What's quantized
32
-
33
- Only the expert MLP projections in each MoE block (`block_sparse_moe.experts.{0..255}.w{1,2,3}`)
34
- are converted to NVFP4. Everything else — self-attention (`q_proj`/`k_proj`/`v_proj`/`o_proj`),
35
- router (`block_sparse_moe.gate`), embeddings, layernorms, and `lm_head` — stays in BF16.
36
- This matches the `excluded_modules` declaration in [`hf_quant_config.json`](./hf_quant_config.json):
37
-
38
- ```json
39
- {
40
- "quantization": {
41
- "quant_algo": "NVFP4",
42
- "kv_cache_quant_algo": "FP8",
43
- "group_size": 16,
44
- "exclude_modules": [
45
- "lm_head",
46
- "*self_attn*",
47
- "*block_sparse_moe.gate*"
48
- ]
49
- }
50
- }
51
- ```
52
 
53
- ## Calibration recipe
54
-
55
- - **modelopt recipe:** `nvfp4_experts_only-fp8_kv` (variant of `nvfp4_default-fp8_kv`
56
- that leaves attention projections in BF16)
57
- - **Calibration data:** 1024 samples — 512 from `cnn_dailymail` + 512 from
58
- `nvidia/OpenMathReasoning` (math reasoning traces), each truncated to 2048 tokens
59
- - **Batch size:** 64, `seq_len=2048`
60
- - **All-expert activation:** `--moe_calib_experts_ratio 1.0` forces every forward pass
61
- during calibration to dispatch to all 256 experts in each layer. This is critical —
62
- natural top-k routing over 1024 samples leaves roughly 6 experts across the 62 layers
63
- completely cold (amax=0), which in turn makes their NVFP4 block scales degenerate and
64
- produces characteristic "spurious space" token glitches during inference (e.g.
65
- `"mpg_ high"`, `"SPEC. md"`). Forcing full-expert coverage eliminates this class of
66
- quality regression entirely.
67
- - **KV cache scales:** statically calibrated and baked into the safetensors (not computed
68
- on-the-fly at serving time). This avoids the silent per-layer `k_scale`/`v_scale = 1.0`
69
- fallback in vLLM when KV scales are missing from the checkpoint.
70
- - **Quantizer fix (modelopt 0.43.0rc3):** 124 `use_constant_amax` quantizers (self-attention
71
- Q/K/V/O and router inputs) are missing `_amax` after calibration due to an upstream
72
- modelopt bug. Before export we explicitly register `_amax = 448.0` on each one — the
73
- correct FP8 E4M3 saturation value. Without this fix the export silently produces a
74
- checkpoint that loads but generates garbage.
75
- - **Hardware:** 4x H100 PCIe (80 GB) — the base BF16 model streams through at ~9 GB/expert
76
- layer; the run takes about 90 minutes end-to-end including calibration.
77
-
78
- ## Quality
79
-
80
- Smoke-tested with vLLM v0.19.0 on 2x RTX Pro 6000 (SM120 Blackwell).
81
-
82
- - **Prose generation** (5-sentence summary of the Battle of Thermopylae): passes.
83
- Correct dates (480 BCE), names (Leonidas, Xerxes, Ephialtes, Thespians, Salamis),
84
- coherent narrative, no glitch tokens, `finish_reason=stop`.
85
- - **Tool calling** (single-turn `get_weather` function): passes. Correct function
86
- selected, correct `{"location": "Boston"}` args, `<think>` reasoning properly
87
- separated into `reasoning_content` via the `minimax_m2` parser.
88
- - **No spurious-space tokens** observed across subword-heavy prompts — the cold-expert
89
- class of failure is gone.
90
-
91
- ## Hardware requirements
92
-
93
- NVFP4 requires **native FP4 tensor cores**, available on:
94
-
95
- | GPU | SM | Status |
96
- |-----|-----|--------|
97
- | B200 / GB200 | SM100 | native |
98
- | B100 | SM100 | native |
99
- | RTX Pro 6000 (Blackwell) | SM120 | native |
100
- | DGX Spark (GB10) | SM121 | native (requires 128×128×128 CUTLASS tile) |
101
- | H100 / H200 | SM90 | **not supported** (no FP4) |
102
- | A100 | SM80 | **not supported** |
103
-
104
- Minimum VRAM for TP=2 at `--max-model-len=196608`: ~90 GB per GPU (FP8 KV cache).
105
-
106
- ## Serving with vLLM
107
-
108
- Tested on **vLLM v0.19.0** with the FLASHINFER attention backend and `FLASHINFER_CUTLASS` NVFP4 MoE kernel (both auto-selected — no env vars needed).
109
-
110
- ```bash
111
- python3 -m vllm.entrypoints.openai.api_server \
112
- --model demon-zombie/MiniMax-M2.7-NVFP4 \
113
- --trust-remote-code \
114
- --served-model-name MiniMax-M2.7 \
115
- --tensor-parallel-size 2 \
116
- --max-model-len 196608 \
117
- --max-num-seqs 256 \
118
- --gpu-memory-utilization 0.90 \
119
- --tool-call-parser minimax_m2 \
120
- --reasoning-parser minimax_m2 \
121
- --enable-auto-tool-choice \
122
- --disable-custom-all-reduce \
123
- --host 0.0.0.0 \
124
- --port 8000
125
- ```
126
 
127
- ### Required flags
128
 
129
- - `--trust-remote-code` — the MiniMax M2 architecture uses custom Python modeling code.
130
- - `--disable-custom-all-reduce` — **critical on SM120 (RTX Pro 6000) with TP>1**.
131
- vLLM's custom CUDA all-reduce hangs post-weight-load on Pro 6000: workers spin at
132
- 100% SM utilization with 0 memory traffic and minimal power draw, and EngineCore
133
- logs `No available shared memory broadcast block found in 60s` every minute. Passing
134
- `--disable-custom-all-reduce` falls back to NCCL and avoids the hang. This is required
135
- even on tagged v0.19.0-cu130. Not needed on B200.
136
- - Do **not** pass `--enforce-eager`. Earlier reports suggested eager mode was required
137
- on Blackwell — this is no longer true as of vLLM v0.19.0. CUDA graphs capture cleanly
138
- (PIECEWISE mixed prefill-decode + FULL decode, 51 + 35 graphs captured) and give
139
- roughly 5x single-stream throughput and 2x aggregate throughput at 8x concurrency
140
- compared to eager. No accuracy regression.
141
 
142
- ### Backend auto-selection
143
 
144
- vLLM automatically picks:
145
 
146
- - **NVFP4 MoE kernel:** `FLASHINFER_CUTLASS` (picked via `enable_sm120_or_later` logic)
147
- - **KV cache dtype:** `fp8_e4m3` (picked because `kv_cache_quant_algo: FP8` is in
148
- `hf_quant_config.json` and the static `k_scale`/`v_scale` tensors are present in the shards)
149
- - **Attention backend:** `FLASHINFER`
150
 
151
- ## Performance
 
 
 
152
 
153
- Measured on **2x RTX Pro 6000 (SM120 Blackwell, 96 GB each)**, vLLM v0.19.0, TP=2,
154
- `--disable-custom-all-reduce`, CUDA graphs enabled, `max-model-len=196608`:
155
 
156
- ### Sequential (single request, gen=500)
157
 
158
- | Context | tok/s | TTFT |
159
- |---------|------:|-----:|
160
- | warmup | 80.7 | 1.26 s |
161
- | 9K | 77.1 | 1.11 s |
162
- | 9K cached | 78.5 | 0.40 s |
163
- | 18K | 76.0 | 1.25 s |
164
- | 27K | 74.3 | 1.43 s |
165
- | 27K cached | 73.0 | 0.77 s |
166
 
167
- ### Concurrent (ctx=32K, gen=500, 0 errors)
168
 
169
- | Concurrency | agg tok/s | TTFT avg |
170
- |------------:|----------:|---------:|
171
- | 8x | **201.8** | 6.95 s |
172
- | 16x | **427.8** | 1.33 s |
173
 
174
- For reference, a W4A16 (Marlin) build of the same base model on the same hardware
175
- with `--enforce-eager` runs at ~14 tok/s single / 86 tok/s @8x / 141 tok/s @16x —
176
- so NVFP4 on Blackwell is roughly 5x single-stream, 2.3x @8x, and 3x @16x, with
177
- zero errors at 16-way concurrent 32K contexts.
178
 
179
- ## License
 
 
 
 
 
 
 
 
 
 
 
 
180
 
181
- MIT, inherited from the base model [MiniMaxAI/MiniMax-M2.7](https://huggingface.co/MiniMaxAI/MiniMax-M2.7).
182
 
183
- ## Credits
184
 
185
- - **Base model:** [MiniMaxAI/MiniMax-M2.7](https://huggingface.co/MiniMaxAI/MiniMax-M2.7)
186
- - **Quantization toolchain:** [NVIDIA TensorRT Model Optimizer](https://github.com/NVIDIA/TensorRT-Model-Optimizer)
187
- - **Inference runtime:** [vLLM](https://github.com/vllm-project/vllm)
 
1
  ---
2
  base_model:
3
  - MiniMaxAI/MiniMax-M2.7
 
4
  license: mit
 
 
 
 
 
 
 
 
 
 
 
5
  ---
6
 
7
+ ## Model Description
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
+ **MiniMax-M2.7-NVFP4** is an NVFP4-quantized version of [MiniMaxAI/MiniMax-M2.7](https://huggingface.co/MiniMaxAI/MiniMax-M2.7), a 230B-parameter Mixture-of-Experts language model with 10B active parameters.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ Produced with [NVIDIA TensorRT Model Optimizer](https://github.com/NVIDIA/TensorRT-Model-Optimizer) (`modelopt` 0.43.0rc3) using the `nvfp4_experts_only-fp8_kv` recipe — the same recipe structure as [`nvidia/MiniMax-M2.5-NVFP4`](https://huggingface.co/nvidia/MiniMax-M2.5-NVFP4). The base model is quantized directly from its official FP8 checkpoint via modelopt's on-the-fly FP8→BF16 dequant path (no separate BF16 master), then requantized to NVFP4.
12
 
13
+ ### What's quantized
 
 
 
 
 
 
 
 
 
 
 
14
 
15
+ Only the MoE expert MLP layers (`w1`, `w2`, `w3` — gate, up, down projections) are quantized to NVFP4 (W4A4, group size 16). Self-attention projections, the MoE router, embeddings, layernorms, and `lm_head` are left in BF16. The `exclude_modules` list in `hf_quant_config.json` matches `nvidia/MiniMax-M2.5-NVFP4` exactly.
16
 
17
+ The KV cache is quantized to FP8 E4M3 with **statically calibrated scales** baked into the safetensors as per-layer `k_proj.k_scale` / `v_proj.v_scale` tensors (62 of each). This avoids vLLM's silent `scale=1.0` fallback when KV scales are missing from the checkpoint.
18
 
19
+ ### Calibration
 
 
 
20
 
21
+ - **Recipe:** `nvfp4_experts_only-fp8_kv`
22
+ - **Dataset:** `cnn_dailymail` + `nvidia/Nemotron-Post-Training-Dataset-v2` (same as nvidia's M2.5 quant)
23
+ - **Samples:** 1024
24
+ - **Full expert coverage:** calibration is run with `--moe_calib_experts_ratio 1.0`, which sets the MoE top-k to 256 during calibration so every token activates every expert in every layer. This guarantees all 256 × 62 = 15,872 experts receive a non-zero `amax` regardless of dataset routing, and eliminates the cold-expert failure mode (spurious spaces at subword boundaries, e.g. `"mpg_ high"`, `"SPEC. md"`) seen when experts are calibrated via natural top-k routing alone.
25
 
26
+ ### Hardware
 
27
 
28
+ NVFP4 requires native FP4 tensor cores — NVIDIA Blackwell (B100 / B200, RTX Pro 6000, DGX Spark GB10). Not supported on H100/H200 or older.
29
 
30
+ ### Quality
 
 
 
 
 
 
 
31
 
32
+ Smoke-tested with vLLM v0.19.0 on 2x RTX Pro 6000 (SM120): prose generation and single-turn tool calling both pass, no spurious-space tokens observed. You should always evaluate against your specific use case.
33
 
34
+ ## Usage
 
 
 
35
 
36
+ ### vLLM
 
 
 
37
 
38
+ Tested on `vllm/vllm-openai:v0.19.0-cu130` with 2x RTX Pro 6000 Blackwell:
39
+
40
+ ```sh
41
+ vllm serve demon-zombie/MiniMax-M2.7-NVFP4 \
42
+ --trust-remote-code \
43
+ --served-model-name MiniMax-M2.7 \
44
+ --tensor-parallel-size 2 \
45
+ --max-model-len 196608 \
46
+ --tool-call-parser minimax_m2 \
47
+ --reasoning-parser minimax_m2 \
48
+ --enable-auto-tool-choice \
49
+ --disable-custom-all-reduce
50
+ ```
51
 
52
+ `--disable-custom-all-reduce` is **required** on RTX Pro 6000 (SM120) with TP > 1 — vLLM's custom CUDA all-reduce hangs post-weight-load (workers spin at 100% SM with 0 memory traffic). Not needed on B200. Do **not** pass `--enforce-eager`; CUDA graphs capture cleanly on v0.19.0.
53
 
54
+ ### SGLang
55
 
56
+ (pending)