Repository navigation
spec : --spec-select, the draft with the most expected tokens per time - #47
Merged
Merged
Conversation
With several --spec-type the first drafter that has a draft wins: an n-gram draft of copied text makes copy-heavy answers much faster, and other answers slower where its drafts are rejected (a hybrid model pays a checkpoint restore and a replay for every partial acceptance). With --spec-select each step chooses per sequence between its n-gram draft (truncated to the best length), the model drafter's draft, or none: - acceptance per draft position (decayed hits and trials per position bucket), learned per sequence, also from n-gram drafts that were not used: they are compared with the text that follows; - step times per number of verified tokens, learned from steps of one pass; a batch whose sequences verify different numbers of tokens takes one pass per length (ubatches of recurrent and hybrid models), the model drafter's time separately; - the choice maximizes the sum over the step's sequences of log(tokens / step time), and no sequence may get more than 10% slower than with every one on the model drafter. Qwen3.8 27B, MTP depth 2 with the draft vocabulary, ngram-simple,draft-mtp: - one slot: German docker-compose edit 74 -> 101 t/s (temperature 1.0), 80 -> 105 (greedy); code edit, German letter, English explanation as MTP alone - two slots at once (compose + explanation): as MTP alone (with n-gram first both slots were slower, without the limit the explanation lost 17%) Idea after Strata by @Niko1221 (MIT). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed drafts as the text comes Two gaps in how the chooser learned the acceptance of n-gram drafts: - A draft cut to the length its learned acceptance paid for only taught the positions it verified, so positions beyond the cut kept their prior (0.5 per position) and the chooser never saw that longer drafts of copied text would pay. The cut-off part is now compared with the text that follows, like an unused draft, for the positions after the cut. - An unused draft taught nothing until the text had passed it or left it: a 48-token draft of copied text took ~20 steps, during which the estimate stayed at its prior and the steps stayed on MTP. Its positions are now learned as the text reaches them. Qwen3.8 27B, one slot, ngram-simple,draft-mtp, 4 requests per task in a row (median): docker-compose edit 78 -> 123 t/s at temperature 1.0 and 79 -> 125 greedy against MTP alone, code edit 70.8 -> 71.0 / 77.0 -> 75.7, German letter 48.0 -> 47.0 / 55.1 -> 54.9, English explanation unchanged; two slots as MTP alone. With 2 requests per task the change was not measurable (the choices depend on measured step times, runs differ by up to 10%). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rafts, empty model drafts, clean step times Review of #47 (all four only cost speed, the target verifies every draft): - After a checkpoint restore (hybrid models) the replay reports one accepted token more to common_speculative_accept (MTP needs it for the row of its hidden state), and the selector learned the first rejected position as a hit. The selector now learns from common_speculative_verified(), which the server (and speculative-simple) call once per draft at its verification, before a restore, with the true count. - A draft cut by the choice and accepted up to the cut was reported to its drafter as its own outcome: ngram-mod read 3 of 3 of a 32-token draft as a low acceptance and reset its shared table every 5 such steps, ngram-map-k stored the cut length as the key's draft length for good. Such a step now tells the drafter nothing (is_other). - When every drafting sequence took its n-gram draft the model drafter was still called without work: its time decayed toward 0 in t_model (5.5 ms -> 13 us over 22 steps), and draft-simple decoded an empty batch with an error. The model drafter is skipped then. - Step times were learned from batches that held more than the step's drafts (another slot's prompt tokens or replays) or ran next to a prompt of the background context (--concurrent-prefill), and from the restore and replay of a partially accepted draft: up to 5-45x the time of a clean step, in a bucket the chooser then avoided. A step's time is now learned only when its batch held exactly the drafts of its sequences and nothing computed alongside, measured at the verification (before a restore). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # README.md
Owner
Author
|
Review fixes in c37bca8, then main (#46) merged in (8b87d64, README rows only):
🤖 Generated with Claude Code |
This was referenced Oct 20, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #37 (combining drafters, after the choice between prompt lookup and MTP in Strata by @Niko1221, MIT).
With several
--spec-type(e.g.ngram-simple,draft-mtp) the first drafter that has a draft wins today. An n-gram draft of copied text makes copy-heavy answers (a config file or code given back with a few edits) much faster, but where its drafts are rejected it makes answers slower: a hybrid model pays a checkpoint restore and a replay for every partial acceptance, so a code rewrite lost 9-15%.--spec-selectchooses per step and sequence between the n-gram draft (cut to its best length), the model drafter's draft, or none:Without the flag nothing changes.
Results
Qwen3.8 27B UD-Q4_K_S, 4070 + 3060,
-sm tensor, MTP depth 2 with the draft vocabulary (#36), production sampling (temperature 1.0) / greedy; one slot, 4 requests per task in a row (median):ngram-simple,draft-mtp --spec-select(After the review fixes; before them: compose 122.9 / 125.3, the rest the same.) In the production-like concurrent prefill test the compose edit ran at 119 and 127 t/s, the second one next to a 5.5k-token prompt of the other slot.
Review fixes (c37bca8): the selector learns a draft's outcome at its verification (
common_speculative_verified, before a checkpoint restore whose replay reports one token more), a draft cut by the choice and accepted up to the cut no longer counts as its drafter's own outcome (ngram-mod reset its shared table, ngram-map-k shrank its drafts), the model drafter is not called when every sequence took its n-gram draft (its time decayed toward 0), and step times are learned only from batches that hold exactly the step's drafts with nothing computed alongside.Debug output (
-v): onechoose:line per step with the candidate, the chosen length, the expected tokens of both drafts and whether the n-gram draft was taken.🤖 Generated with Claude Code