Skip to content

Convert a model

Most people can download a published build. Convert your own when the model or the bit mix you want isn't published yet.

Conversion is data-free: it needs only the model's weights, no calibration text. It reads a Hugging Face repo or a local folder in BF16 or FP16 and writes MLX safetensors plus a quantization block in config.json.

turboquant-convert \
    --hf-path meta-llama/Llama-3.2-1B \
    --mlx-path ./llama-3.2-1b-tq3 \
    --bits 3 --group-size 64

(python -m turboquant_mlx.convert is the same command.) Vision and diffusion models use convert_vlm instead: see Vision models.

Choosing bits and group size

Option Values Effect
--bits, -b 2, 3, 4 (default 3) Codebook width for every quantized layer. 3 is the usual choice; 4 for the most quality; 2 only for very large MoEs.
--group-size, -g 32, 64, 128 (default 64) How many weights share one scale. 32 is more accurate and a little bigger; 64 is the usual choice.

Mixed precision for Mixture-of-Experts

In a big MoE, the routed experts are most of the weights but each token uses only a few of them, so they tolerate fewer bits than attention.

Option What it does
--attn-bits / --mlp-bits Separate widths for attention and for MLP/expert layers. --bits 3 --mlp-bits 2 gives the tq3a-tq2e builds.
--mlp-group-size A finer group size for the expert tier only (16, 32, 64, 128).
--ternary-experts Experts on a ternary {−c, 0, +c} codebook, about 1.6 bits per weight, packed as base-3 trits. Attention stays at --bits. These are the tqTe builds.
--expert-down-bits Gives the experts' down projection its own width, above the ternary or 2-bit tier. --ternary-experts --expert-down-bits 4 gives the down4 builds.
--protect-expert-layers Keeps the experts of chosen layers (for example 0-2,45-47) at --protect-bits (default 3).
--expert-layer-tiers A JSON file choosing a tier per MoE layer: ternary, 2, 3 or 4.
# Ternary experts: Qwen3-235B in 53 GB, fully resident on a 64 GB Mac
turboquant-convert \
    --hf-path Qwen/Qwen3-235B-A22B-Instruct-2507 \
    --mlx-path ./qwen3-235b-tq3a-tqTe-g64 \
    --bits 3 --group-size 64 --ternary-experts --streaming

# Ternary experts with a 4-bit down projection: the agent-capable 35B for a 16 GB mini
turboquant-convert \
    --hf-path Qwen/Qwen3.6-35B-A3B \
    --mlx-path ./Qwen3.6-35B-A3B-tq3a-tqTe-down4-g64 \
    --bits 3 --group-size 64 --ternary-experts --expert-down-bits 4

Sub-2-bit experts only hold on some models

Ternary and 2-bit experts rely on many experts sharing the work. Measured so far:

  • Works on models with many, wide experts: Qwen3-235B (128 experts, top-8), Qwen3.5-122B and Qwen3.6-35B (256), Laguna-S-2.1 (256, 1024 wide), Nemotron 3.5 Super VL (512, top-22).
  • Fails with narrow experts (Laguna-XS.2, 512 wide: it loops), with few active experts on a 4-bit source (GPT-OSS-120B, top-4, MXFP4), and on 32-expert models (GPT-OSS-20B becomes word salad at 2-bit).

Always check a new build on real prompts, not only with the unit tests. A 4-bit down projection (--expert-down-bits 4) has rescued two failing ternary builds.

Nemotron-H layer names

Nemotron-H models name their blocks mixer.*, which --attn-bits, --mlp-bits and --mlp-group-size don't recognise, so on Nemotron-H only --bits and --group-size apply. --ternary-experts and --expert-down-bits do work, because they pick experts by layer type.

Models too big to convert in memory: --streaming

The in-memory converter holds the whole quantized model before saving, which limits a 64 GB Mac to about 130B parameters at 3-bit. --streaming writes each layer to a shard as soon as it is quantized and frees it, so the peak stays near one shard plus one layer, whatever the model size. Qwen3-235B converts on a 16 GB Mac mini this way.

Point --mlx-path at a disk with room for the output, and expect the source download to need more space than the result. (--dtype is not supported with --streaming.)

Everything else the polar path skips: --quantize-extras

TurboQuant compresses the linear layers. Embeddings, lm_head and (in vision models) the vision tower are left in BF16 unless you add --quantize-extras, which stores them as MLX affine (--extras-bits 2, 3, 4 or 8, default 4; --extras-group-size). It matters most on models with a big lookup table: Qwen3.8-Flash-Next's n-gram table is 51.2B parameters, so without it a ternary build is about 124 GiB instead of 54 GiB. Routers always stay at full precision.

Other options

Option Use
--rotation hadamard (default), blockwise_hadamard or none. Leave the default.
--rotation-seed Seed for the random rotation signs (default 42).
--use-qjl Adds a 1-bit residual correction (about +1 bit). Slow to decode; not recommended.
--dtype Cast the source before quantizing: float16, bfloat16, float32.
--keep-mtp Copies a multi-token-prediction head (Qwen3.8) into the output. Nothing uses it by default yet.
--trust-remote-code Lets the source run its own tokenizer or model code. Needed for Kimi K3 by Hub id. Only use it for sources you trust.

Check the result

turboquant-plan --model ./qwen3-235b-tq3a-tqTe-g64       # does it fit, and with which settings?
turboquant-generate --model ./qwen3-235b-tq3a-tqTe-g64 --prompt "Why is the sky blue?"

To measure perplexity against the original, see python -m turboquant_mlx.evaluate --help (needs the [eval] extra).