Bug
At temperature 0 (greedy), mlx_lm.generate with --draft-model (speculative decoding) produces different output than the same call without a draft model. Greedy speculative decoding should be lossless — the target verifies every drafted token and accepts only its own argmax, so the output must equal plain greedy decoding. Instead the two diverge, reproducibly.
Versions
mlx 0.31.2
mlx-lm 0.31.3
- Apple M3 Ultra (512 GB), macOS 26.2 (arm64)
Reproduce
Public models — 8-bit target, 4-bit draft, byte-identical tokenizer (both vocab 262144):
# (A) no speculative decoding
mlx_lm.generate --model mlx-community/gemma-4-31b-it-8bit \
--temp 0 --max-tokens 500 \
--prompt "Write a detailed essay (multiple paragraphs) explaining how a transformer neural network processes a sentence, from tokenization through attention to output."
# (B) with speculative decoding (same prompt)
mlx_lm.generate --model mlx-community/gemma-4-31b-it-8bit \
--draft-model mlx-community/gemma-4-e2b-it-4bit --num-draft-tokens 2 \
--temp 0 --max-tokens 500 \
--prompt "Write a detailed essay (multiple paragraphs) explaining how a transformer neural network processes a sentence, from tokenization through attention to output."
Expected
(A) and (B) identical (greedy spec-decode is exact).
Actual
They diverge. Same prompt, temp 0:
(A) no draft: …its significance (replacing RNNs/LSTMs), and the general flow (Encoder-Decoder or Decoder-only).
(B) with draft: …its departure from RNNs/LSTMs (parallelism), and the general goal (mapping input sequences to output sequences).
Observations:
- Reproducible & deterministic across repeated isolated runs (not a flaky startup artifact).
- The divergence appears/accumulates with longer generations; short generations — or runs where an early
stop sequence truncates output before the divergence point — can look identical, which makes it easy to miss.
- Not a tokenizer mismatch — draft and target
tokenizer.json are byte-identical (vocab 262144).
- Also reproduces via
mlx_lm.server /v1/chat/completions with the same model pair: spec-decode responses can drop the entire post-reasoning content on longer generations, consistent with the same underlying divergence.
Bug
At temperature 0 (greedy),
mlx_lm.generatewith--draft-model(speculative decoding) produces different output than the same call without a draft model. Greedy speculative decoding should be lossless — the target verifies every drafted token and accepts only its own argmax, so the output must equal plain greedy decoding. Instead the two diverge, reproducibly.Versions
mlx0.31.2mlx-lm0.31.3Reproduce
Public models — 8-bit target, 4-bit draft, byte-identical tokenizer (both vocab 262144):
Expected
(A) and (B) identical (greedy spec-decode is exact).
Actual
They diverge. Same prompt, temp 0:
Observations:
stopsequence truncates output before the divergence point — can look identical, which makes it easy to miss.tokenizer.jsonare byte-identical (vocab 262144).mlx_lm.server/v1/chat/completionswith the same model pair: spec-decode responses can drop the entire post-reasoningcontenton longer generations, consistent with the same underlying divergence.