~/satyajit

MiniCPM5-2B: how 2 KV heads pay for a 131K window

mdjsonmcp

2026-09-08 · 26 min · llm · on-device · gqa · kv-cache · quantization · speculative-decoding · long-context

openbmb/MiniCPM5-2B is a dense 2B-class language model that, per its own README, reaches "2B-class open-source SOTA" across 34 benchmarks, natively handles a 131,072-token context, and ships with an open speculative-decoding draft, a Q4/Q8/GPTQ/MLX/GGUF release matrix, and same-day recipes for vLLM, SGLang, llama.cpp, and five more inference backends. All of that is worth taking seriously. None of it comes with a tech report.

Pull the model repo's own metadata and it lists exactly two arXiv citations: 2506.07900MiniCPM4: Ultra-Efficient LLMs on End Devices — and 2602.09003, a data-tiering paper referenced once, for the pretraining data pipeline. Scroll to the bottom of the README and the BibTeX block still cites MiniCPM4. There is no MiniCPM5 paper. Every architectural and training claim this article makes about MiniCPM5-2B specifically rests on the model card, config.json, and the GitHub cookbooks — not a peer-reviewed report. Where the lineage runs through MiniCPM4's actual paper, this article says so explicitly and cites it as MiniCPM4, not MiniCPM5.

openbmb/MiniCPM5-2Bhugging face · snapshot 2026-09-08
parameters
2.52B
repo size
5.03 GB
architecture
LlamaForCausalLM
license
apache-2.0
downloads
13
likes
475
files
11
parameters by dtype
BF16 2.52B

What's actually in the config

Model cards can round; config.json cannot. Here are the fields that matter, fetched directly from the repo:

{
  "architectures": ["LlamaForCausalLM"],
  "model_type": "llama",
  "hidden_size": 2048,
  "intermediate_size": 6144,
  "num_hidden_layers": 42,
  "num_attention_heads": 16,
  "num_key_value_heads": 2,
  "head_dim": 128,
  "max_position_embeddings": 131072,
  "rope_theta": 5000000,
  "vocab_size": 130560,
  "tie_word_embeddings": false,
  "torch_dtype": "bfloat16"
}

Two things worth stopping on before anything else:

It's LlamaForCausalLM. Not a MiniCPM-specific architecture class, not InfLLM v2's trainable sparse attention from the MiniCPM4 paper — a stock Llama-style transformer with grouped-query attention. The README says this outright: "MiniCPM5-2B uses the standard LlamaForCausalLM architecture, so mainstream inference engines can load it directly: no custom kernels, no model-code fork." That is a real, useful engineering decision — every backend in this article works on day zero because of it — but it also means MiniCPM5 did not inherit MiniCPM4's headline sparse-attention mechanism. What it inherited is the training philosophy: the data pipeline, the tiered data management, the RL recipe. The architecture reverted to something engines already know how to run fast.

"2B" is 2.52B. The Hugging Face API reports 2,516,756,480 BF16 parameters — 2.52 billion, 1.98B of them outside the embedding and LM head (vocab_size=130560 at hidden_size=2048 makes the embedding table alone about 267M parameters, doubled since tie_word_embeddings: false means input and output embeddings are separate weights). usedStorage on the repo is 5,033,557,096 bytes, which is 2,516,756,480 × 2 to within rounding — consistent with a straight BF16 release. None of this makes "2B" dishonest; every model in its comparison set rounds the same way. It's just worth naming once, in numbers, rather than letting the name do the rounding silently.

Repoopenbmb/MiniCPM5-2B · Apache-2.0 · BF16 final release, post-trained with RL + OPD
Params2,516,756,480 total (2.52B) · 1,981,982,720 non-embedding
Shape42 layers · hidden 2048 · intermediate 6144 · 16 attention heads, 2 KV heads (8:1 GQA) · head dim 128
Context131,072 tokens native, rope_theta 5,000,000
Siblings-SFT (pre-RL), -Midtrain, -Base, -GGUF, -MLX, -GPTQ, -DSpark (draft model) — plus a smaller MiniCPM5-1B series
Cited papersMiniCPM4 (2506.07900) and a data-tiering paper (2602.09003) — no MiniCPM5 report

The lineage, from a paper that isn't about this model

Since MiniCPM5 doesn't have its own report, the honest way to talk about where it came from is to go read the paper it does cite and be careful about what transfers. MiniCPM4's abstract targets exactly this problem — efficient end-device LLMs — across four axes: architecture (InfLLM v2 trainable sparse attention), training data (the UltraFineWeb / UltraClean filtering lineage this site has covered separately), training algorithms (a µP-style hyperparameter search called ModelTunnel v2, plus chunk-wise RL rollouts), and inference systems (speculative decoding via FR-Spec, a CPU/GPU inference framework called CPM.cu).

Diagram of InfLLM v2's two-stage sparse attention: Stage 1 scores block-partitioned KV cache against semantic kernels and selects top-k relevant blocks per query group; Stage 2 computes exact attention only over the selected blocks.
MiniCPM4's InfLLM v2 trainable sparse attention (paper, Figure 2) — the architecture MiniCPM4-8B shipped. MiniCPM5-2B does not use this; it runs plain GQA attention instead, for engine compatibility.

