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

Add model card: recipe, hardware support, vLLM launch config, benchmarks

Browse files
Files changed (1) hide show
  1. README.md +187 -0
README.md ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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)