Acceptance metrics for DeepSeek-V4-Pro with the DSpark drafter

What each number measures, how it is computed from the raw evaluation files, and what the data shows. Compiled 2 September 2026 from DeepSeek-evaluations.zip.

Setup. Target DeepSeek-V4-Pro; drafter = the shipped DSpark head (DeepSeek-V4-Pro-DSpark), vLLM, TP8, fp8 KV cache, $K = 7$ speculative tokens per step, probabilistic draft sampling, temperature 1.0, chat mode, ≤ 2,048 new tokens, seed 980406.

Run A (7_draft): one response per prompt, 3,030 responses, 435,989 verify steps; aggregate counters only. Run B (7_draft_best_of_10): ten responses per prompt, 30,296 responses, 4,344,265 verify steps, with a per-step log (spec_log.csv: request id, drafted, accepted). Run B is the primary source; run A is used as a consistency check.

Datasets. gsm8k 500, math500 500, aime25 30 (math); humaneval 164, mbpp 256, livecodebench 500 (code); mt-bench 80, alpaca 500, arena-hard-v2 500 (chat).

1. Metrics and formulas

Notation: a run consists of responses $r = 1..N$; response $r$ takes $S_r$ verify steps; step $s$ drafts $K = 7$ tokens and the target accepts the first $a_s \in \{0,\dots,K\}$ of them, then emits one bonus (resampled or next) token. Total steps $S = \sum_r S_r$.

$$\text{tokens emitted at step } s = 1 + a_s, \qquad 1 \le 1 + a_s \le K{+}1 = 8$$ spec_log.csv: one row per step, columns (request_id, 7, a_s)

Step outcome. Every step yields between 1 and 8 tokens. All other metrics are functions of the multiset $\{a_s\}$. Because DSpark is a block drafter producing all 7 tokens in one pass, the per-step draft cost is fixed and $a_s$ alone determines the step's value.

$$\tau = \frac{\sum_s (1 + a_s)}{S} = 1 + \frac{\sum_s a_s}{S}$$ run A: acceptance_length = 1 + accepted / drafts
run B: 1 + mean of column 3 of spec_log.csv

Acceptance length, step-weighted. Tokens emitted per verify step, pooled over every step in a dataset. This is the throughput-relevant quantity: wall time is $S \times t_{\text{step}}$ and tokens produced is $S\tau$, so $\tau$ is exactly tokens per unit of step time. In a WAN pipeline where one step is one lap of the pipe, $\tau$ is tokens per lap and tok/s $= \tau / T_{\text{lap}}$.

$$\tau_r = 1 + \frac{1}{S_r}\sum_{s \in r} a_s, \qquad \bar\tau_{\text{resp}} = \frac{1}{N}\sum_r \tau_r, \qquad \tau = \frac{\sum_r S_r\,\tau_r}{\sum_r S_r}$$ run B: samples.jsonl accept_len (per response); results_table.txt alen_mean

Per-response acceptance length and its mean. $\tau_r$ is the acceptance length of one response; $\bar\tau_{\text{resp}}$ weights every response equally regardless of length. The step-weighted $\tau$ is the $S_r$-weighted average of the same $\tau_r$. The two differ whenever $\tau_r$ correlates with $S_r$: if long responses draft poorly, $\bar\tau_{\text{resp}} > \tau$. Use $\bar\tau_{\text{resp}}$ only for "what does a typical prompt experience".

$$\text{verify\_rate} = \frac{\tau}{K+1}, \qquad \text{acceptance\_ratio} = \frac{\sum_s a_s}{K\,S} = \frac{\tau - 1}{K}$$ run A results_table.txt: verify_rate
run B results_table.txt: ratio_max / ratio_mean / ratio_min

Two ratios that appear in the raw tables. They are different normalisations of $\tau$ and are not comparable with each other: verify_rate is the fraction of the $K{+}1$ verified positions that produced a token; acceptance_ratio is the fraction of drafted tokens that were accepted. Both are reported here as $\tau$.