That figure is here for contrast, not lineage. InfLLM v2 is what let MiniCPM4-8B post the speed numbers in its own headline chart:

Bar charts comparing prefilling and decoding token/s at 32k, 64k, 96k, and 128k context on a Jetson AGX Orin and an RTX 4090, for Llama-3-8B, GLM-4-9B, Qwen-3-8B, and MiniCPM4-8B. MiniCPM4-8B leads every bar, with the gap widening at longer context.
MiniCPM4-8B vs. three same-class open models on end-side hardware (paper, Figure 1) — this is a MiniCPM4-8B result, not MiniCPM5-2B; it establishes why sparse attention was worth building, not what MiniCPM5-2B's speed looks like.

MiniCPM5-2B is a different model, a different size class, and — per the README's own words above — a different attention mechanism entirely. What plausibly does carry over from MiniCPM4 to MiniCPM5 is everything data- and training-shaped: the UltraFineWeb/UltraClean filtering approach, tiered data management (now formalized in the 2602.09003 paper cited on this repo), and the general end-device efficiency mandate. What does not carry over, on the model's own admission, is the sparse-attention architecture. If MiniCPM5-2B is fast and cheap to serve at long context, the mechanism is downstream of GQA and aggressive quantization support — covered next — not of InfLLM v2.

Why 2 KV heads is the whole story

config.json, drawn: why 2 KV heads is the whole trick5.64 GB KV cache @ 131,072 tokens
16 query heads : 2 KV heads (8:1)
GQA as shipped: 16 query heads mapping to 2 key/value heads. Per-token KV cache bytes across all 42 layers: 43,008. At the model's native 131,072-token context that is 5.64 GB.16 query heads (unchanged by this choice)2 key/value heads — this is what gets cached, per token, per layer
bytes / token / layer
2 × 128 × 2 × 2 = 1,024 B
× 42 layers
43,008 B/token
× 131,072 tokens
5.64 GB

Every query head still gets its own attention output — GQA doesn’t shrink the model, and nothing here touches the 16 query heads on top. What shrinks is what has to be stored: with 2 KV heads, groups of 8 query heads share one cached key/value pair, so the cache pays for 2 heads instead of 16. Toggle to the hypothetical MHA panel — same model, same 131K context, only num_key_value_heads changed from 2 to 16 — and the cache at full context jumps from 5.64 GB to 45.10 GB, exactly 8× larger. 45.10 GB of KV cache alone doesn’t fit on any consumer GPU sold today, at any weight quantization. The 8:1 GQA ratio isn’t a minor efficiency knob here — it’s the difference between a 131K context window that fits in a laptop and one that doesn’t exist outside a datacenter.

Grouped-query attention doesn't change how many query heads compute attention outputs — it changes how many distinct key/value projections have to be cached. MiniCPM5-2B ships 16 query heads sharing only 2 KV heads, an 8:1 ratio that is aggressive even among GQA models (Llama-3.1-8B ships 8 KV heads for 32 query heads, a 4:1 ratio, for comparison). Every group of 8 query heads reads the same cached key and value at inference time. The compute cost of attention doesn't move; the memory cost of storing that cache for every generated token, in every layer, for the life of the request, drops in direct proportion to the KV-head count.

The KV-cache arithmetic

This is the number the rest of the article turns on, so it's worth deriving instead of quoting. Per-token KV cache size, across the whole model, is:

layers = 42
kv_heads = 2
head_dim = 128
dtype_bytes = 2       # f16 — 2 bytes per element
context = 131_072     # native max_position_embeddings
 
per_token = layers * kv_heads * head_dim * 2 * dtype_bytes  # the "2" is K and V
total = per_token * context
 
print(per_token)        # 43,008 bytes/token
print(total)             # 5,637,144,576 bytes
print(total / 1e9)       # 5.637 GB

At the model's native 131,072-token context and f16 KV cache, that's 5,637,144,576 bytes — 5.637 GB — of KV cache alone, before a single weight is loaded. Now check it against a real deployment report: someone running MiniCPM5-2B-GGUF on a single RTX 3060 with

llama-server -m MiniCPM5-2B-Q8_0.gguf -ngl 99 -c 131072 -fa on --jinja \
  -np 1 -ctk f16 -ctv f16 -b 2048 -ub 1024 --temp 1.0 --top-p 0.95

measured Q4_K_M at ~163 tok/s decode, 7.2GB total VRAM, and Q8_0 at ~113 tok/s decode, 8.2GB total VRAM, both with prefill around 5,800 tok/s, and reported that "most of that VRAM is the 131K KV cache." The GGUF weight files are 1.56GB (Q4_K_M) and 2.68GB (Q8_0). Subtract:

