Repository navigation
feat(gguf): serve image input on minimax-m3 ggufs from a minimax_m3 mmproj - #829
Merged
Merged
Conversation
This was referenced Oct 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #671 (the MiniMax-M3 item in #794). Serves the MiniMax-M3 vision tower from a llama.cpp
minimax_m3mmproj on the #803 base. MiniMax-M3.1-Flash GGUFs share the arch and projector and load through the same code.What it does
gguf_mm_configderives the tower config from the mmproj metadata and tensor shapes;image_token_idis]<]image[>[in the text GGUF's tokenizer. Rope theta 10000 (llama.cpp hardcodes it too), min / max pixels 3136 / 451584 (whatMiniMaxM3VLImageProcessoruses in place of the stale[672, 672]in the HFpreprocessor_config.json), gelu and temporal patch 2 are family constants equal to the HF release.iter_mmproj_weightsstacks the Conv3d patch embedding's two temporal halves back and undoes the converter's per-head q / k row order ([t t | h h | w w | pad]back to HF's[t h w | t h w | pad], head_dim 80); the rest is HF layout.encoders/mm_processorand switches to the ConditionalGeneration class.IMAGE_START_ID/IMAGE_END_IDmove from the processor tominimax_m3/config.py, which both the processor andgguf.pyimport (the DeepSeek-V4 processor reads its image id the same way).--mmproj, a logged skip under auto-discovery): another projector, an output width other than the text model's, no]<]image[>[token,]<]start of image[>[/]<]end of image[>[not at the ids the processor uses (200029 / 200030), and a tensor set other than the one llama.cpp loads (Serpen'smm.merge.*files, which llama.cpp cannot load either).Tower parity
Image processor vs
AutoImageProcessor: pixels and grids identical on 20 images, also under--image-min-tokens/--image-max-tokens. Image token ids and the chat template's image rendering equal HF.tok_comparevs the HF tokenizer: 0/198,941 vocab, 0/20,000 combos, 1/13 edge cases (a combining accent: HF has an NFC normalizer; same on main).Check sweep
scripts/gguf_checkon header stubs of every MiniMax-M3 / M3.1-Flash GGUF repo on HF (230 files, 34 repos) plus their 26 mmproj files, kernels.json probed on the GPU. 83/204 files of the served arch pass, the same files as on main 0bf7dbb (0 of 230 differ on the text side). With each repo's mmproj set byFREETOKEN_MMPROJ, the tower checks on 87 files with 0 vision-side problems; 23/26 mmproj files load (the other 3 below). Text-side failures are the same as main: unknown ggml types, pre-indexer conversions, quantized indexer projections, per-tensor.scale, IQ1_M.Serving
RTX PRO 6000 Blackwell Server Edition (96 GB), driver 595.91.07, Xeon Platinum 8559C, 249 GB RAM, torch 2.14.1+cu130, transformers 5.18.0.
bartowski
MiniMax-M3-IQ2_XXS(116.6 GB), 15 probes (OCR, shapes, two images, wide / tiny / tall images, a repeat). No HF checkpoint fits this box, so the reference is the prompt length from the HF tokenizer, chat template andMiniMaxM3VLProcessor.--mmproj--mmprojThe 2400x240 and 300x1500 squashes are misread at IQ2_XXS.
--mm-disable visionand a folder without an mmproj serve text and reject images with a 400.Not covered
minimax_m3_vl), Serpen's (mm.merge.*)--mmproj, skipped by discovery--mmprojor the model folder, as in llama.cpp; M3.1-Flash ships its own tower, so pair each release with its own mmproj--mmprojpicks the fileNo per-family GGUF test file, per the #721 review direction.
pytest tests/models tests/mm tests/tokenizer tests/server: 1153 passed, 7 failed, the same 7 as on main 0bf7dbb (test_quant_config.pycases that read the local HF cache).