$$p_i = \Pr(\text{position } i \text{ accepted}) = \frac{\#\{s : a_s \ge i{+}1\}}{S}, \qquad i = 0..K{-}1$$ run A: accept_rates_by_position[i] = per_pos[i] / drafts

Unconditional per-position acceptance. Probability that the $i$-th drafted token (0 = first) is accepted, counting every step. Because acceptance is prefix-based ($a_s \ge i{+}1$ means positions $0..i$ were all accepted), $p_i$ is non-increasing in $i$ and $\tau = 1 + \sum_i p_i$.

$$c_i = \Pr(\text{accept } i \mid \text{accepted } 0..i{-}1) = \frac{p_i}{p_{i-1}}, \qquad p_{-1} \equiv 1$$ derived from per_pos counters / step log

Conditional per-position acceptance. The drafter's hit rate at depth $i$ given it has survived so far — the closest thing to "quality of the $i$-th draft token". If $c_i$ were a constant $\alpha$ the outcome would be geometric; the data show $c_i$ falling with $i$.

$$P(a = j) = p_{j-1} - p_j \;\;(j \lt K), \qquad P(a = K) = p_{K-1}$$ run B: histogram of column 3 of spec_log.csv
run A: differences of per_pos

Step outcome distribution. Share of steps that accepted exactly $j$ draft tokens. Recoverable from the per-position counters alone, so it is available for both runs; the two agree to within a fraction of a percent.

$$\sigma_{\text{step}} = \sqrt{\sum_{j=0}^{K} P(a=j)\,\big(j - (\tau-1)\big)^2}$$ run B: std of column 3 of spec_log.csv

Step-level standard deviation. Dispersion of tokens-per-step around $\tau$, over individual verify steps. It is the natural spread to attach to the step-weighted $\tau$ (not the per-prompt spread), and it governs latency jitter when each step has a fixed cost.

$$P_\alpha(a=j) = (1-\alpha)\alpha^{j} \;(j \lt K), \quad P_\alpha(a=K) = \alpha^K, \qquad \tau(\alpha) = \frac{1-\alpha^{K+1}}{1-\alpha}$$ α solved numerically from τ(α) = observed τ

Constant-α (geometric) reference model. The classic chain model with the same acceptance rate at every position. The "implied α" in Table 1 is the α that reproduces the observed $\tau$; comparing $P_\alpha$ and $\sigma_\alpha$ with the observed distribution shows how far the drafter is from position-independent behaviour.

$$\tau(K') = 1 + \sum_{j=0}^{K} P(a=j)\,\min(j, K'), \qquad K' \le K$$ computed from the run-B outcome distribution

Implied acceptance length at a shorter block. Truncating each observed outcome at $K'$ approximates what $\tau$ would be with fewer speculative tokens, assuming the drafter's per-position behaviour is unchanged — reasonable for a block drafter, not for an autoregressive one whose later tokens depend on earlier draft context.

$$\operatorname{Var}(\tau_r) = \underbrace{\operatorname{Var}_q\big(\bar\tau_q\big)}_{\text{between prompts}} + \underbrace{\mathbb{E}_q\big[\operatorname{Var}(\tau_r \mid q)\big]}_{\text{within prompt}}$$ run B: 10 copies per prompt q; population variances

Variance decomposition (best-of-10 run). Splits the spread of per-response $\tau_r$ into prompt difficulty (between) and sampling noise at $T = 1.0$ (within). The "mean of max / min over copies" columns are the expected best and worst of ten draws for the same prompt.

2. Acceptance length

Row markers: math code chat

datasetfamilysteps (run B)τ run Aτ run Bstep stdper-response meanp10 / p50 / p90implied α
gsm8kmath191,1194.974.972.375.034.37 / 5.03 / 5.690.858
math500math499,6685.095.092.445.214.38 / 5.25 / 5.970.865
aime25math92,0764.414.452.434.573.68 / 4.65 / 5.380.822
humanevalcode46,1775.365.292.455.304.29 / 5.36 / 6.220.877
mbppcode398,3544.884.902.384.934.46 / 4.93 / 5.400.853
livecodebenchcode494,4004.144.122.395.073.76 / 5.09 / 6.290.796
mt-benchchat163,2203.113.152.063.702.33 / 3.42 / 5.590.700
alpacachat919,6642.852.841.843.202.30 / 2.85 / 4.810.661
arena-hard-v2chat1,539,5873.493.512.263.812.29 / 3.93 / 5.280.741
pooled4,344,2653.833.832.37——0.772

Runs A and B agree to within 0.05 on every dataset except the two smallest (aime25, humaneval), so the single-sample run was already converged at dataset level. Math and code sit at $\tau \approx 4.1$–$5.3$, chat at $2.8$–$3.5$; the pooled figure of 3.83 is chat-heavy (alpaca and arena-hard-v2 supply 57% of all steps).

Step-level standard deviation
Figure 1. Left: step-weighted $\tau$ with $\pm\sigma_{\text{step}}$. Right: observed $\sigma_{\text{step}}$ against the geometric model's $\sigma_\alpha$ at the same $\tau$. The observed dispersion is 0.1–0.3 tokens lower everywhere; the gap is largest on high-$\tau$ datasets where the geometric model puts 30–40% of its mass on the all-accepted outcome.
Response length vs acceptance length
Figure 2. Why $\bar\tau_{\text{resp}}$ and $\tau$ diverge. On livecodebench, $\tau_r$ falls steeply with response length ($r = -0.63$): long responses draft poorly and contribute most of the steps, so the per-response mean (5.07) overstates the step-weighted value (4.12) by almost a full token.

3. Acceptance probability per draft position

Unconditional $p_i$

datasetp0p1p2p3p4p5p6
gsm8k0.9120.8040.6760.5580.4470.3410.231
math5000.9050.8000.6840.5800.4760.3750.267
aime250.8640.7230.5840.4670.3630.2690.183
humaneval0.9060.8060.7150.6260.5310.4160.287
mbpp0.9020.7890.6670.5560.4450.3270.214
livecodebench0.8330.6740.5270.4100.3120.2210.139
mt-bench0.7460.5180.3400.2280.1530.1000.060
alpaca0.7180.4690.2850.1720.1030.0600.033
arena-hard-v20.7730.5710.4090.2960.2140.1490.095
pooled0.8040.6220.4670.3560.2670.1930.126

Conditional $c_i = p_i / p_{i-1}$

datasetc0c1c2c3c4c5c6c0 − c6
gsm8k0.9120.8810.8410.8260.8000.7640.6770.235
math5000.9050.8840.8550.8480.8220.7870.7130.191
aime250.8640.8360.8080.8000.7760.7430.6780.186
humaneval0.9060.8900.8870.8760.8490.7830.6890.217
mbpp0.9020.8750.8450.8340.7990.7350.6540.248
livecodebench0.8330.8090.7820.7780.7600.7090.6260.206
mt-bench0.7460.6940.6560.6710.6700.6520.6050.141
alpaca0.7180.6530.6070.6050.5980.5780.5520.166
arena-hard-v20.7730.7390.7150.7250.7210.6960.6360.136
pooled0.8040.7740.7520.7610.7520.7200.6550.149
Per-position acceptance
Figure 3. Unconditional (left) and conditional (right) acceptance by draft position. The first position separates the workloads ($c_0$ 0.90–0.91 math/code vs 0.72–0.77 chat). Conditional acceptance then falls by 0.16–0.25 to position 6 on every dataset: smoothly on math/code with the steepest drop at positions 5–6, and front-loaded on chat, which drops sharply over positions 0–2 and then plateaus near 0.60–0.72. The final-position dip is partly structural — steps that end a response cannot accept late positions — so $c_6$ is a lower bound on drafter quality at depth 7.

4. Step outcome distribution

Share of verify steps (%) by number of accepted draft tokens $a_s$; the last column is the fraction of steps that hit the $K{+}1 = 8$ ceiling.

dataset01234567
gsm8k8.810.812.811.811.110.511.023.1
math5009.510.511.610.410.310.110.826.7
aime2513.614.113.911.710.59.38.718.3
humaneval9.410.09.18.99.511.513.028.7
mbpp9.811.312.211.111.211.811.321.4
livecodebench16.715.914.711.79.89.18.313.9
mt-bench25.422.817.811.27.55.33.96.0
alpaca28.224.918.411.36.94.42.73.3
arena-hard-v222.720.116.311.28.36.55.49.5
pooled19.618.215.411.28.87.56.612.6
Outcome distribution heatmap
Figure 4. The same table as a heatmap. Math/code distributions are roughly flat with a spike at 7; chat distributions are front-loaded with 23–28% of steps accepting nothing.
Geometric model check
Figure 5. Observed $P(a=j)$ against the constant-α model matched on $\tau$. The observed distribution is flatter: fewer complete rejections (pooled 19.6% vs 22.8% predicted), fewer complete acceptances (12.6% vs 16.3%), more mass in between — the signature of conditional acceptance that decays with depth. Chain-cap arithmetic $1/(1-\alpha)$ therefore overstates the return from extending $K$.

5. Implied $\tau$ at shorter blocks

datasetK′=1K′=2K′=3K′=4K′=5K′=6K′=7gain 5→7
gsm8k1.912.723.393.954.404.744.97+0.57
math5001.902.703.393.974.444.825.09+0.64
aime251.862.593.173.644.004.274.45+0.45
humaneval1.912.713.434.054.585.005.29+0.70
mbpp1.902.693.363.924.364.694.90+0.54
livecodebench1.832.513.033.443.763.984.12+0.36
mt-bench1.752.262.602.832.993.083.15+0.16
alpaca1.722.192.472.652.752.812.84+0.09
arena-hard-v21.772.342.753.053.263.413.51+0.24
pooled1.802.432.893.253.523.713.83+0.32

Going from $K' = 5$ to $7$ buys +0.5–0.7 tokens per step on math/code but only +0.1–0.25 on chat; the seventh position alone adds 0.23–0.29 on math/code and 0.03–0.10 on chat. In a lap-bound pipeline the whole $\tau$ is what divides the lap count, so the extra depth is worth having on math/code and nearly free of value on chat.

6. Prompt difficulty vs sampling noise

datasetper-response stdwithin-prompt sharemean std over 10 copiesmean (max−min) over copiesmean of maxmean of mincorr(τr, length)
gsm8k0.5249%0.371.165.614.45-0.04
math5000.6225%0.310.985.704.71-0.08
aime250.6322%0.280.915.064.15-0.12
humaneval0.7643%0.491.516.034.53+0.20
mbpp0.3649%0.260.815.344.53-0.02
livecodebench0.9526%0.481.485.814.33-0.63
mt-bench1.276%0.270.834.123.29-0.21
alpaca1.0415%0.320.993.722.73-0.16
arena-hard-v21.175%0.230.714.173.46+0.12
Per-response distribution and variance decomposition
Figure 6. Left: distribution of per-response $\tau_r$ (violins) for the 10 copies × prompts of each dataset, with the step-weighted $\tau$ marked in black — the black marks are the values in Table 1. Right: share of $\operatorname{Var}(\tau_r)$ that is within-prompt, i.e. sampling noise across the 10 copies at $T = 1.0$. On math/code 22–49% of the per-response spread is sampling noise across copies of the same prompt, so prompt difficulty and noise contribute comparably; on chat only 5–15% is noise — prompt difficulty dominates (85–95%). Even so, ten resamples of one prompt move $\tau_r$ by 0.7–1.5 tokens end to end, so the "mean of max / min" columns describe a lucky or unlucky draw, not an operating point.

7. Upper bound on tokens per second in a 10-stage WAN pipeline

$$T_{\text{lap}} = N \cdot \frac{\text{RTT}}{2}, \qquad \text{tok/s} \le \frac{\tau}{T_{\text{lap}}} = \frac{2\,\tau}{N \cdot \text{RTT}}, \qquad N = 10$$ τ = step-weighted acceptance length (Table 1); RTT = per-hop round-trip latency, one-way = RTT/2

Latency-only bound. One verify step is one lap of the pipeline: the drafted block enters at stage 1, traverses all $N$ stages and the result returns to the drafter, so the lap costs $N$ one-way link traversals, each charged half the hop's RTT. Compute at every stage, drafting time, serialisation and bandwidth are all set to zero, so the numbers are ceilings: whatever a real system achieves must lie below them. The speed-up over an unspeculated pipeline (one token per lap) is exactly $\tau$ and is independent of RTT. At RTT = 25 ms the lap is 125 ms; at 100 ms it is 500 ms.

Single-stream tokens per second, $N = 10$ stages, one-way latency per hop, compute = 0:

datasetτRTT 10 msRTT 25 msRTT 50 msRTT 100 msRTT 200 msspeed-up vs no spec
gsm8k4.9799.439.819.99.95.04.97×
math5005.09101.740.720.310.25.15.09×
aime254.4589.135.617.88.94.54.45×
humaneval5.29105.842.321.210.65.35.29×
mbpp4.9098.039.219.69.84.94.90×
livecodebench4.1282.332.916.58.24.14.12×
mt-bench3.1562.925.212.66.33.13.15×
alpaca2.8456.822.711.45.72.82.84×
arena-hard-v23.5170.128.014.07.03.53.51×
pooled3.8376.730.715.37.73.83.83×
no speculation1.0020.08.04.02.01.01.00×

At 10 ms hops (a 50 ms lap) DSpark lifts the ceiling from 20 to 57–106 tok/s depending on workload; at 50 ms hops (a 250 ms lap) it is 11–21 tok/s; at 100 ms hops (a 500 ms lap) 5.7–10.6 tok/s, roughly reading speed on math/code and below it on chat; at 200 ms hops 2.8–5.3 tok/s. Because the bound scales as $1/\text{RTT}$, halving link latency is worth exactly as much as doubling acceptance length — and doubling $\tau$ from ≈5 to ≈10 is beyond what a $K=7$ chain can deliver (ceiling 8), which is the case for trees or wider blocks made in the laps-and-bytes note.

Tokens per second bound vs RTT
Figure 7. Left: the $2\tau/(10\cdot\text{RTT})$ ceiling as a function of per-hop RTT for each dataset (log–log; all lines have slope −1 and are separated only by $\tau$), with the unspeculated pipeline dashed. Right: the same ceilings at the five RTT values; dashed lines are the no-speculation ceilings at matching RTT.

8. Reading for the WAN-PP notes

Data provenance: request ids in spec_log.csv were assigned to datasets by position (ids are contiguous per dataset in run order, 10 per prompt) and validated against samples.jsonl with a 100% match on per-request draft and accepted counts. Four alpaca requests are absent from the log. Supporting CSVs: tableA_single_sample.csv, tableB_bon10_steps.csv, tableC_bon10_responses.csv, tableD_tau_vs_K_truncation.csv, tableE_step_level_std.csv, tableF_tok_per_s_pp10.csv, bon10_per_response.csv.