Both land within rounding of the derived 5.637GB. The claim checks out — not approximately, but to the byte on the Q4_K_M side. And the mechanism is exactly the 2-KV-head geometry above: an MHA model with 16 KV heads instead of 2 would need 8× that cache — 45,097,156,608 bytes, ~45GB — before weights, which doesn't fit on any consumer GPU sold today regardless of how aggressively the weights themselves are quantized. The 131K window isn't cheap because the model is small. It's cheap because the cache is small, and the cache is small because of a single config field.

weights + KV cache vs. common GPU VRAMfits an 12 GB card
context131,072 tok
Q8_0 weights (2.68 GB) plus 131,072 tokens of f16 KV cache (5.64 GB) totals 8.32 GB. Reference lines at 8, 12, 16 and 24 GB.8 GB12 GB16 GB24 GBweights 2.68 GBKV cache 5.64 GBtotal 8.32 GB
8 GB 12 GB 16 GB 24 GB

The KV cache is layers × kv_heads × head_dim × 2 × dtype_bytes per token — for MiniCPM5-2B, 42 × 2 × 128 × 2 × 2 = 43,008 bytes at f16, times however many tokens are in the window. At the model’s native 131,072-token context that alone is 5.64 GB, which is why a Q4_K_M run measures in at 7.2 GB total — 1.56 GB of weights plus that cache — and a Q8_0 run at 8.2 GB. The weights barely move the total; the context window does essentially all of the work, which is exactly what “most of that VRAM is the KV cache” means once you do the arithmetic. Drag context down and the picture flips: at 32K tokens even the least-quantized Q8_0 build settles comfortably under 8 GB, because the cache shrinks linearly with the window while the weights don’t move at all.

The corollary the RTX 3060 report drew, and the slider above reproduces: drop the context window and the budget opens up fast, because weights barely move while the cache scales linearly with tokens. A Q8_0 build at 32K tokens instead of 131K needs roughly 2.68 + 1.41 ≈ 4.1GB — comfortable on an 8GB card with headroom to spare, or on a shared/multi-tenant box.

What 34 benchmarks actually say

The README's evaluation table compares MiniCPM5-2B against eight other models: three in its own 2B class (LFM2.5-2.6B, Qwen3.5-2B, Gemma-4-E2B-it) and five larger ones listed for reference (Qwen3.5-4B, granite-4.2-3B, Nemotron-3-Nano-4B, Gemma-4-E4B-it, LFM2.5-8B-A1B). The card's claim is an average of 53.9 across 34 benchmarks spanning nine categories, ahead of every model in the comparison set including the 4B-class ones (highest there: 51.1). Averaging MiniCPM5-2B's own 34 column values by hand reproduces 53.88 — the card's number is not a rounding trick, it's the real mean of the rows below.

the README’s own evaluation table, 34 benchmarks / 9 models
MiniCPM5-2B average, this filter: 53.9 · best of 9 on 18/34 rows
benchmarkMiniCPM5-2Bbest of restmargin
LiveCodeBench v669.158.9 (granite-4.2-3B)+10.2
LCB-Pro 25Q2 (Easy)68.058.3 (Qwen3.5-4B)+9.7
LCB-Pro 25Q2 (Medium)17.57.0 (Qwen3.5-4B)+10.5
OJBench32.524.8 (Qwen3.5-4B)+7.7
SciCode (wbg)26.324.9 (granite-4.2-3B)+1.4
AIME 202586.579.4 (granite-4.2-3B)+7.1
AIME 202686.583.5 (granite-4.2-3B)+3.0
HMMT Feb 202663.864.0 (Qwen3.5-4B)-0.2
MATH-50094.699.0 (Qwen3.5-4B)-4.4
IFBench66.373.0 (granite-4.2-3B)-6.7
IFEval86.793.7 (granite-4.2-3B)-7.0
Multi-IF71.876.8 (LFM2.5-2.6B)-5.0
MMLU-Pro70.878.0 (Qwen3.5-4B)-7.2
MMLU-Redux84.788.7 (Qwen3.5-4B)-4.0
HLE8.99.9 (Qwen3.5-4B)-1.0
GPQA-Diamond70.277.1 (Qwen3.5-4B)-6.9
SuperGPQA40.852.8 (Qwen3.5-4B)-12.0
AA-LCR59.061.0 (Qwen3.5-4B)-2.0
NoLiMa68.143.5 (Qwen3.5-4B)+24.6
LongBenchPro44.858.4 (Qwen3.5-4B)-13.6
LongBench v243.747.3 (Qwen3.5-4B)-3.6
τ³-Bench Banking20.87.2 (LFM2.5-2.6B)+13.6
τ²-Bench Telecom97.192.1 (Qwen3.5-4B)+5.0
BFCL v466.661.1 (LFM2.5-2.6B)+5.5
SWE-bench Verified46.436.8 (granite-4.2-3B)+9.6
SWE-bench Pro14.428.2 (Qwen3.5-4B)-13.8
Terminal-Bench v2.18.625.8 (Qwen3.5-4B)-17.2
BrowseComp-ZH43.539.6 (Qwen3.5-4B)+3.9
BrowseComp Top10039.733.3 (Qwen3.5-4B)+6.4
GAIA Text-10388.778.6 (Qwen3.5-4B)+10.1
GDPval-AA v219.611.7 (Qwen3.5-4B)+7.9
Claw-Gym59.260.0 (granite-4.2-3B)-0.8
WildClaw23.920.0 (granite-4.2-3B)+3.9
QwenClaw42.937.1 (Qwen3.5-4B)+5.8

