Skip to content

mlx: propose argmax tokens for v1 drafts under sampling - #169

Open
shoemoney wants to merge 1 commit into
z-lab:mainfrom
shoemoney:pr/v1-argmax-proposals
Open

shoemoney wants to merge 1 commit into
z-lab:mainfrom
shoemoney:pr/v1-argmax-proposals

Conversation

@shoemoney

@shoemoney shoemoney commented Sep 8, 2026 •

Copy link
Copy Markdown

Problem

In _stream_generate, a v1 draft at temperature > 0 samples every block position independently from its own distribution (_sampling_probs then _sample_probs). A v1 head's positions are marginals, not a joint sequence distribution, so the sampled block is incoherent and the target rejects nearly all of it.

Measured with meta-models/Muse-Glimmer-30B-assistant (4-bit) on mlx-community/Muse-Glimmer-30B-4bit, M3 Ultra, T=1 / top-p 0.95 / top-k 64, 6 prompts x 256 tokens:

proposal policy block tok/s vs no draft accepted / step
none - 40.1 1.00x -
independent per-position sampling (current) 5 18.2 0.45x 1.16
independent per-position sampling (current) 8 12.8 0.32x 1.16
argmax proposal (this PR) 5 47.2 1.18x 2.96
argmax proposal (this PR) 8 38.6 0.96x 3.49

Greedy acceptance for the same head is 2.93 at block 5, so the fix restores the head's full acceptance. DFlash2DraftModel is unaffected either way (its candidate selector already proposes a coherent block; 3.35 accepted/step at the same settings).

Fix

For non-DFlash2 drafts at temperature > 0, propose argmax(draft_logits) per position and pass a one-hot draft_probs into the existing _rejection_sample (draft_indices=None). With q one-hot the accept test u * q < p reduces to u < p(token) and the residual max(p - q, 0) renormalized is the target distribution with the rejected token removed, i.e. the standard greedy-draft rejection scheme. The output distribution is exactly the target's; only the proposal changed. This is also what vLLM's DFlash proposer does.

temperature == 0 path and the DFlash 2 path are untouched. 10 insertions, 3 deletions.

Note

This changes sampled-mode behavior for every v1 head on the MLX backend (Qwen3 / Qwen3.5 / Qwen3.6 / Gemma 4 drafts), not just Muse. I only measured Muse; if you have a Qwen3 v1 head bench handy it is worth a look, but the argument above is not model-specific.

Independent of the Muse-Glimmer adapter PR (#168); either can land first.

…ne-hot

DFlash v1 draft positions are independent per-position marginals, so
sampling each block position separately produced an incoherent block
sequence the target rejected almost everything (0.45x, 1.16 tok/step
measured on the Meta head at T=1). Propose argmax instead and
rejection-sample against a one-hot proposal distribution, same as
vLLM's DFlash scheme and standard greedy-draft rejection sampling.
Target distribution is unchanged; only the proposal changes.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant