Repository navigation
Picchio v0.8.0 - MiniMax-M2, a third model family
Picchio v0.8.0 adds MiniMax-M2 (230 B total, ~10 B active, 62 layers ×
256 experts) alongside GPT-OSS and Qwen3-MoE. At ~122 GB converted it is by far
the largest model the engine has run: it does not fit in RAM on any consumer
machine and streams from disk end to end, which is precisely the case Picchio was
built for.
Support is config-gated on model_type="minimax", like Qwen3 before it, so the
existing families are untouched - verified by the built-in self-test plus
end-to-end generation on all three.
Highlights
MiniMax-M2 support
Three architectural switches, each on only for MiniMax checkpoints:
- Partial RoPE - only the first
rotary_dim(64) channels of each 128-wide
head rotate; the rest pass through untouched. - Whole-vector QK-Norm - a single RMSNorm across the entire concatenated
multi-head Q (or K) vector, rather than per head as in Qwen3. - Sigmoid routing -
e_score_correction_biasselects the top-k experts, but
the mixing weight is the unbiased sigmoid score, renormalised over the
selection. The bias never reaches the weights. Applied in both top-k sites
(single-token decode and the batched prefill loop); the GPU router is bypassed
for this path, since its kernel assumes a pre-sigmoid linear bias.
Converter and chat bridge
convert_minimax.py: GPTQ-INT4 → Picchio INT4 gs64, with--dense-bits 8for
INT8 attention, atomic per-shard writes, and an optional--delete-sourcethat
frees each source shard as it is consumed (destructive; the original checkpoint
is gone afterwards).chat_minimax.py: MiniMax reasons unconditionally - its template's generation
prompt ends in a literal<think>, so replies begin inside a reasoning block
and there is noenable_thinkingswitch. The bridge splits the reply on the
</think>token, hides reasoning behind a progress spinner by default
(--show-thinkingstreams it), and records it through the template's own
reasoning_contentfield.
Engine fixes
ST_MAX_TENSORSraised from 32 768 to 131 072. That budget covers the whole
tensor database rather than a single shard; MiniMax's expert tensors alone are
~63 k, and the old ceiling stopped registering tensors mid-load without
reporting an error.cfg_rotary_dim()falls back tohead_dimwhenrotary_dimis unset, so
hand-built configurations (the synthetic self-test model, whoseCfgis
zero-initialised) keep full rotation instead of silently skipping RoPE
entirely - a defect the self-test could not have caught on its own, since both
forward paths would have skipped it identically.chat_qwen.pyrepaired fortransformers5.x, where
apply_chat_template(tokenize=True)returns aBatchEncodinginstead of a
list. The bridge was shipping the literal textinput_ids attention_maskas
token IDs, and the engine exited on it.
Measured performance
MiniMax-M2 on a 12-core AVX2 laptop, 32 GB RAM, model on an entry-level NVMe.
This is a different, larger machine than the 16 GB laptop used for the figures in
the README's main table, so these numbers are not comparable with those:
| Configuration | tok/s | Expert-cache hit |
|---|---|---|
--pin-gb 12 |
0.34 | 42.9% |
+ --async-moe --direct |
0.40 | 42.9% |
+ --pin-gb 20 |
0.48 | 54.6% |
The expert cache is the dominant lever: the experts total ~119 GB, so even 20 GB
holds only ~17% of them while every token touches 496 experts across 62 layers.
Raising --io-threads past the default made no difference - the NVMe is not
queue-depth limited. IDOT=1 gained ~5% but visibly changed the output, which is
expected of the approximate integer kernel and not a good trade. Unlike the other
families, repeat runs do not speed up: the learned hot-store converges
immediately and the resident expert set stops changing.
For scale, gpt-oss-120b reaches ~2 tok/s on this same machine, because it
streams roughly 4× less expert data per token.
Upgrade notes
- No action required for existing GPT-OSS or Qwen3 models: converted checkpoints,
flat stores, and command lines are unchanged. - The startup banner now reads
GPT-OSS/Qwen3-MoE/MiniMax-M2. - Anyone running the chat bridges on
transformers5.x should take this release:
chat_qwen.pywas broken there before it. - Model weights are not included. Users must obtain and convert checkpoints in
accordance with their original licenses.
Validation performed for this release
- Clean Windows x64 AVX2/FMA build.
- Built-in forward and math self-tests, including the RoPE, INT3/INT4 matmul, and
pipeline byte-identity checks. - End-to-end generation regression on all three families after the shared-code
changes: GPT-OSS-120B (INT3 + INT8 attention), Qwen3-30B-A3B (INT4 + INT8
attention) and MiniMax-M2 each answered a factual prompt correctly. minimax_forward_check.cmatches the real upstreamMiniMaxM2ForCausalLMto
max|Δlogit| = 1e-6on the committed fixture (verify_minimax.py).- The MiniMax architecture was additionally cross-checked line by line against
llama.cpp's ownminimax-m2.cpp, which agrees on all three switches. - The converted 230 B checkpoint loads all 64 349 tensors and generates coherent
text. - Python syntax validation and import/CLI smoke tests across the project's entry
points.
Known limitations
- MiniMax-M2 is I/O-bound on consumer hardware; expect well under 1 tok/s unless
a large fraction of the experts fits in the cache. convert_minimax.pyemits INT4 experts only. The engine already supports INT3
(picchio_expert_bits: 3), which would cut expert bytes ~22%, but the
converter does not offer it yet.- No full-model numeric oracle comparison against
transformersfor MiniMax-M2.
This is blocked on the library itself: its in-tree MiniMax-M2 support drops the
checkpoints'rotary_dimand applies full-head RoPE
(huggingface/transformers#48241),
so it is not a trustworthy reference for this architecture today. For the same
reason the validation fixture is committed rather than regenerated, and
make_minimax_test_model.pyrefuses to run ontransformers >= 5.0instead of
emitting a silently wrong oracle. - Carried over from 0.7.0: speculative decoding remains scaffolding and is off by
default; GPU paths remain experimental and do not beat the CPU path on small
(4 GB) cards; the server uses one model process and one KV cache, so requests
are serialized.
Third-party code
reference/minimax_m2/ vendors the upstream MiniMax-M2 modeling code
(Apache-2.0, © 2024-2025 ModelCloud.ai) byte-identical and unmodified, used
only to build the validation fixture. It is never compiled into the engine. See
reference/README.md for attribution.
Downloads
picchio.exe: self-contained Windows x64 CPU build. Requires AVX2/FMA. The
binary identifies itself as v0.8.0 at startup and is unsigned, so Windows
SmartScreen may display a warning.SHA256SUMS.txt: checksum for the downloadable binary.- GitHub-generated source archives: build with
build.baton Windows ormake
on supported Unix-like systems.
Binary SHA-256:
72767a6d140d111ef97bad42c36a5891e3a89552ca0129614183129c465d4a28 picchio.exe
Full change history
Compare: v0.7.0...v0.8.0