Every row here is transcribed from the card’s own table, not re-scored. Filtered to All categories against all 9 models, the live average above comes out to 53.9 — reproducing the card’s headline number from the per-benchmark rows themselves, not just quoting it. Switch to 2B-class only and MiniCPM5-2B’s lead widens on almost every row, which is expected — the 4B-class column includes models nearly double its parameter count.

The full table, transcribed as published (blue-bold-equivalent: bold marks the best result across all 9 models; a dagger † marks scores sourced from the official Artificial Analysis release rather than reproduced internally):

BenchmarkMiniCPM5-2BLFM2.5-2.6BQwen3.5-2BGemma-4-E2B-itQwen3.5-4Bgranite-4.2-3BNemotron-3-Nano-4BGemma-4-E4B-itLFM2.5-8B-A1B
Code Reasoning
LiveCodeBench v669.142.120.242.956.458.950.753.939.8
LCB-Pro 25Q2 (Easy)68.030.910.327.158.354.651.645.827.8
LCB-Pro 25Q2 (Medium)17.50.00.00.07.05.35.31.80.0
OJBench32.511.22.611.624.821.820.019.08.2
SciCode (wbg) †26.314.22.820.916.124.916.424.47.8
Math Reasoning
AIME 202586.541.929.631.778.879.456.337.146.0
AIME 202686.545.229.039.882.783.562.145.056.7
HMMT Feb 202663.833.720.517.864.060.851.330.138.5
MATH-50094.689.685.885.499.097.091.688.293.2
Instruction Following
IFBench66.359.046.025.759.073.058.328.351.0
IFEval86.793.477.531.490.293.788.044.490.8
Multi-IF71.876.857.140.373.675.965.945.971.4
General Knowledge
MMLU-Pro70.865.264.356.078.065.865.768.363.1
MMLU-Redux84.780.080.071.888.778.979.883.780.0
HLE †8.96.22.64.89.96.64.93.86.9
GPQA-Diamond †70.255.845.643.377.155.951.357.651.3
SuperGPQA40.826.238.630.352.839.937.838.734.5
Long Context
AA-LCR †59.05.328.717.061.024.317.333.00.0
NoLiMa68.10.717.13.943.55.11.12.30.5
LongBenchPro44.823.78.242.258.434.827.953.519.6
LongBench v243.730.324.933.247.336.032.042.730.4
Tool Use
τ³-Bench Banking †20.87.22.13.96.85.61.24.13.4
τ²-Bench Telecom97.190.469.0 †20.8 †92.1 †40.928.1 †20.8 †16.1 †
BFCL v466.661.143.636.656.852.243.747.049.2
Coding Agent
SWE-bench Verified46.46.05.02.033.636.83.015.00.4
SWE-bench Pro14.40.60.80.028.212.30.13.30.4
Terminal-Bench v2.1 †8.64.53.00.425.813.93.81.91.9
Search Agent
BrowseComp-ZH43.59.818.24.739.621.13.37.013.2
BrowseComp Top10039.713.719.36.033.319.04.76.39.7
GAIA Text-10388.749.547.930.178.657.326.539.541.1
General Agent
GDPval-AA v2 †19.64.50.00.011.70.0 †0.00.00.0
Claw-Gym59.219.325.531.351.660.033.737.92.7
WildClaw23.910.29.28.917.020.08.914.34.5
QwenClaw42.919.318.214.537.136.416.816.74.5
Average53.933.228.024.651.142.732.631.228.4

A pattern worth naming rather than skating past: MiniCPM5-2B doesn't win every row (Multi-IF, AIME 2025/2026, MMLU-Pro/Redux, MATH-500, several long-context and agentic rows go to a 4B-class model instead), but it wins the average, and wins it against models with meaningfully more parameters. On τ²-Bench Telecom and GAIA it leads the entire field, 2B-class or not. On AIME 2025/2026 it's within a point of the field-leading 4B model. That's a genuinely different shape than "small model wins on paper by cherry-picking benchmarks" — it's mid-pack-to-strong on most rows and exceptional on a handful, which is what actually moves an average that far above the next-best 2B model (33.2).

The training recipe: SFT, then RL teachers, then one distillation pass

Flowchart of MiniCPM5-2B's training pipeline: Pre-Training (Stable Training, Short Decay 4K, Long Decay 32K to 128K to 512K) produces MiniCPM5-2B-Base; SFT stage runs Mid-Training at 32K (600B tokens) then 128K (400B tokens) producing MiniCPM5-2B-Midtrain, then Deep Thinking SFT (400B tokens) producing MiniCPM5-2B-SFT; RL+OPD stage trains parallel Reasoning Task RL, General Task RL, and Agentic RL teacher models from the SFT checkpoint, then Online Policy Distillation (OPD) merges them back into MiniCPM5-2B, using the SFT model as both source and distillation student.
The full pipeline, as OpenBMB diagrams it (OpenBMB, MiniCPM5-2B model card).

