Instructions to use KaedeTai/dflash2-mlx-quantized-draft with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use KaedeTai/dflash2-mlx-quantized-draft with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] huggingface-cli download --local-dir dflash2-mlx-quantized-draft KaedeTai/dflash2-mlx-quantized-draft
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Atomic Chat
File size: 5,797 Bytes
78c877d e3c1203 78c877d 97877d3 78c877d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | ---
license: mit
library_name: mlx
tags:
- mlx
- speculative-decoding
- dflash2
- apple-silicon
- quantization
- benchmark
base_model:
- Qwen/Qwen3.8-27B
---
# DFlash2 on Apple Silicon β quantized-draft loader + M5 Max measurements
Two things this repo provides, neither of which is model weights:
1. **`load_draft_q4.py`** β a drop-in loader that lets the
[`cfontes/qwen3.8-27b-mlx-dflash2`](https://huggingface.co/cfontes/qwen3.8-27b-mlx-dflash2)
server and benchmarks use a **quantized** DFlash2 drafter. The upstream loader builds a
bf16 skeleton and calls `load_weights` directly, so a 4-bit draft fails on shape
mismatch.
2. **`config.json`** β the draft config that
[`ProCreations/Qwen3.8-27B-DFlash2-MLXFast-Q4`](https://huggingface.co/ProCreations/Qwen3.8-27B-DFlash2-MLXFast-Q4)
ships without. That repo contains only `model.safetensors`, so no standard loader can
instantiate it.
Plus the measurements that motivated both.
## Headline: quantizing the *drafter* is close to free throughput
Apple **M5 Max**, 128 GB, macOS 26.4.1, MLX 0.32.0 / mlx-lm 0.31.3. Target:
`tozp/Qwen3.8-27B-OBLITERATED-V2-mlx-4bit`. Greedy, 300 tokens, K=4, interleaved A/B with a
90 s cooldown before each measurement, two rounds.
| drafter | size | tok/s | accept |
|---|---:|---:|---:|
| `z-lab/Qwen3.8-27B-DFlash2` (bf16) | 3.85 GB | 59.8 / 60.3 | 87.9% |
| `ProCreations/...-MLXFast-Q4` (affine-4 g64) | **1.27 GB** | **76.1 / 76.0** | 86.9% |
| | β2.6 GB | **+26%** | β1.0 pp |
The drafter runs a forward pass every block, so shrinking it by 2.6 GB removes real
bandwidth from the hot loop. The prediction quality it costs β one point of acceptance β is
nowhere near enough to offset that.
Stacked against no speculation at all, on the same target and machine:
| configuration | tok/s | vs dense |
|---|---:|---:|
| dense (`mlx_lm.stream_generate`) | 33.3 | 1.00Γ |
| + bf16 drafter | 61.4 | 1.84Γ |
| **+ Q4 drafter** | **76.1** | **2.29Γ** |
A 27B **dense** model at 76 tok/s in **16.1 GB resident** (measured RSS with the server
loaded and generating; 14 GB target + 1.2 GB drafter on disk, plus KV cache β it grows
with context).
## Target-model comparison (same protocol)
| target | dense | DFlash2 (bf16 draft) | speedup | accept | greedy token-exact vs dense |
|---|---:|---:|---:|---:|---|
| `mlx-community/Qwen3.8-27B-mxfp4` | 35.4 | 54.0 | 1.52Γ | 82% | yes |
| Qwen3.8-27B abliterated w/ [Heretic](https://github.com/p-e-w/heretic) | 33.3 | 62.2 | 1.87Γ | 89% | one near-tie flip |
| `tozp/...-OBLITERATED-V2` | 33.3 | 61.4 | 1.84Γ | 88% | yes |
Round-to-round spread under 2% on every cell.
**The drafter transfers across quantization schemes and weight surgery.** It is trained
against the stock model; both alternatives are abliterated by unrelated methods (Optuna
search vs SVD+LEACE blend) *and* quantized differently (affine-4 g64 vs mxfp4 g32).
Acceptance went **up** 6β7 points rather than down. Two independent methods landing in the
same place suggests the cause is removing refusal directions as such β plausibly lower
next-token entropy, which is testable and untested here.
## Measurement traps on this hardware
- **Thermal drift.** Running targets back-to-back without cooldowns, the same mxfp4
measurement read 34.9 t/s at the start and 26.8 t/s three minutes later β **β23%**, enough
to invert a model-vs-model conclusion. Interleaving with 90 s cooldowns took spread from
23% to under 2%.
- **Cold start.** The first model load of a session measures far below steady state; one run
produced `dense 1.9 t/s / speedup 18.00x`. Warm up before timing.
- **`ioreg` "Device Utilization %" is useless here** β it reads 100% at rest. Check GPU
memory in use and whether other engines hold models instead. A 37 GB workload on the GPU
went undetected this way and produced a full set of wrong numbers.
## Usage
```bash
git clone https://huggingface.co/cfontes/qwen3.8-27b-mlx-dflash2 dflash2
cd dflash2
hf download ProCreations/Qwen3.8-27B-DFlash2-MLXFast-Q4 --local-dir models/draft-q4
cp /path/to/this/repo/config.json models/draft-q4/config.json
cp /path/to/this/repo/load_draft_q4.py bench/extra/load_draft_q4.py
# point the server at the quantized draft
python dflash2_mlx_server/server.py --main-dir models/<target> --draft-dir models/draft-q4
```
`server.py` calls `dflash_port.local_load.load_draft_from_dir`; swap that import for
`load_draft_any` from `load_draft_q4.py`. The loader detects a `quantization` block and
falls back to the original function when there isn't one, so bf16 drafts keep working.
Verified end-to-end: server loads in 0.9 s and reports `accept_rate 0.917, tok_per_s 75.4`.
## How the loader works
`nn.quantize` is applied to the draft skeleton **before** `load_weights`, with a predicate
that quantizes exactly the modules that have a `.scales` entry in the weight file β the same
test `mlx_lm` uses. It also normalizes the candidate-selector codebook keys, which the two
published drafts spell differently (`candidate_selector.predecessor_codebook` vs
`...codebook.weight`); the upstream rename raises `KeyError` on the Q4 layout.
## Credits
- [z-lab](https://huggingface.co/z-lab/Qwen3.8-27B-DFlash2) β the DFlash2 drafter
- [cfontes](https://huggingface.co/cfontes/qwen3.8-27b-mlx-dflash2) β the MLX port and server this patches (MIT)
- [ProCreations](https://huggingface.co/ProCreations/Qwen3.8-27B-DFlash2-MLXFast-Q4) β the affine-4 quantization measured here
- [tozp](https://huggingface.co/tozp/Qwen3.8-27B-OBLITERATED-V2-mlx-4bit) and [Heretic](https://github.com/p-e-w/heretic) β the abliterated targets
No model weights are redistributed here. `config.json` is derived from z-lab's draft config
with a quantization block added.
|