Qwen3-32B-lecore-19g-mlx
MLX mixed-precision quantization of Qwen/Qwen3-32B, with the bit width of every
linear layer picked by leCore Unicron requantize (per-tensor bits chosen by measurement), ported to GPU for this model size.
How the bits were chosen
- Each decoder linear tensor was quantized alone (MLX affine, group 64 during measurement) at 2, 3 and 4 bits; the damage was measured as KL(fp16 || quantized) on next-token distributions over a calibration mix (3066 WikiText-2 train tokens, 1022 Python-source tokens, and leCore's structured probe: prose, code, SQL, markdown).
- Bits were assigned greedily: start at 4 bits everywhere, repeatedly take the downgrade with the least measured damage per byte saved until the predicted file size fit the budget. Embeddings 4-bit, lm_head 6-bit, group size 64.
- Converted with
mlx_lm.convertand a per-layerquant_predicate. Bit histogram (linear tensors): {'2': 0, '3': 0, '4': 448, '8': 0, '16': 0} Note: at this size budget the allocator kept every linear tensor at the top rung (4 bits), so the per-tensor selection made no downgrades. In practice this export is uniform 4-bit (group 64), with 4-bit embeddings and a 6-bit lm_head. It is not a mixed-precision mix, and the fair baseline is stock MLX 4-bit, not 3-bit Note: at this size budget the allocator kept every linear tensor at the top rung (4 bits), so the per-tensor selection made no downgrades. In practice this export is uniform 4-bit (group 64), with 4-bit embeddings and a 6-bit lm_head. It is not a mixed-precision mix, and the fair baseline is stock MLX 4-bit, not 3-bit.
Measured results (held-out: WikiText-2 test + a different Python-source slice, seq 512)
Perplexity was computed on the exact shipped weights (MLX tensors dequantized with mx.dequantize, run in bf16 on GPU).
"bpw" = integer bits + 0.5 for the bf16 scale/bias per group of 64.
| Model | Size (GB, weights) | bpw | WikiText-2 ppl (32704 tok) | Python-code ppl (8176 tok) |
|---|---|---|---|---|
| bf16 reference | – | 16 | 9.7287 | 3.5031 |
| this repo (leCore Unicron mix) | 18.62 | 4.547 | 11.4757 | 3.9427 |
| stock MLX 3-bit, group 64 | 14.33 | 3.500 | 39.0780 | 7.4644 |
Benchmarks (lm-eval-harness 0.4.9, run on the shipped weights dequantized to bf16 on GPU)
MMLU 5-shot on the first 10 questions of each of the 57 subjects; GSM8K 5-shot on the first 100 test problems (greedy, 320 new tokens, no chat template). These are subsets, so expect about ±2–4 points of sampling noise.
| Model | MMLU (5-shot) | GSM8K strict | GSM8K flexible |
|---|---|---|---|
| leCore mix (this repo) | 85.3% | 27.0% | 34.0% |
| stock 3-bit affine, group 64 (simulated) | 80.9% | 83.0% | 78.0% |
Only measured numbers are reported. Downstream benchmarks are limited to the MMLU/GSM8K subsets above. Short-context perplexity does not tell you everything about quality, so check outputs for your own use case.
GSM8K regression (diagnosed)
GSM8K is much lower than both bf16 and stock 3-bit, even though perplexity is close to bf16. We ran a diagnostic on the first 20 GSM8K problems:
| strict | flexible | |
|---|---|---|
| bf16 | 70% | 80% |
| this export | 25% | 30% |
| this export, but MLP left in bf16 | 75% | 75% |
| this export, but embeddings left in bf16 | 25% | 25% |
| this export, but lm_head left in bf16 | 20% | 15% |
The quantized model reasons correctly but in a long "thinking" style, so it runs past the 320-token limit before writing the #### answer line. The drift comes from the 4-bit MLP weights. If you need few-shot math in this format, use stock quantizations or a larger budget. For chat use with a longer generation limit this matters less, but we have not measured that.
Files in this repo
| file | size | what it is |
|---|---|---|
model-00001-of-00004.safetensors … (4 safetensors shards) |
18.62 GB total | quantized weights, sharded |
tokenizer.json |
11.4 MB | tokenizer |
vocab.json |
2.8 MB | config / tokenizer |
merges.txt |
1.7 MB | support file |
model.safetensors.index.json |
137.9 KB | config / tokenizer |
config.json |
97.5 KB | model config |
tokenizer_config.json |
5.4 KB | config / tokenizer |
chat_template.jinja |
4.2 KB | chat template |
added_tokens.json |
707 B | config / tokenizer |
Usage (Apple Silicon)
pip install -U mlx-lm
mlx_lm.generate --model staccs/Qwen3-32B-lecore-19g-mlx --prompt "Hello" --max-tokens 256 --max-kv-size 8192
Weights are ~18.62 GB. On a 36 GB Mac you may need to raise the GPU wired-memory limit, e.g. sudo sysctl iogpu.wired_limit_mb=30000.
License
Base model: Qwen/Qwen3-32B, released by the Qwen team under the Apache License 2.0 (https://huggingface.co/Qwen/Qwen3-32B/blob/main/LICENSE). Only quantization was done here: no retraining.
Related builds
Same base model, other formats in the lecore set:
| repo | format | size |
|---|---|---|
| Qwen3-32B-lecore-19g-GGUF | GGUF (llama.cpp) | 38.40 GB |
| Qwen3-32B-lecore-GGUF | GGUF (llama.cpp) | 32.88 GB |
| Qwen3-32B-lecore-hrr | gated-HRR gates | 4.4 MB |
| Qwen3-32B-lecore-mlx | MLX (Apple Silicon) | 13.01 GB |