Reading the diagram left to right: base pretraining runs stable training, a short 4K-context decay phase, then a long decay phase that extends context in stages up to 512K (a training-curriculum detail — the shipped model's documented, served context is 131,072, matching max_position_embeddings). Mid-training then runs two more context stages on top of that base — 600B tokens at 32K context, then 400B tokens at 128K context — before 400B tokens of "deep-thinking" SFT (released as UltraData-SFT-2605, with the agent-specific portion as UltraData-SFT-Agent-2609, ~500K samples).

From the SFT checkpoint, training branches into parallel RL teachers — reasoning, general-task, and agentic tracks, each producing multiple expert checkpoints (16 total, 5 of them agentic) — using UltraData-RL-2609 (80K+ samples spanning math, code, general knowledge, and long-context reasoning). The reasoning-RL reward design is explicitly credited to JustRL ("Scaling a 1.5B LLM with a Simple RL Recipe," arXiv:2512.16649) — a real, citable paper. A separate piece of the recipe, the critic-based algorithm used specifically for the RL+OPD stage, is credited to something called "JustRL II," linked not to arXiv but to a Notion writeup. That is the actual, verified link in the README — worth flagging because an arXiv id (2511.05963) has circulated attached to "JustRL II" in some launch commentary; that id resolves to an unrelated paper ("Next-Latent Prediction Transformers Learn Compact World Models"), not to this work. Cite the Notion page if you cite JustRL II at all, and treat it as an unreviewed writeup, not a paper.

Then On-Policy Distillation (OPD) merges those 16 expert models back into one release checkpoint: at each response position, it computes full-vocabulary reverse KL divergence between student and teacher logits as the advantage estimate — replacing the usual verification-based advantage — and reuses each teacher's own RL training prompts as distillation data, so no separate distillation corpus had to be built.

The README states the net effect in two numbers: RL + OPD improves reasoning/general benchmarks by an average of +10.96 points over the SFT-only checkpoint, and agentic benchmarks by +6.96 points. Here is the chart that number comes from:

Two horizontal bar-chart panels titled 'Score Gains from RL + OPD.' The top panel, Reasoning & General Capabilities, shows SFT-baseline bars in blue with a purple RL+OPD gain segment stacked on top, across Knowledge, Code, Instruction Following, Math Reasoning, and Long Context benchmarks — for example GPQA-Diamond rises from 48.59 to 70.2. The bottom panel, Agent Capabilities, shows the same treatment for Code Agent, Tool Use, Search Agent, and General Agent benchmarks — for example SWE-Bench-Verified rises from 29 to 46.4.
RL + OPD's own before/after chart, benchmark by benchmark (OpenBMB, MiniCPM5-2B model card).

Reading those gains benchmark-by-benchmark off that chart, rather than trusting the two averages alone — this is the same benchmark explorer from earlier, opened straight to its "what RL+OPD bought" tab:

the README’s own evaluation table, 34 benchmarks / 9 models
GPQA-Diamond+21.6
SuperGPQA+6.3
LiveCodeBench v6+10.5
LCB-Pro 25Q2 (Easy)+22.7
LCB-Pro 25Q2 (Medium)+12.3
OJBench+10.3
SciCode (wbg)+5.9
IFBench+15.7
IFEval+5.0
AIME 2025+20.0
AIME 2026+12.3
HMMT Feb 2026+11.8
AA-LCR+11.0
NoLiMa+8.9
LongBenchPro+6.8
LongBench v2+1.6
SWE-bench Verified+17.4
τ³-Bench Banking+8.2
τ²-Bench Telecom+4.1
BFCL v4+11.2
BrowseComp-ZH+6.9
BrowseComp Top100+1.3
GAIA Text-103+9.4
GDPval v2 (AA)+3.8
Claw-Gym+4.8
WildClaw+9.3
QwenClaw+2.9

Grey is the SFT-only checkpoint (before RL); green is what RL + OPD added on top. The README states this averages +10.96 points across reasoning/general benchmarks and +6.96 points across agentic ones — this chart is that same comparison, read off the card’s own figure row by row rather than taken only as an average. Two rows (HLE, Terminal-Bench v2.1) are left out here because their SFT-baseline bars were too thin on the source chart to transcribe a reliable number.

NoLiMa gains 8.9 points, GPQA-Diamond gains 21.6, SWE-bench Verified gains 17.4, and τ²-Bench Telecom — already near-saturated at 92.98 after SFT — gains a comparatively modest 4.1. The gains aren't uniform, which is what you'd expect from a distillation step reusing each teacher's own training distribution rather than a generic capability boost applied everywhere at once.

One name from the release announcements that this article is not going to assert as fact: a training framework sometimes called "Meshy," described elsewhere as a scalable RL training system behind this release. It does not appear anywhere in the model card, the GitHub repository, or public documentation as far as this research could find — searched by name, directly, with nothing returned. If it's real, it shipped without a citable reference this article could locate; the RL-stack claims above are limited to what the README itself names and links.

The open release

Alongside the weights, OpenBMB released the training data itself:

DatasetSizeRole
UltraData-Code~550B tokens (L2 algorithmic-selection ~400B + L3 task-synthesis ~150B, from an L0 base of ~192M GitHub repos)Tiered code data, L0–L3
UltraX-Preview~100B tokens, 113,789,578 rows, English-only, 487GBHigh-quality web pretraining corpus (5 sub-corpora, ~20B tokens each)
UltraData-SFT-Agent-2609~500K samplesAgent-specific SFT data
UltraData-RL-260980K+ samplesRL training data — math, code, general knowledge, long-context
Ultra-FineWeb~1T English + ~120B Chinese tokensCore web pretraining data — see this site's own measurement of what its filter costs and buys

DSpark: speculative decoding, and a speedup that doesn't decay smoothly

MiniCPM5-2B ships an open speculative-decoding draft, MiniCPM5-2B-DSpark. Per the community GGUF conversion of that draft, its GGUF architecture string is literally dflash — DSpark is built as DFlash plus a Markov head, which puts it in the same family this site covered in DFlash 2: the drafter already knew the answer, it just picked the wrong one, and adjacent to the confidence-scheduled verifier approach in DeepSeek's DSpark (a different, unrelated "DSpark" — DeepSeek and OpenBMB happened to land on the same name for different mechanisms). SGLang is the recommended serving path, with a purpose-built launch flag:

python -m sglang.launch_server \
  --model-path openbmb/MiniCPM5-2B \
  --trust-remote-code \
  --speculative-algorithm DSPARK \
  --speculative-draft-model-path openbmb/MiniCPM5-2B-DSpark \
  --speculative-dspark-block-size 7 \
  --port 30000

SGLang's own day-0 cookbook for this model publishes concrete single-GPU throughput numbers, reproduced in full below — worth being precise about what they do and don't establish, since a claim of "over 250 tok/s/user on coding tasks with DSpark enabled on a 5090" circulated around this release and this article could not confirm that specific framing against the cookbook page: the page's tables don't label whether DSpark was active for the runs, and don't mention a coding-specific workload — only a synthetic random benchmark (isl=1024, osl=1024).

SGLang day-0 cookbook throughput + FlagOS chip breadthrandom isl=1024/osl=1024, 1 GPU
32 GB, consumer desktop GPU
decode tok/s/GPU
496
time to first token
34 ms
time per output token
4.0 ms
FlagOS: adapted to 9 AI chip architectures, released on FlagRelease
NvidiaHygonMetaxIluvatarZhenwuMthreadsKunlunxinAscendARM-v9

The two measured points anchor opposite ends of “day-0 deployment”: a RTX 5090 desktop card single-streams 496 tok/s and holds 19,280 tok/s aggregate at 128-way concurrency, while a DGX Spark — built for unified-memory capacity over raw bandwidth — single-streams a much slower 72 tok/s but still clears nearly 2,900 tok/s aggregate once batched. Neither table says whether DSpark speculative decoding was switched on for these specific runs, so treat 496 tok/s as a same-day SGLang measurement, not confirmation of any particular DSpark-enabled number. The FlagOS row is a different kind of claim entirely — not speed, but breadth: the same weights, adapted and shipped across 9 unrelated chip architectures without a MiniCPM5-specific fork, which is what “standard LlamaForCausalLM” buys in practice.

HardwareWorkloadTTFTTPOTDecode tok/s/GPU
RTX 5090 (32GB)bs=1, single user34 ms4.0 ms496
RTX 5090 (32GB)concurrency=12834 ms11.8 ms19,280
DGX Spark (128GB unified)bs=1, single user85 ms27.7 ms72
DGX Spark (128GB unified)concurrency=641,373 ms42.9 ms2,892

Whatever the DSpark status of those specific runs, the community-built GGUF of the draft (aj9o9/MiniCPM5-2B-DSpark-GGUF) publishes a cleaner, fully-labeled comparison — same box, same target checkpoint, llama-benchy, decode-only, with and without the draft:

llama-server \
  --model MiniCPM5-2B-F16.gguf \
  -md MiniCPM5-2B-DSpark-F16.gguf \
  --spec-type draft-dspark \
  --spec-draft-n-max 7 \
  --host 127.0.0.1 --port 8080 \
  -ngl 999 -ngld 999 -fa on -np 1 -t 12 --jinja \
  -ctk q8_0 -ctv q8_0
aj9o9’s DSpark GGUF, tg256 on an RTX 3090 · Q8_0 KV
Decode throughput vs baseline at four prompt depths on an RTX 3090: 8k 109.5 to 181.8 tok/s (1.66x), 16k 90.6 to 134.5 (1.48x), 32k 70.2 to 85.0 (1.21x), 64k 46.2 to 70.0 (1.51x). The draft model's training range ends at 12,288 tokens, inside the 8k point and before every point after it.draft trained to 12,288 tok1.0×1.2×1.4×1.6×1.8×8k16k32k64k1.66×1.48×1.21×1.51×
baseline (no draft)+ DSpark, n-max 7
8k depth
1.66×
16k depth
1.48×
32k depth
1.21×
64k depth
1.51×

The speedup is not a flat multiplier and it does not decay smoothly: 1.66× at 8k (still inside the draft’s 12,288-token training range), falling to 1.48× at 16k and 1.21× at 32k once the draft is extrapolating — then climbing back to 1.51× at 64k in this specific run. The uploader flags exactly this himself: wall-clock speedup and accept length are “related but not the same number,” and while VRAM stays a predictable +1.8 GB for the draft (8.3 GB baseline to 10.1 GB with DSpark loaded), the official card’s accept-length figures — ~5.5 at T=0, ~4.1 at T=1.0 on in-distribution prompts — are reported to collapse toward ~1.6 once you push well past the training range. Treat the throughput curve above as one honest measurement on one box, not a guarantee that holds at every context length.

DepthBaseline tok/s+ DSpark tok/sSpeedup
8k (inside 12,288-token training range)109.54181.781.66×
16k90.62134.471.48×
32k70.1885.031.21×
64k46.2269.961.51×

VRAM cost is predictable and small — baseline 8,317MB, +1.8GB with the F16 draft loaded, 10.1GB total. The speedup is the interesting part precisely because it isn't a clean monotonic decay: strongest at 8k, inside the draft's 12,288-token training range, then weakening through 16k and 32k as the draft extrapolates past what it saw during training — and then recovering somewhat at 64k in this specific run. The uploader's own framing, worth repeating exactly: wall-clock speedup and accept length "are related but not the same number" — the official DSpark card's accept-length figures (~5.5 at T=0, ~4.1 at T=1.0 on in-distribution prompts) are reported to collapse toward ~1.6 well past the training range, which is a more pessimistic signal than the throughput curve above shows even at 64k. Both are real measurements; they're just measuring slightly different things, and only one number ships in most marketing.

For deeper context on why draft quality decays with distance from training data at all, and how other teams have addressed it, see this site's coverage of DFlash 2 and DSpark's speculative-decoding cousin over at LFM2.5 — the "does the speedup survive long context" question turns out to be a running theme across this entire family of drafters, not a MiniCPM5-specific quirk.

Deploying it: nine backends, nine chips, zero forks

Because MiniCPM5-2B is a stock LlamaForCausalLM, the GitHub repo ships cookbooks and matching Claude-Code/Cursor-style Agent Skills for every mainstream backend, with no custom kernel work required:

BackendFormat / use caseCookbook
TransformersBF16/FP16 local Python inference, GPU + CPUtransformers.md
vLLMBF16/FP16 OpenAI servervllm.md
SGLangBF16/FP16 OpenAI server, recommended for tool callingsglang.md
llama.cppGGUF local inference, CPU/GPUllama_cpp.md
OllamaGGUF local on-device runtimeollama.md
LM StudioGGUF Mac desktop app + OpenAI serverlmstudio.md
MLX4-bit local inference on Apple Siliconmlx.md
ArcLightGGUF local on-device, CPU, desktop & serverarclight.md
vLLM AscendBF16/FP16 OpenAI server on Huawei Ascend NPUvllm_ascend.md

The released GGUF sizes, for reference — these are the numbers the VRAM budget explorer above uses:

FileSizeUse case
MiniCPM5-2B-F16.gguf5.04GBreference quality, uniform CPU/GPU performance
MiniCPM5-2B-Q8_0.gguf2.68GBvery small quality drop vs. F16, half the disk
MiniCPM5-2B-Q4_K_M.gguf1.56GBedge/mobile-class hardware, minimal VRAM

Beyond the mainstream engines, OpenBMB partnered with the FlagOS Open Source Community to adapt the model across nine unrelated AI chip architectures via FlagRelease — Nvidia, Hygon, Metax, Iluvatar, Zhenwu, Mthreads, Kunlunxin, Ascend, and ARM-v9 — each getting its own published ModelScope/Hugging Face weights:

That ARM-v9 row is the one honest gap in this section worth naming directly: launch commentary around this release cited specific edge-hardware performance multipliers — Intel Core Ultra with OpenVINO, Arm Armv9 with SME2 giving roughly 1.7× prefill and 1.2× decode on mobile, and Rockchip RK3588/RK1828 numbers. This research checked the model card, the full GitHub repository (including every deployment doc and Agent Skill), and public search, and could not find those specific multipliers attached to MiniCPM5-2B anywhere verifiable. OpenVINO support for the MiniCPM5 family is real and documented by Intel — but for MiniCPM5-1B specifically in the material this research could locate, not confirmed for the 2B model at the cited multipliers. The FlagOS ARM-v9 row above is the verified edge-ARM claim this article can stand behind; the SME2 percentages are not repeated here because they couldn't be traced to a primary source.

Quickstart

# vLLM
pip install "vllm>=0.21"
vllm serve openbmb/MiniCPM5-2B --port 8000
# SGLang
pip install "sglang[srt]>=0.5.16"
python -m sglang.launch_server --model-path openbmb/MiniCPM5-2B --port 30000
# Transformers
from transformers import AutoModelForCausalLM, AutoTokenizer
 
model_id = "openbmb/MiniCPM5-2B"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype="auto", device_map="auto")
 
