This page summarizes model-family support in the v0.0.27 source tree. The runtime source of truth is the code, not this prose page:
- detection:
src/models/detection.rs ModelTypeenum and module exports:src/models/mod.rs- loading policy:
src/model_metadata.rs - VLM loading routes:
src/loading/vlm*.rs
ModelType spans text and non-VLM language models, VLM variants, a
speech-to-text encoder-decoder (Whisper), and a text-to-speech model (Kokoro).
These are architecture/runtime variants, not a guarantee that every checkpoint
under a marketing family name is supported.
Implemented model families include:
- Llama-family and Mistral-style dense decoders
- Llama 4 text
- Qwen 2 / 2.5 / 3 / 3.5, Qwen MoE, Qwen3 Next
- Gemma 1 / 2 / 3 / 3n / 4 text variants
- Phi, Phi-3, Phi-3 Small, PhiMoE
- Mixtral and other MoE families
- DeepSeek v1 / v2 / v3 / v3.2
- dots.llm1 (
dots1, rednote: a DeepSeek-V3-style Mixture-of-Experts without MLA. Standard multi-head attention with per-head Q/K RMSNorm, a dense first layer (first_k_dense_replace), then sigmoid-routed experts that select ongate.weightlogits plus ane_score_correction_bias, with a single always-on shared expert. Validated againstmlx-community/dots.llm1.inst-mixed-4-6bit, a mixed 4/6-bit export whosev_projanddown_projtensors are 6-bit while the rest are 4-bit; the unified loaders detect the per-tensor bit width from shape.) - Mistral 4 (
mistral4, Mistral Small 4: a DeepSeek-V3-style Multi-Latent Attention decoder with compressed query and KV LoRA projections (q_lora_rank1024,kv_lora_rank256), split rope/nope query-key head dims, and a separate value head dim, paired with a softmax-routed Mixture-of-Experts (128 routed experts plus one always-on shared expert, 4 active per token,norm_topk_prob) and Llama-4 position-dependent attention scaling. The only public checkpoint is the Mistral Small 4 119B vision model, whosetext_config.model_typeismistral4; mlxcel detects it as a Mistral 3 VLM (Pixtral vision tower) on the Mistral4 text backbone. Validated againstmlx-community/Mistral-Small-4-119B-2603-4bitfor both text and image-plus-text.) - Cohere / Cohere2
- Command MoE (
cohere2_moe, Cohere: the Cohere2 parallel-residual backbone (interleaved sliding/global attention, conditional RoPE, logit scaling, tied embeddings) with the dense FFN replaced by a sparse Mixture-of-Experts. The router scores onmlp.gatelogits activated in f32 by sigmoid (default) or softmax, takes the top-k, and gathers the activated values at the selected experts (not a fresh softmax over the k logits), with optionalnorm_topk_probrenormalization clamped by1e-12. Always-on shared experts (moe_num_shared_experts) run a dense SwiGLU on the same input and combine by average (default(y + y_s) / 2) or sum. An optional dense-FFN prefix (first_k_dense_replace, widthprefix_dense_intermediate_size) and an optional RMSNorm mode (rms_norm_eps, else LayerNorm) round out the deltas versus densecohere2. The full runtime (detection, metadata, loaded-model dispatch, CLI and server generation) is wired; real-checkpoint validation is pending a publiccohere2_moecheckpoint.) - MiniMax-M3 (
minimax_m3, MiniMax: a hybrid dense/MoE decoder that follows MiniMax-M2 (minimax) but swaps in Gemma-style RMSNorm (weight+1) everywhere including per-head Q/K norm, clamp-SwiGLU (swigluoai) experts and dense MLPs, partial RoPE (rotary_dimofhead_dim), and a sigmoid router with a selection-only routing bias plus one shared expert. The per-layer plan comes frommoe_layer_freq(leading dense layers, then MoE); routed experts load the Mixtral-styleblock_sparse_moe.experts.{i}.w1/w3/w2checkpoint naming (auto-falling back togate_proj/up_proj/down_proj), and the shared expert is always a separateblock_sparse_moe.shared_expertsMLP added to the routed mixture at a fixed weight of 1.0, never packed into the switch tensors. The sparse layers (sparse_attention_config.sparse_attention_freq) add a block-sparse "MSA" indexer with an MQA-style index: per-headindex_q_projquery heads score against a single sharedindex_k_projkey head, each normed (Gemma norm) and RoPE'd, top-sparse_topk_blocksselection oversparse_block_sizekey blocks scored by their max token score, expanded to an additive block mask on top of the causal mask, with the shared index key cached alongside the regular K (requiressparse_index_dim == head_dim, else the indexer falls back to dense). When the selected window still covers at least half the live cache, attention stays dense; whensparse_topk_blockscovers every block, the block mask is all zeros and attention is bit-identical to dense; a zerosparse_block_sizeorsparse_topk_blocksis rejected at load time instead of dividing by zero or mis-indexing the block partition. Only the text decoder is implemented; the VL wrapper and MTP head are out of scope (MTP tensors are skipped on load). The only public checkpoint is the 427BMiniMaxAI/MiniMax-M3VL repo, which exceeds the development machine's memory, so validation is synthetic reduced-config unit tests plus a real-text_configparse test; real-checkpoint load/generate carries over to a follow-up runtime validation.) - InternLM 2 / 3
- GLM 4, GLM MoE, GLM MoE DSA
- ERNIE 4.5 and ERNIE 4.5 MoE
- Hunyuan dense and MoE variants
- IBM Granite dense (
granite) - IBM Granite 4.x hybrid (
granitemoehybrid: interleaves Mamba2 SSM and GQA attention layers bylayer_types, applies the four Granite scalar multipliers (embedding, attention, residual, logits), and defaults to NoPE attention. The dense-MLP mode is validated againstmlx-community/granite-4.0-h-350m-4bit; the MoE mode (block_sparse_moe+shared_mlp) is implemented but awaits a public MLX checkpoint to validate. The non-hybridgranitemoevariant is not yet ported.) - BitNet b1.58 (
bitnet, Microsoft: a Llama-style transformer whose every projection is aBitLinearwith 1.58-bit ternary weights ({-1, 0, +1}) packed 4-per-uint8 and scaled by a single per-tensorweight_scale. A custom Metal kernel (bitlinear_matmul) multiplies directly on the packed bytes, so the unpacked weights never materialize. Two extra sub-norms (attn_sub_normbeforeo_proj,ffn_sub_norminside the MLP) and a squared-ReLU MLP (relu2(gate) * up). Runs in native bf16 (its squared-ReLU overflows f16), bypassing the Apple-Silicon f16 conversion. Validated againstmlx-community/bitnet-b1.58-2B-4Tand its-4bitvariant, which additionally affine-quantizes the embedding/lm_head to 4-bit (the BitLinear weights stay ternary); keeping the whole model bf16 also keeps that 4-bit dequant dtype-consistent.) - ExaOne / ExaOne 4 / ExaOne MoE / Solar Open
- OLMo / OLMo2 / OLMo3 / OLMoE
- StarCoder2, StableLM, SmolLM3, Baichuan, MiniCPM, MiniCPM3, MiniMax, Ministral3, Nemotron, Nemotron-NAS, Step 3.5, MiMo
- Mellum / Mellum 2 (
mellum, JetBrains code model: sliding/full hybrid attention driven bylayer_types, with QK-RMSNorm and a sparse softmax-routed MoE (norm_topk_prob) in every layer. Full-attention layers use YaRN-scaled RoPE plus a standardKVCache; sliding-attention layers use default RoPE plus aRotatingKVCachewindowed tosliding_window. Supports tied and untied LM heads. Validated againstJetBrains/Mellum2-12B-A2.5B-Base.) - Apertus (
apertus, Swiss AI: Llama-style dense transformer with an xIELU activation MLP (no gate), QK-norm, llama3 RoPE scaling, and untied embeddings) - Seed-OSS (
seed_oss, ByteDance: plain Llama-style dense transformer with a standard SwiGLU MLP and standard residuals. The only deltas are a split attention bias (attention_biason q/k/v,attention_out_biason o_proj), an explicithead_dim, untied embeddings, and a{"rope_type": "default"}rope_scaling that applies no scaling. Validated againstmlx-community/Seed-OSS-36B-Instruct-4bit.) - Mamba, Mamba2, RWKV7, Recurrent Gemma, Jamba, Nemotron-H
- Falcon-H1 (TII: runs a Mamba2 SSM mixer and GQA attention in parallel within each block, summing both outputs; the MUP channel multipliers are pre-folded into the MLX weights)
- LFM2 and LFM2-MoE (Liquid Foundation Models: short-convolution and attention hybrid; the MoE variant routes through sigmoid-gated experts)
- LFM2-VL (
lfm2_vl/lfm2-vl): a SigLIP2-style packed-patch vision tower (native variable resolution, per-image bicubically-resampled position grid) + a pixel-unshuffle (space-to-depth) projector into the LFM2 hybrid text backbone. Each image is smart-resized so its post-downsample token count lands in[min_image_tokens, max_image_tokens], packed at its native patch count (no padding), and itsceil(h/f)*ceil(w/f)projected tokens replace the<image>placeholder. The multi-tiledo_image_splittinghigh-resolution path is a documented follow-up. - PLaMo 2 (Preferred Networks: interleaves Mamba SSM and GQA attention layers by index; each block carries normformer-style pre/post offset RMSNorms, and the Mamba mixer derives B/C/dt from a post-conv projection). The architecture is validated against the mlx-lm reference at the token-id level (
tests/plamo2_parity.rs). CLI text generation additionally needs support for PLaMo's customPlamoTokenizer(thetokenizer.jsonlUnigram format), which the Rust tokenizer loader does not yet read. - Kimi Linear, LongCat Flash, LongCat Flash N-gram
- GPT-OSS
Many of these families have checkpoint-specific config or weight-layout
requirements. If a checkpoint fails detection or loading, inspect its
config.json::model_type first and compare it with src/models/detection.rs.
| Family | model_type key |
Notes |
|---|---|---|
| DiffusionGemma | diffusion_gemma / diffusion_gemma_text |
Block-diffusion on a Gemma 4 MoE backbone. Generates a canvas of tokens per block through iterative denoising rather than token-by-token left-to-right decoding. CLI (mlxcel generate) supports text and image input (--image <path>, repeatable). Served in mlxcel-server (serial, batch-1 by design) via /v1/chat/completions and /v1/completions; image input follows the standard image_url content part format. See Block-diffusion generation. |
| LLaDA-2 MoE | llada2_moe |
Masked-diffusion LM with a DeepSeek-V3-style MoE FFN (sigmoid-routed grouped experts on gate.weight + expert_bias, one always-on shared expert, first_k_dense_replace dense layers). Decoder-only transformer with fully bidirectional attention (no causal mask), fused QKV projection, per-head QK-norm, and partial RoPE. Generates by semi-autoregressive block-wise unmasking of `< |
DiffusionGemma uses a two-phase forward pass: an encoder prefill that caches the
prompt into dense FP16 KV caches, then a canvas loop that attends bidirectionally
within each output block while attending causally to the cached prefix.
Load detection accepts model_type: "diffusion_gemma" (outer config) and
model_type: "diffusion_gemma_text" (inner text_config).
The fused MoE gate_up_proj weights are split at load time. When a vision tower is present in the checkpoint, its weights are loaded and wired for image input; checkpoints without vision weights fall back to text-only mode without error.
Implemented VLM variants include:
- Gemma 3 VL, Gemma 3n VL, Gemma 4 VL
- Gemma 4 Unified (
gemma4_unified): encoder-free text + image + audio + video. Patch-projection vision embedder and waveform-chunk audio path feed the shared Gemma 4 backbone, with blockwise bidirectional attention over image/video token spans during prefill. Video is handled as images-per-frame: frames are extracted withffmpeg(uniform sampling, default 2.0 fps), patchified through the same vision embedder with a per-framevision_soft_tokens_per_video_framebudget (70), and scattered intovideo_token_idplaceholder spans. Video is available on both the CLI (--video) and the server (video_urlcontent blocks). The prompt grows by ~70 soft tokens per sampled frame, so a multi-second clip at the default fps expands past the model's 1024-token sliding window. That over-window single-pass prefill is handled correctly: the windowed prefill mask spans the full prompt (the rotating cache keeps every prefill key and only trims to the window for the decode step), so long clips decode coherently without lowering--fps. - Gemma 4 VL audio: the Gemma 4 VL checkpoints that ship a Conformer audio tower (for example the
e2b/e4binstruct models) take spoken audio from the CLI with--audio <path>and transcribe or answer questions about it. Input audio is resampled to 16 kHz before the Conformer encoder, so a clip at any source rate produces the encoder frame count the duration-based audio-token budget expects. Server-sideinput_audioinPOST /v1/chat/completionsis also supported: the audio block is spliced inside the last user turn, before the<turn|>end-of-turn marker that Gemma 4 uses (id 106). - Llama 4 VLM
- Llama 3.2 Vision (
mllama): a Llama-3 text backbone whose layers atcross_attention_layers(e.g.[3, 8, 13, 18, 23, 28, 33, 38]) are gated cross-attention adapters attending to a tiled ViT tower. The image processor picks an optimal tile arrangement (up tomax_num_tiles, default 4) from the supported aspect ratios, resizes and pads each image into560x560tiles, and emits aspect-ratio ids/masks. The tower adds gated tile + position embeddings, runs a local then a global (gated) transformer, and concatenates a set of intermediate hidden states; amulti_modal_projectormaps thosevision_output_dimfeatures into the text hidden size. Unlike the LLaVA-style VLMs, image features are not merged into the token stream: they are held ascross_attention_statesand consulted through the gated cross-attention layers (with per-headq_norm/k_norm). Text-only prompts leave the cross-attention layers as pass-throughs. - LLaVA and LLaVA-Bunny
- Aya Vision and PaliGemma
- Pixtral and Mistral 3 VLM wrappers (Mistral 3 VLM supports both the standard Llama/Mistral text backbone and the Mistral4 MLA+MoE backbone; text and image-plus-text are validated on both, including the Mistral Small 4 119B checkpoint). Images keep their aspect ratio: each is downscaled so its longest side fits
size.longest_edgeand rounded up to a whole number of merged patches (patch_size * spatial_merge_size, so Pixtral rounds to 16 and Mistral 3 to 28), never upscaled. The[IMG]placeholder then expands to one patch token per merged cell laid out row by row, with[IMG_BREAK]between rows and[IMG_END]after the last, so non-square inputs keep the spatial structure the models were trained on. The encoder builds its 2D-RoPE grid per image from the actual patch shape, and multi-image batches with differing sizes run the tower once per image. - Qwen2-VL, Qwen2.5-VL, Qwen3-VL, Qwen3.5-VL, and Qwen3-VL MoE
- PaddleOCR-VL (
paddleocr_vl): document-OCR VLM pairing a NaViT dynamic-resolution SigLIP-style vision encoder (Conv2d patch embedding, cached bilinearly interpolated learned position embeddings for repeated page grids, 2D vision RoPE,cu_seqlens-packed attention with uniform and length-bucketed batched fast paths, and a spatial-merge projector) with a lightweight ERNIE-4.5 text decoder that uses MRoPE. Best for plain OCR, tables, formulas, and chart understanding. - Step-3.7 (
step3p7): StepFun's multimodal model. A 47-blockperception_encoderViT tower (Conv2d patchify, learned absolute position embeddings bilinearly resized for the patch grid, 2D vision RoPE, LayerScale, quick-GELU MLP) feeds two stride-2 conv downsamplers and a linear projector into the text hidden size. Each image runs a base pass (728 px, 52x52 grid collapsed to 169 tokens) and, when larger than 728 px, a tiled-patch pass (504 px windows, each 36x36 grid collapsed to 81 tokens); features are ordered patches-first then base per image and scattered into<im_patch>placeholders. The text decoder is the Step-3.5 MoE stack (text_config.model_type: step3p5), reused as the backbone. Text-only prompts work through the same checkpoint. - dots.ocr (
dots_ocr): document-OCR VLM (rednote-hilab) pairing a 42-blockdots_vitdynamic-resolution ViT with a Qwen2 text decoder. The tower shares the Qwen2-VL vision machinery (cu_seqlens-packed block-diagonal attention, 2D vision RoPE, merge-block patch ordering) but uses RMSNorm blocks, a SwiGLU vision MLP, a patch embed with bias and a trailing RMSNorm, and apost_trunk_norm; its merger projects each 2x2 patch block straight to the text width (no separate connector). Plain 1D RoPE text decode, no MRoPE. Best for layout analysis (bbox + category JSON), plain OCR, tables, formulas, and Markdown conversion. - GLM-4V (
glm4v): GLM-4V ViT vision tower (3D patch embedding, bilinear-resampled learned position embeddings, Conv2d spatial downsample, SwiGLU patch merger) plus a GLM-4 text backbone driven by sectioned even/odd MRoPE. Reuses the shared Qwen-VL image processor and prompt/token plumbing. - GLM-4V MoE (
glm4v_moe): GLM-4.5V-class variant reusing the GLM-4V ViT vision tower with a GLM-4 MoE text backbone (groupednoaux_tcrouting, shared experts,first_k_dense_replacedense layers) driven by sectioned half-split MRoPE. Reuses the GLM-4 MoE machinery and the shared Qwen-VL runtime. - Granite Vision (
granite_vision, orllava_nextwith agranitetext config): IBM's document VLM. A SigLIP vision tower with four intermediate feature taps (concatenated on the channel axis) feeds a 2-layer GELU projector; a learnedimage_newlineembedding, LLaVA-Next AnyRes multi-tile preprocessing (image_grid_pinpoints), and a dense Granite text backbone (embedding / attention / residual / logits multipliers) complete the model. Bothconfig.jsonspellings route to the same loader. Best for document understanding, charts, and tables. - Granite 4 Vision (
granite4_vision): IBM's document VLM with multi-depth visual injection. A SigLIP tower feeds eight window-QFormer projectors (a QFormer with self+cross attention per4x4/8x8window, with deepstack mean-pool and spatial strided-offset query downsamplers) whose packed outputs are added into the residual stream at eight different depths of a Granite 4 hybrid (granitemoehybrid) text backbone during prefill, rather than merged once. Reuses the shared AnyRes tiling and the four Granite scalar multipliers. Best for document understanding. - DeepSeek-OCR (
deepseekocr): DeepSeek's document-OCR VLM. Each view runs a SAM-style ViT-B (windowed / global attention with a decomposed relative-position bias, a two-conv neck, and a two-stage stride-2 conv compressor) and a CLIP-style ViT-L that ingests the SAM grid as its patch embeddings; the two token sets are concatenated on the channel axis, projected to the decoder width, and laid out as a 2D tile mosaic with learnedimage_newlinecolumns and a trailingview_separator. A small DeepSeek MoE decoder (12 layers, 64 routed + 2 shared experts, standard attention, reusingdeepseek) reads the mosaic. The processor pads a global 1024 view and, for larger images, adds a closest-aspect-ratio grid of 640 tiles. Best for plain text, markdown, HTML tables, and grounding boxes. - DeepSeek-OCR 2 (
deepseekocr_2): the second-generation document-OCR VLM. It keeps DeepSeek-OCR's SAM-style ViT-B (with the compressor emitting 896 channels) but replaces the CLIP stage with a Qwen2-0.5B-shaped query resampler: the SAM grid is concatenated with a learnable query bank and run through 24 GQA + rotary + SwiGLU layers under a mixed mask (image tokens bidirectional among themselves, queries causal and attending to all image tokens); only the query outputs are projected to the decoder width. There is no channel-concat fusion and noimage_newlinemosaic, so features are flat runs assembled per image as[tiles, global, view_separator]. The processor tiles every image with 768 tiles (closest-aspect-ratio grid of 1..6) plus the padded global 1024 view. The same DeepSeek MoE decoder reads the features. Best for plain text, markdown, HTML tables, and grounding boxes. - Unlimited-OCR (
unlimited-ocr): baidu's document-OCR VLM (baidu/Unlimited-OCR), built on the DeepSeek-OCR stack. The SAM ViT-B + CLIP-L/14-224 encoders, the linear projector, theimage_newline/view_separatormosaic, and the 12-layer DeepSeek MoE decoder (64 routed + 2 shared experts) are the same as DeepSeek-OCR, so the whole vision path and processor are reused. The one new piece is the decode cache: attention runs against a per-layer ring sliding KV cache that keeps the full prefill KV (prompt + image tokens) permanently and rotates only the most recentsliding_window_size(128) decode tokens, with absolute RoPE positions that keep increasing past the window. A single literal<image>covers all pages of a multi-page input. Best for long-document OCR where decode runs well past the window without unbounded KV growth. - DeepSeek-VL2 (
deepseek_vl_v2): DeepSeek's general vision-language model. Each view runs a SigLIP-style ViT (no CLS token, apatch_sizeConv2d patch embed folded into a linear, a learned absolute position embedding, fused-qkv full attention, GELU-tanh MLP, and a trailing LayerNorm); thedownsample_mlp_geluprojector folds each 2x2 patch block into one channel-outermost feature vector and maps it to the decoder width with a two-layer GELU MLP. Features are laid out as a 2D tile mosaic with learnedimage_newlinecolumns and aview_separator, ordered[global, view_separator, local]. A DeepSeek-V2 MoE decoder (MLA attention, softmax-gated routed experts plus shared experts, reusingdeepseek_v2) reads the mosaic. The processor pads a global view and, for at most two images, adds a best-fit grid of local tiles chosen fromcandidate_resolutions; three or more images use a single tile each. Best for image description, grounding, and document understanding. - ERNIE-4.5 MoE VL (
ernie4_5_moe_vl): Baidu's vision-language MoE. A DFNRope ViT (linear patch embedding over 588-wide merge-window rows, 2D vision RoPE,cu_seqlens-packed attention, quick_gelu MLP) feeds a variable-resolution resampler (2x2 spatial fold, temporal pair fold with single-frame duplication, GELU MLP stacks, RMSNorm) whose rows replace the<|IMAGE_PLACEHOLDER|>tokens. The text decoder extends ERNIE-4.5 MoE with modality-split expert banks: separate text and multimodal routers and expert stacks selected per token by token type, with a correction bias that shifts expert selection but never the mixing weights, plus a fused shared-experts MLP. Position encoding is interleaved 3D MRoPE ([T, H, W]axes assigned per frequency index, adjacent-pair rotation) that degenerates to traditional RoPE for text. Validated againstmlx-community/ERNIE-4.5-VL-28B-A3B-Thinking-4bit(28B-A3B; text and resampler 4-bit, vision tower bf16). Best for general image chat and grounded reasoning; the checkpoint is a thinking variant and emits reasoning before the answer. - Qwen3-Omni MoE (
qwen3_omni_moe, thinker): Alibaba's omni-modal MoE. Stage 1 covers the thinker: text output conditioned on text, image, and audio inputs. The vision tower and MoE text decoder are the Qwen3-VL-MoE stack (DeepStack feature injection, interleaved MRoPE) reused unchanged; the new audio tower converts 16 kHz audio to a 128-bin log-mel spectrogram, downsamples it through three stride-2 convolutions (13 output frames per second of audio), and runs 32 windowed-attention encoder layers whose output rows scatter into the token stream exactly like image features. Audio arrives via--audio file.wavon the CLI (combinable with--image). Stage 2 adds speech output:mlxcel generate --output-audio out.wavruns the talker and code2wav after text generation and writes 24 kHz mono PCM16. The talker is a 20-layer Qwen3-MoE codec decoder conditioned on the projected thinker token embeddings of the chat-role segments; per frame it emits the first of 16 codebooks and a 5-layer code predictor fills in the residual 15, then the code2wav vocoder (causal pre-transformer, ConvNeXt upsampling, BigVGAN-style SnakeBeta decoder) renders 1920 samples per 12.5 Hz frame.--speakerselects the voice (ethan default; chelsie and aiden also ship in the released checkpoints). The speech stack loads lazily and only when requested, so text/vision use keeps its memory footprint; speech currently requires a text-only, chat-templated prompt. Validated againstmlx-community/Qwen3-Omni-30B-A3B-Instruct-4bit(text and talker 4-bit; vision, audio tower, code predictor, and code2wav bf16). - Hunyuan-VL (
hunyuan_vl, e.g. HunyuanOCR): Tencent's vision-language family. A ViT with a per-patch conv embedding, bilinearly interpolated learned position embeddings, and full attention over the packed patch sequence feeds aperceivemerger: a stride-2 conv pair over the raster grid, a learnedimage_newlinecolumn, a linear to the decoder width, and learnedimage_begin/image_endrows. Per image that yieldsmh * (mw + 1) + 2feature rows, matching the prompt placeholder count exactly. The decoder is the Hunyuan dense stack (per-head Q/K RMSNorm after the rotation, DynamicNTK-alpha rope base) with XD-RoPE at prefill: 4D[P, T, H, W]position ids split across the frequency dims, degenerating to the standard rotation for text; decode uses sequential positions. Validated againsthadeseus/HunyuanOCR-mlx-4bit(text 4-bit, vision bf16). Best for OCR: text spotting, document parsing, and grounded extraction. - MiniMax-M3-VL (
minimax_m3_vl): MiniMax's vision-language model on top of the MiniMax-M3 text backbone. A CLIP-style ViT (hidden 1280, 16 heads, 32 layers, patch 14,pre_layrnorm, LayerNorm + exact-GELU blocks with separateq/k/v/outprojections) runs native-resolution packing: Qwen2-VL-style dynamicsmart_resizetopatch_size * spatial_merge_size = 28-aligned dimensions,image_grid_thwpatchify, per-imagecu_seqlensvariable-length attention, and 3D (t, h, w) vision RoPE (temporal axis inert for images, trailing dims unrotated). A two-stage projector then maps features to the text width: a per-patchmulti_modal_projector(linear_1 -> GELU -> linear_2, intoprojection_dim6144) followed by apatch_merge_mlpthat folds eachspatial_merge_size^2 = 4adjacent patches (linear_1[6144, 24576]-> GELU -> linear_2). Each]<]image[>[placeholder expands togrid_t * (h/2) * (w/2)tokens (vision_start200029,vision_end200030), which the merged features replace LLaVA-style; the MiniMax-M3 hybrid dense/MoE decoder then runs its standard partial 1D RoPE. The vision tower runs in f32 (non-quantized in the checkpoint) while the text tower may be quantized in community exports. Image and multi-image inputs are wired end to end (CLI and server); video is out of scope for this port. The only public checkpoint (MiniMaxAI/MiniMax-M3, 427B) exceeds the development machine, so image Q&A parity is deferred to a runtime validation once a fitting quantized conversion exists; the merge gate is the unit tests plus the real nested-config parse. - FastVLM (
llava_qwen2/fastvlm): Apple's low-latency VLM. A FastViTHD hybrid encoder runs entirely on channels-last maps: a conv stem, three RepMixer stages (depthwise token mixing plus a BatchNorm ConvFFN), two attention stages with channel LayerNorm andhead_dim32 self-attention, inter-stage large-kernel PatchEmbed downsamples, RepCPE position encoders, and a squeeze-exciteconv_exphead. Each 1024x1024 pad-to-square image becomes a(16, 16, 3072)map flattened to 256 tokens, projected to the Qwen2 decoder width by anmlp2x_geluMLP. The<image>placeholder is the fixed-200sentinel (not a vocabulary token); the runtime splices one sentinel per image, expands it to 256 tokens, and scatters the image embeddings (LLaVA merge). The text decoder is stock Qwen2, reused unchanged. The loader accepts both the genuine (apple/FastVLM-0.5B) and converted (mlx-community/FastVLM-0.5B-bf16) weight layouts. Best for fast image description and grounded chat. - GLM-OCR (
glm_ocr): document-OCR sibling of GLM-4V. A 24-block ViT (3D patch embedding, per-head q/k RMSNorm on the packedcu_seqlensattention, 2D vision RoPE, Conv2d spatial downsample, SwiGLU patch merger) feeds a 16-layer GLM-4 text decoder driven by full-width even/odd MRoPE (rope_parameterswithmrope_section [16, 24, 24],partial_rotary_factor 1.0). The tower has no learned position embedding or post-conv norm, and the loader drops the next-n prediction (MTP) layer. Patches are reordered from the processor's raster order into spatial-merge-window order so the rotary, downsample, and merged-token grid stay spatially aligned (OCR reads scrambled patches wrong). Best for plain text, tables, and formula recognition. - Youtu-VL
- Kimi-VL and Kimi-VL 2.5 (
kimi_vl/kimi_k25): MoonViT native-resolution vision encoder (Conv2d patch embedding, learned plus bicubically-interpolated 2D position embedding, a shared 2D rotary embedding, block-diagonal cross-image attention, andspatial_merge_sizepatch merging) feeding aLayerNorm -> Linear -> GELU -> Linearconnector into a DeepSeek-V3-style MoE text backbone. Detected, loaded, and served end to end: the safetensors directory loader wires the MoonViT tower, the connector, and the DeepSeek-V3 MoE backbone; the native-resolution processor patchifies each image; and the runtime expands each<|media_pad|>placeholder into(h/merge) * (w/merge)tokens before the merged vision features replace them. Video is also supported, on both the CLI (--video) and the server (video_urlcontent blocks): frames are extracted withffmpeg(uniform sampling, default 2.0 fps, matching the Gemma 4 video path) and patchified per frame, and the encoder treats a clip as a 3D(t, h, w)patch grid rather thantindependent images. A computed (not learned) temporal sinusoid is added to the tiled 2D position table, the 2D rotary tables repeat per frame, attention over a clip is one block-diagonal segment spanning all its frames, and the patch merger mean-pools over the temporal axis before the usualspatial_merge_size2x2 merge, so the placeholder expansion(h/merge) * (w/merge)is unchanged byt. A single-frame clip is equivalent to the same frame processed as an image once the frame-0 temporal constant folds into the patch-embed bias. - SmolVLM, SmolVLM2, and Idefics3 (
smolvlm/idefics3): one shared Idefics3-family runtime, a SigLIP vision tower + pixel-shuffle token compression + a Llama text backbone (SmolLM2 for SmolVLM, Llama-3 forIdefics3-8B-Llama3). Both on-disk layouts load:SmolVLMForConditionalGeneration(model.text_model.*+ a top-levellm_head) andIdefics3ForConditionalGeneration(the whole Llama-with-head nested underlanguage_model.*). Images are tiled into square patches with a global thumbnail tile, and each<image>placeholder expands tonum_image_tokencompressed feature tokens per tile. - Idefics2 (
idefics2): SigLIP vision tower + a perceiver-resampler connector (amodality_projectionSwiGLU MLP into the text hidden size, thenn_latentslearned query slots refined by grouped-query cross-attention over the image patches) + a Mistral text backbone. Each image contributes a fixedn_latents(64) compressed feature tokens regardless of the patch grid, and the<image>placeholder is framed by<fake_token_around_image>and expanded to those tokens. This first port feeds a single full-resolution square tile per image; the optionaldo_image_splittinghigh-resolution tiling is a documented follow-up. - MiniCPM-O
- Moondream 3
- Moondream 2 (
moondream2/moondream1): reuses Moondream3's linear-patch ViT vision tower and overlap-crop preprocessor, paired with a Phi-1.5-style dense text decoder (fused QKV, partial rotary embedding, parallel attention/MLP, tanh-GELU) instead of Moondream3's sparse-MoE decoder. Images are split into a resized global crop and a grid of overlapping local crops; the local crop features are trimmed of their overlap margins, stitched, and adaptively average-pooled back to the 27x27 encoder grid before being concatenated with the global features and projected to the text hidden size. The BOS token and the 729 projected image tokens form a bidirectional prefix ahead of the causal text prompt. Checkpoint revisions from 2025-06-21 onwards are trained against themoondream/starmie-v1tokenizer with Moondream3-style control-token templates (bos = eos = 0), while the official repository still ships the older GPT-2tokenizer.jsonnext to them; mlxcel detects the revision from the bundledmoondream.py, resolves the starmie tokenizer from the Hub (cached after the first fetch, or place starmie'stokenizer.jsonin the model directory when offline), and keeps the GPT-2 tokenizer withQuestion:/Answer:framing for the 2025-01-09 .. 2025-04-14 revisions where that contract is the correct one. - Phi-3 Vision, Phi4MM, Phi4 SigLIP VLM
- Molmo2 and Molmo-Point
- Nemotron-H Nano Omni: ships a Conformer/Parakeet audio encoder and accepts spoken audio from the CLI with
--audio <path>. Input audio is resampled to 16 kHz before the encoder. Server-sideinput_audioinPOST /v1/chat/completionsis also supported: the audio block is spliced inside the last user turn, before the<|im_end|>end-of-turn marker that the ChatML template uses (id 151 in the released checkpoint).
Audio/video capability is model-specific. The server request types include
image_url, video_url, and input_audio content blocks, but a loaded model
must advertise support for the corresponding modality. Video frame extraction
uses the system ffmpeg/ffprobe binaries at runtime.
Gemma 4's vision front-end is resolution-driven: it works over whatever patch grid the preprocessor hands it, with no fixed feature length. The number of soft tokens an image contributes to the prompt therefore follows directly from the resize target, and the resize target follows from a soft-token budget. That budget is read from the checkpoint's config at load time (280 for every shipped Gemma 4 checkpoint) and can be overridden per request.
This applies to both Gemma 4 architectures: gemma4 (the ViT tower, e.g.
gemma-4-e2b-it, gemma-4-31b-it) and gemma4_unified (the encoder-free patch
projector, e.g. gemma-4-12b-it).
A larger budget keeps more detail (denser patch grid, better small-text and fine-structure reading) at the cost of a longer prompt and more prefill work. A smaller budget is cheaper and faster. Supported values, shared with the video per-frame budget:
| Budget | Meaning |
|---|---|
| 70 | Smallest. What detail: "low" maps to. |
| 140 | |
| 280 | Checkpoint default for the shipped Gemma 4 models. |
| 560 | |
| 1120 | Largest. What detail: "high" maps to. |
Any other value is rejected with a 400. The budget is untrusted request input
and it scales the resized image and its patch grid, so it is validated against
this ladder rather than clamped: a silent clamp would leave the caller believing
they got a budget they did not get. 1120 is also the hard ceiling for
gemma4_unified, whose learned 2-D position table is exactly 1120 wide; a budget
past it would index off the end of that table.
Two optional fields on the image_url content part:
{
"model": "gemma-4-12b-it-4bit",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Transcribe the small print."},
{"type": "image_url", "image_url": {
"url": "data:image/png;base64,...",
"detail": "high"
}}
]
}]
}-
detailis the OpenAI-standard field."low"maps to 70,"high"maps to 1120, and"auto"(or an absent field) leaves the checkpoint's configured budget in place. An unknown value is a 400, not a silent fallback to"auto". -
max_soft_tokensis an mlxcel extension, not part of the OpenAI spec. It names an exact budget from the ladder above and takes precedence overdetailwhen both are present:{"type": "image_url", "image_url": {"url": "...", "max_soft_tokens": 560}}
Both fields are optional and default to absent, so a request that sends only
url behaves exactly as it did before these fields existed. The budget applies
to the request as a whole; when a request carries several image_url parts they
must agree on an explicit budget (parts that set neither field are free to
coexist with parts that do). Every non-Gemma-4 model ignores both fields.
Note that the budget is part of the vision-feature cache identity, so the same image requested at two budgets is encoded twice rather than served the wrong cached features.
mlxcel generate --image-soft-tokens <N> takes the same ladder and the same
validation:
./target/release/mlxcel generate -m models/gemma-4-12b-it-4bit \
--image receipt.png --image-soft-tokens 1120 \
-p "What is the total?"Omitting the flag uses the checkpoint's configured budget. The flag applies to
--image inputs only; --video frames keep their own (smaller) per-frame
budget.
Gemma 4 Unified (gemma4_unified) ships <|channel> / <channel|> thinking
markers in its tokenizer, so the server defaults enable_thinking=true for this
family on startup, mirroring ml-explore/mlx-lm#1114.
With thinking on, the model writes an internal scratchpad before the visible
reply, so simple prompts spend more of the budget on reasoning than on the
answer. A one-sentence answer can take roughly 275 completion tokens, and a
default max_tokens of 64 to 80 may return an empty content with
finish_reason of length because the whole budget went to thinking. Set
max_tokens to at least 512 for this family, and higher for multi-sentence
answers.
The scratchpad is no longer dropped: it is surfaced as reasoning_content on
both streaming responses (delta.reasoning_content) and non-streaming responses
(a reasoning_content field on the assistant message, present only when the
model produced reasoning). This applies to every thinking family, including
Qwen-style <think> models. To turn thinking off, pass
chat_template_kwargs={"enable_thinking": false} per request, or set the server
default via --chat-template-kwargs or LLAMA_ARG_CHAT_TEMPLATE_KWARGS. A
per-request value always wins over the server default.
The upstream deepseek-ai/DeepSeek-V3.2-Exp chat template gates its
<think> block on a bare thinking boolean rather than the conventional
enable_thinking kwarg that mlxcel forwards by default (verified against
deepseek-ai/DeepSeek-V3.2-Exp assets/chat_template.jinja).
Because the template only ever reads thinking, enable_thinking alone would
have no effect on this family. mlxcel detects the {% if not thinking is defined %} idiom in the loaded template and, when present, also mirrors the
fully-resolved enable_thinking value (request override, or the server
default) into a thinking key so toggling reasoning works the same way it
does for every other thinking-capable model. The detection is based on the
template source, not the model name, so any future template that adopts the
same idiom is covered automatically. GLM-5.2 (glm_moe_dsa) ships its own
chat template that already reads enable_thinking directly and is
unaffected. An explicit thinking entry in chat_template_kwargs always
overrides the derived alias.
Some chat templates check a thinking_mode string (for example thinking_mode == "enabled") instead of the enable_thinking boolean, so mlxcel also detects that identifier in the loaded template and injects thinking_mode: "enabled" whenever the resolved enable_thinking value is true. Nothing is injected when thinking is off, and an explicit thinking_mode entry in chat_template_kwargs always overrides the derived value.
Gemma 4 (31B Dense and 26B-A4B MoE, including the QAT 4-bit checkpoints) has an upstream, weights-level token-repetition collapse documented in google-deepmind/gemma#622 and reproduced across other engines, including vllm-project/vllm#40080. Generation can degenerate into a single repeated token (or short fragment) that fills the token budget, most often inside the thought channel. Tool declarations and json_schema structured-output requests amplify it, but it is not limited to those cases. Sampling penalties do not reliably recover it, because once the logits collapse the top-k candidates are themselves garbage.
mlxcel applies vLLM-style N-gram loop detection to break this, default-on for the Gemma 4 family with no configuration required. For any model in the family (Gemma4, Gemma4VLM, Gemma4Unified), the engine applies the conservative threshold min_pattern_size=1, max_pattern_size=20, min_count=4 by default; a degenerate run then ends early with finish_reason of stop. The default-on applies to plain Gemma 4 chat too, so a downstream serving app and its users need no setup and see no toggle. Detection only ends generation when a real repetition loop is present, so this conservative default is low risk. Every non-Gemma-4 model defaults to disabled (bit-exact baseline preserved). The behavior is still tunable on top of the default: a per-request override (the vLLM max_pattern_size / min_pattern_size / min_count fields, including max_pattern_size=0 to opt out) wins, and a global operator override (MLXCEL_LOOP_DETECTION) can tune, force-enable for any model, or force-disable. See Generation loop detection for the field semantics and the full precedence order.
mlxcel loads Whisper-style encoder-decoder ASR checkpoints (model_type: "whisper") and serves them through the OpenAI audio endpoints. A convolutional audio encoder builds features from a 30-second log-mel window, and an autoregressive text decoder cross-attends to those features as it emits tokens, steered by the multilingual transcribe/translate task tokens.
When the server's loaded checkpoint is detected as Whisper, the speech-to-text slot is populated and POST /v1/audio/transcriptions (transcribe in place) and POST /v1/audio/translations (translate to English) return the recognized text. Uploaded audio is decoded with the shared WAV reader, resampled to 16 kHz, and processed in consecutive 30-second windows. An explicit language hint is honored; otherwise the language is detected from the first decoder step. Token suppression follows the Whisper rules: suppress_blank, the non-speech symbol set, and <|notimestamps|>.
This first port targets non-quantized (fp16/f32) checkpoints with greedy decoding, and the loader accepts both the native MLX and HuggingFace key layouts. Loading a Whisper checkpoint serves speech-to-text only; chat generation is not available in the same process. Beam search, word-level and segment timestamps, quantized checkpoints, and streaming transcription are follow-ups.
mlxcel loads the Kokoro-82M model (a StyleTTS2 phoneme-to-mel acoustic model with a built-in iSTFTNet vocoder) and serves it through POST /v1/audio/speech. The path is: text to phonemes (grapheme-to-phoneme front-end) to a PLBert text encoder, a duration predictor that expands per-token features to per-frame, F0 (pitch) and energy prosody, and an iSTFTNet decoder that produces a 24 kHz mono waveform directly via an inverse STFT (no separate neural codec).
Detection works without a top-level model_type: the loader recognizes a Kokoro checkpoint by the istftnet config block or the kokoro-v1_0.safetensors weight filename, so -m <kokoro-dir> resolves to the TTS provider. The voice request field selects a pack from voices/<name>.safetensors (54 voices; default af_heart), validated against the available packs with a safe fallback. speed scales the predicted durations (larger is faster and shorter). response_format accepts wav today (returned via the shared WAV writer); other containers are a follow-up.
The grapheme-to-phoneme front-end is a self-contained American-English phonemizer: text is normalized (lower-cased, integers spoken, common punctuation kept), each word is looked up in a bundled lexicon, and out-of-vocabulary words fall back to deterministic letter-to-sound rules. It emits the IPA symbols in Kokoro's vocab and needs no external binary or download. Non-English voices in the checkpoint still load and synthesize, but their phonemes come from the English front-end, so pronunciation quality is limited; per-language g2p (the analogue of upstream Kokoro's misaki[xx] packages) is future work. Like Whisper, the model loads and runs every synthesis on one dedicated MLX worker thread, so loading a Kokoro checkpoint serves text-to-speech only.
| Format | Status | Notes |
|---|---|---|
| FP16 / BF16 | supported | BF16 handling is platform/model dependent; Apple Silicon paths commonly convert to FP16 for execution. |
| 4-bit affine MLX checkpoints | supported | Primary path for many mlx-community checkpoints. CUDA coverage depends on MLX kernel support for the target GPU. |
| 8-bit affine | supported | Used for weights and/or KV cache depending on path. |
| NVFP4 / MXFP4 / MXFP8 | supported where implemented | Used by specific families such as GPT-OSS and recent quantized checkpoints. |
Do not infer quality or speed from the ability to load a quantized checkpoint. Run a smoke test and, for release claims, a benchmark/quality gate.
| Capability | Current summary |
|---|---|
| Tensor parallelism | Advertised for selected dense text families such as Llama, Qwen, Gemma text, ERNIE 4.5, and Hunyuan dense. Validate per model/rank count. |
| Pipeline parallelism | Best validated for Llama-family text models; stage executors exist for more families with less operator coverage. |
| VLM under TP/PP | Partial. Vision tower / projector partitioning is not uniformly supported. |
| Disaggregated inference | Infrastructure exists; validate per topology and workload. |
| Drafter | Target families | Notes |
|---|---|---|
| MTP | Gemma 4 target paths | Available through shared speculative decoding flags. |
| DFlash | Qwen 3.5 text/VLM paths | Available through shared speculative decoding flags. |
Use auto-detection by default. Override only when you know the target and drafter checkpoint pair are compatible.
- A supported architecture does not imply every community checkpoint variant is supported.
- VLM and video/audio paths require additional runtime dependencies and prompt preparation beyond text-only generation.
- TurboQuant, TP, PP, and speculative decoding are not uniformly validated for every family.
- The
mlxcel archoutput is a CLI summary and may lag the detailed enum count; the canonical source remainssrc/models/mod.rsandsrc/models/detection.rs.
See Adding a new model for the registration, loading, and test checklist.