exact verifier
Exact verifier: the speculative-decoding accept/reject step in numpy
sideband · folder
6 files, 29146 bytes; MIT licence.
Contents: spec_step; run_block; residual_distribution; analytic_acceptance; StepOutcome; BlockOutcome; RunMetrics.
Tests of this copy: 24 passed
How to use this tool
A speculative decoder lets a small draft model guess the next tokens and a large model check them. This is the checking rule: it keeps or replaces each guess so that the text that comes out follows the large model's own probabilities exactly, whatever the draft guessed. The tests prove that by counting through every outcome.
- Copy the command under Get this folder, run it, then run the tests to see the rule hold.
- In your code, import
spec_stepfromsideband.specdec. Give it a numpy random generator, then the large model's probabilities, then the draft's, for one position over the same vocabulary. - It returns a
StepOutcome: the token the draft proposed, whether it was kept, and the token that came out. - For a block of several guesses use
run_block, with one more large model distribution than draft distributions; the extra one gives a bonus token when every guess is kept. - If you write a faster version, make these tests pass against it before you trust it.
A numpy implementation of the exact speculative-decoding accept/reject step (Leviathan et al. 2023) with tests that check by enumeration that the emitted token follows the target distribution for any draft distribution; for researchers building or changing speculative decoders.
Get this folder
One command makes a new folder named exact-verifier inside the folder your terminal is in. It changes nothing else, joins no project and installs nothing. Paste it into bash, zsh or PowerShell with Python on the path; where python is not found, change the first word to python3. It downloads the 6 files listed below from the repository at tag v1.0.0, checks each against its full sha256, writes nothing unless every one matches and the folder is new, and adds the pytest.ini the tests run under. The tests need numpy and pytest: pip install numpy pytest, then cd exact-verifier and python -m pytest.
Show the command
python -c "
import hashlib, pathlib, urllib.request
base = 'https://raw.githubusercontent.com/Mike-Byrne-AI/specdec-sidechannels/v1.0.0/'
out = pathlib.Path('exact-verifier')
files = [
('LICENSE', 'LICENSE', '8497cbc80c24245fc8f9be355fca4a8d15b0235b7de4870b30d573189092aeef'),
('src/sideband/__init__.py', 'sideband/src/sideband/__init__.py', 'b3123882e5c63944e9ecadcf31126ddbd513be73b9829ae89ee095dca685946f'),
('src/sideband/dists.py', 'sideband/src/sideband/dists.py', 'a8fb156eff2141061fa7b7d1ae61de364797aebb77acf7a7425f25fb7423e280'),
('src/sideband/specdec.py', 'sideband/src/sideband/specdec.py', '80502d0f5695a56f650aa1d166afaa7b34683628480bed703b8fd34f4640c65d'),
('src/sideband/steering.py', 'sideband/src/sideband/steering.py', '3271311b2303ba317036f01ca581a16da00bb22598eefd65e65d50a6b55ffff7'),
('tests/test_specdec.py', 'sideband/tests/test_specdec.py', '4791d46cc47cdf1c3d55623e7d6b203908375fff7fbdc136112c0348aff63ca2'),
]
if out.exists():
raise SystemExit(str(out) + ' already exists: nothing written')
got = []
for dest, src, sha in files:
data = urllib.request.urlopen(base + src).read()
if hashlib.sha256(data).hexdigest() == sha:
got.append((out / dest, data))
else:
raise SystemExit(src + ': its sha256 is not the one on the page: nothing written')
for path, data in got:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(data)
(out / 'pytest.ini').write_bytes(chr(10).join(['[pytest]', 'testpaths = tests', 'pythonpath = src', '']).encode())
print('checked and wrote', len(got), 'files to', out.resolve())
"In the record
In the record this file is the single implementation of accept, reject and residual (DECISIONS.md D-3: the real-model adapter converts logits to numpy and calls spec_step, and anyone re-implementing the verifier for speed must first make these numpy tests pass against their implementation). Its docstring states the property the tests check by enumeration: for any draft distribution, steered or not, the emitted token is distributed exactly as the target distribution, so steering can only change speed, never output quality.
Use
- Copy src/sideband/ into your project, or vendor specdec.py and dists.py together (specdec imports normalize, sample and tv_distance from dists).
- steering.py is here only because the test file uses its bucket_bias; it is not needed to call spec_step.
- Run
python -m pytestfrom this folder: pytest.ini points it at the copied tests and this folder's src/.
Good to know
- Per-step acceptance is analytically 1 - TV(p, q), and that identity is tested too.
- The docstring names the record's real-model adapter (sideband.real.hf_specdec, not copied) and the test file, which is copied here.
The 6 files, each linked to the same file at v1.0.0
| Module path | Public file at v1.0.0 | sha256 | Bytes |
|---|---|---|---|
| LICENSE | LICENSE | 8497cbc80c24 | 1070 |
| src/sideband/__init__.py | sideband/src/sideband/__init__.py | b3123882e5c6 | 87 |
| src/sideband/dists.py | sideband/src/sideband/dists.py | a8fb156eff21 | 2115 |
| src/sideband/specdec.py | sideband/src/sideband/specdec.py | 80502d0f5695 | 7210 |
| src/sideband/steering.py | sideband/src/sideband/steering.py | 3271311b2303 | 6217 |
| tests/test_specdec.py | sideband/tests/test_specdec.py | 4791d46cc47c | 12447 |