messages = [{"role": "user", "content": "Who are you? Please briefly introduce yourself."}]
inputs = tokenizer.apply_chat_template(
    messages, tokenize=True, add_generation_prompt=True,
    enable_thinking=True, return_dict=True, return_tensors="pt",
).to(model.device)
 
outputs = model.generate(**inputs, max_new_tokens=128)
print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:], skip_special_tokens=True))

Recommended sampling for the "Think" mode: temperature=1.0, top_p=0.95. Tool calling emits XML-style calls; SGLang's built-in minicpm5 parser converts them to OpenAI-compatible tool_calls natively — start the server with --tool-call-parser minicpm5 (or auto), then send a standard OpenAI-style tools=[...] request and it just works, no custom parsing required on the client side. For the engines this site has covered end to end, see SGLang: the tree, and the language nobody remembers and vLLM: what PagedAttention turned into — both apply directly here, since nothing about MiniCPM5-2B asks either engine to do anything model-specific.

Beyond the card: what Artificial Analysis independently measured

Everything above comes from the model card or a GitHub repo commit MiniCPM5-2B ships in. One more data point circulates around this release that deserves its own section precisely because it is not in the card: Artificial Analysis independently benchmarked the model and published its own Intelligence Index score, separate from anything OpenBMB self-reports.

