MiniCPM5-2B-NVFP4
openbmb/MiniCPM5-2B quantized to NVFP4
(4-bit weights and 4-bit activations, group size 16, FP8 block scales) with
llm-compressor GPTQ, in the
compressed-tensors format that vLLM loads natively.
It pairs with the official openbmb/MiniCPM5-2B-DSpark draft model for speculative decoding — the drafter stays BF16 and attaches to this quantized target without any conversion. Measured 2.7x decode speedup on code.
Baked by Lna-Lab on 8x RTX PRO 2000 Blackwell (single GPU used for this model).
Read this before using it for English reasoning. Quantization changed where this model stops thinking, and not in a small way. On 250 English GSM8K problems (MGSM-en, greedy, strict parsing) this checkpoint fails to emit a closing
</think>75-77% of the time, at both a 2048- and a 6144-token budget — the BF16 original fails 19%. The reasoning itself is fine: among the answers that do terminate, 98% are correct. But if your stack needs</think>to end a turn, budget generously and expect truncation in English. In Japanese the same change runs the other way and is a clear improvement. Numbers and the whole story are in Verbosity and stopping below.
What was chosen, and why
Four rounding methods and two activation precisions were baked and measured against the BF16 original. The table below is the whole reason this checkpoint uses GPTQ:
| recipe | format | wikitext2 | ja-wikipedia | python source | mean Δ | size |
|---|---|---|---|---|---|---|
| BF16 original (reference) | — | 13.095 | 13.113 | 2.359 | — | 5.03 GB |
| RTN | NVFP4 W4A4 | 15.081 (+15.17%) | 15.101 (+15.16%) | 2.707 (+14.76%) | +15.03% | 2.18 GB |
| AWQ * | NVFP4 W4A4 | 14.509 (+10.79%) | 14.599 (+11.33%) | 2.535 (+7.47%) | +9.87% | 2.18 GB |
| AutoRound | NVFP4 W4A4 | 14.662 (+11.96%) | 14.419 (+9.96%) | 2.498 (+5.90%) | +9.27% | 2.18 GB |
| GPTQ | NVFP4A16 (weight-only) | 13.577 (+3.68%) | 13.510 (+3.02%) | 2.438 (+3.37%) | +3.36% | 2.18 GB |
| GPTQ — this checkpoint | NVFP4 W4A4 | 13.574 (+3.66%) | 13.509 (+3.02%) | 2.437 (+3.33%) | +3.34% | 2.18 GB |
| GPTQ + actorder | NVFP4 W4A4 | 13.574 (+3.66%) | 13.509 (+3.02%) | 2.437 (+3.33%) | +3.34% | 2.18 GB |
| GPTQ, 1024 samples @ 4096 | NVFP4 W4A4 | 13.741 (+4.93%) | 13.535 (+3.22%) | 2.422 (+2.67%) | +3.61% | 2.18 GB |
| GPTQ, last 4 layers BF16 | mixed | 13.463 (+2.81%) | 13.451 (+2.58%) | 2.423 (+2.73%) | +2.71% | 2.46 GB |
| GPTQ, last 8 layers BF16 | mixed | 13.413 (+2.43%) | 13.407 (+2.24%) | 2.412 (+2.26%) | +2.31% | 2.73 GB |
| GPTQ, last 12 layers BF16 | mixed | 13.361 (+2.03%) | 13.362 (+1.90%) | 2.406 (+2.00%) | +1.98% | 3.00 GB |
* AWQ ran out of memory at the full calibration size on a 16 GB card and was measured with 192 samples at 1024 tokens instead of 512 at 2048. Its gap to GPTQ is far larger than that difference plausibly explains, but it is not a like-for-like comparison.
Two findings drove the recipe:
- Activation precision is free here. NVFP4 W4A4 and weight-only NVFP4A16 land within 0.03% of each other on every corpus. MiniCPM5-2B's activations survive 4-bit dynamic group-16 quantization intact, so this checkpoint ships W4A4 and keeps the native FP4 GEMM path.
- Weight rounding is the whole story. Round-to-nearest costs ~15% perplexity; GPTQ costs ~3%. AutoRound landed in between on this model.
lm_head and the embeddings are left in BF16.
Serving
Plain vLLM:
vllm serve sakamakismile/MiniCPM5-2B-NVFP4 \
--max-model-len 32768 --gpu-memory-utilization 0.5
With the official DSpark drafter (recommended — the drafter is BF16 and needs no conversion):
vllm serve sakamakismile/MiniCPM5-2B-NVFP4 \
--max-model-len 32768 --gpu-memory-utilization 0.5 \
--speculative-config '{"model":"openbmb/MiniCPM5-2B-DSpark","method":"dspark","num_speculative_tokens":7}'
Sampling: the model's own generation_config.json asks for temperature 1.0 / top_p 0.95. That is
too hot for Japanese (see Japanese below) — use 0.3-0.6 there.
num_speculative_tokens should be 7, the block size the drafter was trained with.
vLLM resolves the drafter's target_layer_ids [1,10,20,30,39] into auxiliary hidden-state
layers (2,11,21,31,40) on the quantized target automatically.
Requires a vLLM build with the DSpark speculator and Qwen3DSparkModel in the model registry.
For tool calling, add the parser — vLLM ships one for this model's XML dialect:
vllm serve sakamakismile/MiniCPM5-2B-NVFP4 \
--max-model-len 32768 --gpu-memory-utilization 0.5 \
--enable-auto-tool-choice --tool-call-parser minicpm5
Verified end to end on this checkpoint: an English or Japanese request comes back with
finish_reason: "tool_calls" and structured tool_calls, and feeding the tool result back
produces the final answer. Without those two flags vLLM rejects any request carrying tools.
⚠️ Offline
LLM.generateusers:<function,<param,</param>and</function>are special tokens in this tokenizer. The defaultskip_special_tokens=Truesilently deletes them, leaving debris likename="get_weather"> name="city">Osakathat no parser can read — the model looks like it cannot call tools when it is calling them perfectly. PassSamplingParams(skip_special_tokens=False). The server path with--tool-call-parser minicpm5handles this for you.
Measured speed
Single stream, one RTX PRO 2000 Blackwell (16 GB), greedy, 768 output tokens.
Median of 3 runs; --max-model-len 32768, --max-num-seqs 8, prefix caching on.
| workload | no speculation | DSpark n=7 | speedup | accepted length |
|---|---|---|---|---|
| code generation | 137 tok/s | 366 tok/s | 2.67x | 5.02 / 7 |
| math reasoning | 137 tok/s | 349 tok/s | 2.54x | 5.01 / 7 |
| general explanation | 137 tok/s | 304 tok/s | 2.22x | 4.17 / 7 |
| Japanese prose | 137 tok/s | 165 tok/s | 1.21x | 2.24 / 7 |
Run-to-run spread on the speculative numbers is real: an earlier independent measurement of code generation gave 378 tok/s against this table's 366. Treat these as a band, not a constant.
Speculation pays where the next token is structurally determined — code and math — and barely moves prose. That is the expected shape for block drafting, not a defect.
Measured quality
Own harness, greedy, zero-shot chat format: GSM8K (first 250 test problems, numeric match) and HumanEval (all 164, executed). These absolute numbers are not comparable to published scores — the prompting and extraction are mine and cost the base model several points. The comparison between rows is the point.
| checkpoint | GSM8K | HumanEval pass@1 |
|---|---|---|
| BF16 original | 205/250 = 82.0% | 74/164 = 45.1% |
| NVFP4 GPTQ — this checkpoint | 201/250 = 80.4% | 65/164 = 39.6% |
| NVFP4 + last 8 layers BF16 | 193/250 = 77.2% | 62/164 = 37.8% |
Why this checkpoint is not the mixed-precision one. Leaving the last 8 decoder layers in BF16 improves perplexity clearly (mean +2.31% against +3.34%), and GPTQ's own reconstruction error grows monotonically with depth, so those layers really are where the damage is. But it did not improve either downstream score — both differences are under one standard error, so nothing was demonstrated — while costing 21% of decode speed (108 against 137 tok/s) and 25% more disk. Perplexity alone was not enough to justify that, so the plain, fully-quantized NVFP4 build ships.
Also verified on this checkpoint: Japanese generation, tool-call XML emission per the model's own template, and needle retrieval at 11.4k and 24.4k tokens of context (both found).
Tool calling
22 situations, each posed in English and Japanese, through the model's own chat template with
tools=: straightforward calls, multi-parameter extraction, questions that need no tool,
requests missing a required argument, two-step tasks, and continuing after a tool result.
| category | NVFP4 @ temp 0.3 | NVFP4 @ greedy | BF16 @ greedy |
|---|---|---|---|
| picks the right tool and fills it | EN 10/10, JA 9/10 | EN 10/10, JA 9/10 | EN 10/10, JA 10/10 |
| stays quiet when no tool is needed | EN 4/5, JA 4/5 | EN 3/5, JA 5/5 | EN 1/5, JA 5/5 |
| asks instead of inventing a missing argument | EN 2/2, JA 1/2 | EN 2/2, JA 1/2 | EN 2/2, JA 1/2 |
| answers from a returned tool result | EN 3/3, JA 3/3 | EN 3/3, JA 1/3 | EN 3/3, JA 2/3 |
| overall | EN 19/22, JA 17/22 | EN 18/22, JA 16/22 | EN 16/22, JA 18/22 |
Tool selection and argument extraction are excellent and do not depend on the language. Every malformed-XML check came back clean: 0 malformed calls across all runs.
The weak spots, in both the quantized checkpoint and the BF16 original:
- Reaching for a tool when it should just answer, and only in English. Asked the capital of
France or why the sky is blue, the BF16 original calls
search_web4 times out of 5; this checkpoint does it 1-2 times out of 5. In Japanese both answer directly, 5/5. - Inventing a missing required argument. "Email the team about the delay" makes both models
invent
team@example.comrather than asking who the team is. - One call per turn. Given a two-step task both emit only the first call. That is normal agent behaviour, not a defect, but do not expect two calls in one response.
temp 0.3 is the best operating point — it beats greedy on both languages and was the only setting where nothing ran past the token budget.
Verbosity and stopping
Greedy, 250 MGSM problems per language, strict scoring (an answer counts only if the model closed
its </think> block). Two seeds each; the pair shows run-to-run spread.
| checkpoint | English: did not stop | Japanese: did not stop |
|---|---|---|
| BF16 original | 47, 50 / 250 (19%) | 145, 146 / 250 (58%) |
| this NVFP4 checkpoint | 193, 195 / 250 (77%) | 42, 44 / 250 (17%) |
| NVFP4 + last 8 layers BF16 | 174, 177 / 250 (70%) | 45, 47 / 250 (18%) |
Quantization swapped which language the model cannot stop thinking in. Both independently baked quantized checkpoints moved the same way, across both seeds, so this is a property of the quantization and not casting variance.
Raising the budget rescues Japanese but not English:
| budget | Japanese: did not stop | English: did not stop |
|---|---|---|
| 2048 | 44 (18%) | 193 (77%) |
| 6144 | 16 (6%) | 187 (75%) |
| 12288 | 8 (3%) | not measured |
In Japanese the median answer takes 682 tokens with a long tail — verbose, but it finishes. In English the median output is the cap at both 2048 and 6144: it does not finish. Accuracy among answers that do terminate stays high throughout (English 98%, Japanese 80-86%).
The GSM8K and HumanEval numbers in the previous section were scored with a lenient parser that accepts an answer found anywhere in the output, including inside an unterminated think block. That is why they look healthy while the table above does not. Both are true; they measure different things. If you need the model to stop on its own, the table above is the one that matters.
Japanese
The base model declares only English and Chinese, but its Japanese is real, and lopsided: it reads Japanese much better than it writes it.
| measure | BF16 original | this checkpoint |
|---|---|---|
| JCommonsenseQA (1119, accuracy among answered) | 96.9% | 84.6% |
| JCommonsenseQA (answered at all) | 745 (67%) | 1112 (99%) |
| MGSM Japanese, 12288-token budget | not measured | 77.2% |
| perplexity on Japanese Wikipedia | 13.113 | 13.510 (+3.02%) |
Note that quantization costs less perplexity in Japanese (+3.02%) than in English (+3.66%), and that this checkpoint answers 99% of the Japanese commonsense questions against the original's 67%.
What it does well: reading, summarizing, and classifying Japanese. Simplified-Chinese characters almost never leak into its Japanese output (5 stray characters in 1785 kanji, 0.3%, and 2 of those 5 are rare-but-valid Japanese).
What it does badly, at every temperature and in the BF16 original too:
- Honorifics are wrong. Asked for the honorific and humble forms of 見る it answers 見上げる and 見下す ("look up at" / "look down on") instead of ご覧になる and 拝見する. This is a knowledge gap, not a sampling artifact.
- Other languages leak into Japanese writing. A Japanese business email comes back with the Chinese placeholder 您的名字 in it; at the model's default temperature of 1.0, English and even Korean fragments appear mid-sentence.
- Register instructions are ignored. Asked for a casual message to a friend, it writes polite です/ます forms.
For Japanese, use a low temperature (0.3-0.6), not the model's default 1.0, and give it a generous token budget. Do not rely on it for honorific or business Japanese.
Calibration
512 sequences at 2048 tokens, drawn from a deliberate mix so no single domain sets the ranges:
| source | share |
|---|---|
general chat (neuralmagic/calibration, LLM split) |
55% |
| Python source files | 20% |
| Japanese Wikipedia | 15% |
| Chinese Wikipedia | 10% |
The included recipe.yaml is the exact llm-compressor recipe used.
Provenance and honesty notes
- Every number above is measured on this hardware, not copied from a paper or estimated.
- Perplexity is computed through vLLM itself (
prompt_logprobs), so it reflects the same kernels that serve the model, not a separate reference implementation. - Quantization is not a deterministic transform. Numbers here describe this checkpoint.
- The DSpark draft weights are not redistributed here; point vLLM at the official repo.
- The English stopping regression in Verbosity and stopping was found after this checkpoint was first published, by measuring it rather than assuming it. It is documented rather than hidden; a re-bake with a different calibration mix has not been attempted yet.
License
Apache-2.0, inherited from the base model. The base model, the DSpark drafter, and the training data are the work of OpenBMB.
Baked by ケンと一緒に研究している Lna-Lab のユキ(Fable 5.1).
- Downloads last month
- 223
Model tree for sakamakismile/MiniCPM5-2B-NVFP4
Base model
openbmb/MiniCPM5-2B