Qwen3.5-2B-DSpark-v2
A DSpark draft model for speculative decoding with Qwen/Qwen3.5-2B as the verifier, trained with speculators. The drafter proposes 8 tokens at a time and the verifier checks them in one forward pass, so greedy output is identical to running the verifier alone — a lossless speedup. At temperature 0, mean acceptance length is 3.77 tokens committed per verification step, up to 5.49 on math_reasoning. Compared with the verifier alone, throughput is 2.25× higher on average, up to 2.98× on math_reasoning and 2.87× on HumanEval, and it is the fastest configuration on all nine benchmark subsets, ahead of both the verifier's native MTP drafter and v1.
This is a smaller and faster successor to rasyosef/Qwen3.5-2B-DSpark: 4 layers instead of 5, about 0.3B parameters instead of 0.5B, trained on more data. It accepts slightly fewer tokens per step than v1 and is faster anyway.
Training code: rasyosef/train-dspark-draft-models.
Trained on 180,000 samples.
Usage
vLLM
vLLM loads the verifier automatically from the config — don't pass it separately.
vllm serve rasyosef/Qwen3.5-2B-DSpark-v2 --port 8000 \
--gpu-memory-utilization 0.8 \
--override-generation-config '{"temperature": 0}'
Then query the OpenAI-compatible endpoint at http://localhost:8000/v1.
To serve with the sampling settings used in the evaluation below, swap the last flag:
--override-generation-config '{"temperature":1.0,"top_p":0.95,"top_k":20}'
Details
4 Qwen3 layers (hidden size 2048, intermediate size 6144, 16 attention heads over 4 KV heads, head dim 128, all layers sliding-window attention with a 2048-token window), ~0.3B params, bfloat16. Block size 8, draft vocabulary reduced to 32,000 from the verifier's 248,320 (selected by token frequency over the training data), aux hidden-state layers 2/8/16/22, confidence head with Markov (vanilla, rank 256).
Trained for 3 epochs at lr 3e-4 (AdamW, cosine schedule with 4% warmup) on 180,000 filtered Open PerfectBlend, Ultrachat, and Nemotron prompts with responses regenerated by the verifier itself, split 96/4 into train and validation, with a {"ce": 0.1, "tv": 0.9} loss. Samples prepared at 2048 tokens; training sequence length 8192, up to 1024 anchors per sample. Verifier hidden states were pulled on demand from a running vLLM server during training and deleted after use rather than staged to disk up front.
Changes from v1
| v1 | v2 (this model) | |
|---|---|---|
| layers | 5 | 4 |
| KV heads | 8 | 4 |
| parameters | ~0.5B | ~0.3B |
| draft vocabulary | 50,000 | 32,000 |
| aux hidden-state layers | 1/6/11/16/21 | 2/8/16/22 |
| training samples | 100,000 | 180,000 |
| epochs | 4 | 3 |
| learning rate | 4e-4 | 3e-4 |
| weighted acceptance length (temperature 0) | 3.892 | 3.772 |
| average speedup over the verifier (temperature 0) | 2.00× | 2.25× |
Hidden size, intermediate size, attention heads, block size, loss and the rest of the training setup are unchanged.
Evaluation
Results are from evaluate.py throughput across the nine RedHatAI/speculator_benchmarks subsets, with acceptance measured at two settings: temperature 0 (greedy decoding), and sampling with {"temperature":1.0,"top_p":0.95,"top_k":20}. Throughput is reported at temperature 0 only. acceptance_length is mean tokens committed per verification step, including the bonus token — floor 1.0, ceiling 9.0 at block size 8. Rows are in the same order in every table, sorted by acceptance length at temperature 0.
Acceptance at temperature 0
| subset | acceptance_length | pos_0 | pos_1 | pos_2 | pos_3 | pos_4 | pos_5 | pos_6 | pos_7 |
|---|---|---|---|---|---|---|---|---|---|
| math_reasoning | 5.488 | 88.3% | 78.1% | 67.4% | 57.9% | 49.8% | 42.2% | 35.7% | 29.5% |
| HumanEval | 4.693 | 83.6% | 69.5% | 57.1% | 46.3% | 37.9% | 30.5% | 24.7% | 19.7% |
| rag | 3.857 | 78.9% | 60.1% | 45.8% | 33.9% | 26.3% | 19.0% | 13.2% | 8.5% |
| qa | 3.675 | 70.4% | 49.5% | 36.5% | 29.7% | 25.0% | 22.2% | 18.5% | 15.8% |
| tool_call | 3.360 | 70.8% | 49.6% | 35.4% | 26.1% | 20.0% | 14.9% | 11.1% | 8.2% |
| writing | 3.332 | 70.8% | 48.8% | 33.6% | 25.0% | 19.3% | 15.1% | 11.7% | 8.9% |
| question | 3.045 | 68.9% | 45.0% | 29.2% | 20.4% | 15.3% | 11.4% | 8.3% | 6.1% |
| translation | 2.516 | 68.1% | 41.4% | 23.8% | 10.8% | 4.1% | 2.0% | 1.0% | 0.5% |
| summarization | 2.483 | 64.7% | 37.2% | 20.5% | 11.9% | 7.2% | 3.8% | 2.0% | 0.9% |
Weighted across all subsets: 3.772 over 118,426 verification steps. math_reasoning and HumanEval are highest, and with qa they are the three subsets that still accept more than 15% of drafts at pos_7. translation and summarization are lowest and fall below 1% by pos_7.
Acceptance with sampling
Same benchmark with {"temperature":1.0,"top_p":0.95,"top_k":20}.
| subset | acceptance_length | pos_0 | pos_1 | pos_2 | pos_3 | pos_4 | pos_5 | pos_6 | pos_7 |
|---|---|---|---|---|---|---|---|---|---|
| math_reasoning | 4.265 | 76.7% | 61.0% | 48.4% | 39.8% | 32.6% | 26.9% | 22.6% | 18.5% |
| HumanEval | 3.352 | 68.3% | 49.2% | 36.3% | 27.1% | 20.2% | 15.0% | 11.0% | 8.1% |
| rag | 2.565 | 60.8% | 37.2% | 23.0% | 14.8% | 9.7% | 5.7% | 3.3% | 2.1% |
| qa | 2.239 | 53.6% | 29.5% | 16.6% | 10.2% | 6.5% | 3.8% | 2.3% | 1.5% |
| tool_call | 2.642 | 59.2% | 36.2% | 23.5% | 16.3% | 11.6% | 7.9% | 5.6% | 3.9% |
| writing | 2.609 | 58.3% | 34.8% | 22.2% | 15.4% | 11.3% | 8.4% | 6.1% | 4.5% |
| question | 2.617 | 58.3% | 34.4% | 22.0% | 15.6% | 11.7% | 8.9% | 6.3% | 4.5% |
| translation | 2.406 | 65.3% | 37.5% | 20.3% | 10.1% | 3.8% | 1.9% | 1.1% | 0.5% |
| summarization | 2.067 | 51.8% | 26.1% | 13.5% | 7.4% | 4.1% | 2.1% | 1.1% | 0.5% |
Weighted across all subsets: 2.868 over 173,922 verification steps, against 3.772 at temperature 0. Acceptance length is lower on every subset. The drop is largest on qa (3.675 to 2.239) and HumanEval (4.693 to 3.352), and smallest on translation (2.516 to 2.406). math_reasoning stays highest at 4.265. Acceptance at pos_7 is under 5% on every subset except math_reasoning (18.5%) and HumanEval (8.1%).
Throughput at temperature 0 (tokens/s)
Mean output throughput with a single concurrent request. Baseline is Qwen3.5-2B with no speculative decoding, and MTP is the verifier's native MTP drafter at 4 and 8 draft tokens; the baseline, MTP and v1 columns are the figures reported on the v1 card, measured on one A100. The fastest configuration in each row is bolded. The last column gives this model's throughput divided by baseline throughput for each subset.
| subset | baseline (no drafter) | MTP (4 draft tokens) | MTP (8 draft tokens) | DSpark v1 | DSpark v2 (this model) | v2 speedup |
|---|---|---|---|---|---|---|
| math_reasoning | 233.4 | 410.1 | 357.0 | 671.8 | 695.4 | 2.98× |
| HumanEval | 233.5 | 412.8 | 376.4 | 612.2 | 670.4 | 2.87× |
| rag | 221.5 | 401.2 | 373.3 | 499.5 | 542.3 | 2.45× |
| qa | 228.7 | 386.7 | 311.4 | 472.9 | 563.7 | 2.46× |
| tool_call | 224.5 | 360.5 | 376.2 | 560.4 | 571.5 | 2.55× |
| writing | 233.0 | 345.1 | 229.4 | 365.3 | 470.7 | 2.02× |
| question | 231.6 | 345.4 | 229.3 | 359.7 | 471.3 | 2.03× |
| translation | 168.4 | 196.6 | 152.9 | 188.1 | 215.6 | 1.28× |
| summarization | 219.5 | 293.8 | 220.5 | 316.6 | 350.6 | 1.60× |
| average speedup | 1.00× | 1.57× | 1.31× | 2.00× | 2.25× | 2.25× |
This model has the highest average speedup at 2.25× (unweighted mean of per-subset speedups), ahead of v1 (2.00×), MTP at 4 draft tokens (1.57×) and MTP at 8 (1.31×), and it has the highest mean throughput on all nine subsets. The gains are largest on math_reasoning (2.98×), HumanEval (2.87×) and tool_call (2.55×), and smallest on summarization (1.60×) and translation (1.28×).
Against v1, mean throughput is higher on every subset, by 2% on tool_call and 4% on math_reasoning up to 29% on writing and 31% on question. Translation, where v1 trailed MTP at 4 draft tokens, is now ahead of it on mean throughput (215.6 against 196.6).
Median throughput is close to the mean on math_reasoning (683.4) and HumanEval (666.9). It is well below the mean on qa (423.6 against 563.7) and on translation (90.6 against 215.6); translation is the smallest subset, with fewer than 1,000 verification steps.
Acceptance comparison with MTP and v1
Acceptance length at temperature 0 for this model, v1 and the verifier's native MTP drafter on the same subsets. MTP and v1 figures are from the v1 card. The highest value in each row is bolded and named in the last column. At 4 draft tokens the ceiling on acceptance_length is 5.0 rather than 9.0.
| subset | MTP (4 draft tokens) | MTP (8 draft tokens) | DSpark v1 | DSpark v2 (this model) | best |
|---|---|---|---|---|---|
| math_reasoning | 3.832 | 4.743 | 5.405 | 5.488 | DSpark v2 |
| HumanEval | 3.785 | 4.862 | 4.766 | 4.693 | MTP (8 draft tokens) |
| rag | 3.812 | 4.844 | 3.986 | 3.857 | MTP (8 draft tokens) |
| qa | 3.408 | 4.227 | 4.074 | 3.675 | MTP (8 draft tokens) |
| tool_call | 3.309 | 4.041 | 3.619 | 3.360 | MTP (8 draft tokens) |
| writing | 3.054 | 3.281 | 3.107 | 3.332 | DSpark v2 |
| question | 3.062 | 3.379 | 3.299 | 3.045 | MTP (8 draft tokens) |
| translation | 2.873 | 3.115 | 2.527 | 2.516 | MTP (8 draft tokens) |
| summarization | 2.695 | 3.018 | 2.548 | 2.483 | MTP (8 draft tokens) |
| weighted | 3.398 | 4.106 | 3.892 | 3.772 | MTP (8 draft tokens) |
MTP at 8 draft tokens has the highest acceptance length on seven of the nine subsets and on the weighted average. This model is highest on math_reasoning (5.488) and writing (3.332). MTP's lead over it is widest on rag (4.844 against 3.857) and narrowest on HumanEval (4.862 against 4.693). Against MTP at 4 draft tokens, this model is higher on six subsets and lower on question, summarization and translation.
Against v1, acceptance length is lower on seven subsets, most on qa (4.074 to 3.675), and higher on math_reasoning and writing. The weighted average goes from 3.892 to 3.772.
This model is faster than both v1 and MTP at 8 draft tokens on every subset while accepting fewer tokens per step than each of them on seven, which points to a cheaper draft-and-verify step rather than better drafts as the source of the gain.
Limitations
Works only with Qwen3.5-2B and is not usable as a standalone model. The verifier is vision-language, but the drafter was trained on text-only prompts and was evaluated on text-only benchmarks, so acceptance on image inputs is untested. All results are for a single concurrent request; throughput under load is not reported. With sampling at temperature 1.0, weighted acceptance length falls from 3.772 to 2.868; throughput with sampling is not reported. The verifier's native MTP drafter at 8 draft tokens has a higher acceptance length on seven of the nine subsets, though lower throughput on all nine, and v1 has a higher acceptance length on seven. Acceptance at the last draft position at temperature 0 is under 1% on summarization and translation and under 10% on rag, tool_call, writing and question, so a block size of 8 is partly wasted there; with sampling it is under 5% on seven subsets. The throughput mean on translation rests on a small sample and is far above its median. Real-world speedup depends on your traffic mix, and because verification is lossless, the verifier's own behavior and biases carry through unchanged.
License
Apache 2.0, inherited from the verifier. The speculators training code is Apache-2.0.