Per Artificial Analysis's own published article on the release: MiniCPM5-2B scores 15 on their Intelligence Index — "the highest Intelligence Index of any open weights model under 4B total parameters," 4 points clear of Granite 4.2 3B (11), and 1 point ahead of Qwen3.5 4B (14, estimated) "with 44% fewer parameters." It sits "level with Qwen3.5 9B (Reasoning, 15, estimated) at roughly 4x its size" — level with, not above, which is a meaningfully more modest claim than "beats models 4x its size" and worth stating precisely rather than rounding up. On token efficiency: MiniCPM5-2B used 19k output tokens per Intelligence Index task (11k of them reasoning tokens), "joint-lowest in the comparison model set with Granite 4.2 3B (19k)" — tied for lowest, not uniquely lowest, and notably not the 21k-vs-19k framing that has circulated for this comparison; by Artificial Analysis's own published figure, MiniCPM5-2B and Granite 4.2 3B post the identical 19k token budget. On agentic evaluation specifically, GDPval-AA v2 Elo of 831 "leads <4B models," about 110 points ahead of Ling 3.0 Tiny (718) and about 180 ahead of Granite 4.2 8B (647). OpenBMB's own launch post on X separately states a score of 20 on an "Agentic Index" — that specific figure comes from OpenBMB's own announcement, not from Artificial Analysis's article, and this research could not retrieve the full post to check its surrounding context (it returned an access-restricted response rather than the page).

What this article can and can't stand behind

To close where it opened: there is no MiniCPM5 tech report, and everything specific to this model in this article traces back to a model card, a GitHub repo, or an independent third-party benchmark — never a peer-reviewed source. Reproduced and verified directly against a primary source: the config shape, the 2.52B parameter count, the KV-cache arithmetic (to the byte), the 34-benchmark average (recomputed, not just quoted), the RL+OPD gain figures, the DSpark GGUF throughput table, the SGLang single-GPU numbers, the FlagOS nine-chip list, and the UltraData/UltraX dataset sizes. Explicitly not verifiable from anything this research could locate: the "Meshy" training-framework name, the specific Arm SME2 / Intel OpenVINO / Rockchip RK3588+RK1828 performance multipliers, and the full text of OpenBMB's own Agentic Index claim. Both categories are listed here on purpose — a model card this detailed deserves to be read exactly as carefully as it was written.

@article{minicpm4,
  title={Minicpm4: Ultra-efficient llms on end devices},
  author={MiniCPM, Team},
  journal={arXiv preprint arXiv:2506.07900},
  year={2025}
}

That's the citation the MiniCPM5-2B README itself asks you to use — for MiniCPM4, still, in 2026.

Cite this article

For attribution, please use the following reference or BibTeX:

Satyajit Ghana, "MiniCPM5-2B: how 2 KV heads pay for a 131K window", ai.thesatyajit.com, September 2026.

bibtex
@misc{ghana2026minicpm52b,
  author = {Satyajit Ghana},
  title  = {MiniCPM5-2B: how 2 KV heads pay for a 131K window},
  url    = {https://ai.thesatyajit.com/articles/minicpm5-2b},
  year   = {2026}
}
share