Repository navigation
Releases
v1.34.0 - fboudra's code-quality pass, and the security fix that was never published
Thanks to @fboudra for PR #6: ruff format/lint at line-length 100, pre-commit, a CI checks job, bandit security scanning, and three genuine file-handle leaks closed (json.load(open(f)) in recipes.py leaked a descriptor on every recipe load).
requires-python is now >=3.11 (was >=3.9). Python 3.10 reaches EOL in October 2026; Debian 12 oldstable already ships 3.11. On an older interpreter pip resolves to v1.33.x.
This release also carries v1.33.0 and v1.33.1, which were changelogged but never tagged or published. Upgrading from 1.32.0 delivers these for the first time:
- Security: a spawned
llama-serveris pinned to--host 127.0.0.1instead of inheriting llama.cpp's default. llama.cpp's server starts with CORS*and no API key, so an inherited0.0.0.0would put an unauthenticated LLM endpoint on the user's LAN. An explicit--extra "--host 0.0.0.0"still wins. probe --evaldefaults toautoand fetches WikiText-2 itself, instead of requiring a corpus the README never located.
Full notes: CHANGELOG.md
v1.28.2 - hotfix: 1.28.1 was broken on GPU-less machines
If you installed 1.28.1, upgrade. pip install -U quantprobe
1.28.1's AMD refactor wrapped the non-NVIDIA detection branches in a guard with no else, so a machine with no GPU at all fell through every arm: detect() returned hardware with no vram/vram_bw keys and printed no GPU: line, and None propagated downstream — the same failure mode issue #1 reported. Every CPU-only user of that release was affected; no GPU user could be.
detect()now always settlesvram/vram_bwand always emits exactly oneGPU:line. The empty case falls through the sameelseas every other dead end, which is what the pre-refactor code did.- The regression test stubs all three probes empty in-process, so the no-GPU path is exercised on GPU machines too — and it was verified against the actual released 1.28.1 file rather than an imitation of the bug: it fails there, passes here.
How it got out. The full suite ran green locally before the release, and this development box has an NVIDIA card, so the broken branch was unreachable here. CI — which runs on GPU-less runners — caught it on four tests within minutes, but the tag and the PyPI upload had already gone out in the same sequence as the push. The rule that follows, and that this release is the first to obey: CI green is a release gate, not a formality that runs after the upload.
None of this is @fboudra's doing — the AMD detection in 1.28.1 is good work and stays exactly as it is. The guard was a merge-time hole that our review and our local suite both missed, and the fix belongs to us.
v1.28.1 - AMD GPU detection (first external contribution)
AMD GPUs are detected, not guessed at — and the patch came from outside the project.
@fboudra built the rocm-smi path end to end and validated it on an RX 9070 XT: PR #4, closing issue #2. First external code contribution quantprobe has received.
rocm-smidetection (Linux, amdgpu): name, VRAM, sclk/mclk, temperature and the supported-frequency ceiling, through a pure parser that is testable without a GPU — the same convention the Windows registry parser follows.detect()tries NVIDIA first, so no existing machine changes behaviour.calibrateworks on AMD:gpu_state_amd()returns the identical dict shape, so ClockSampler, the boost verdict and the calibration state id needed no changes at all.audit-ollamacan verify a clean GPU on AMD, and the stuck-boost advice now namesrocm-smi --showclocksalongside the NVIDIA command.- Five parser tests shipped with the patch; full suite green on the merged tree before merge.
One follow-up of ours, disclosed: the AMD fallback collapsed unload()'s two failure modes into one return, which made the "ollama is still holding the GPU" refusal unreachable — a working nvidia-smi plus a squatting ollama would have reported an unreadable GPU and sent the user to fix the wrong thing. Contention reporting is a measurement-discipline surface here, so the tristate is restored and pinned by a test that fails if the distinction collapses again (mutation-checked).
pip install -U quantprobe
Running an AMD card? quantprobe bench --gguf <model> --contribute would put the first AMD row in the hardware atlas — and a miss on RDNA4 is worth more to us than a hit, because misses are published at the same size as hits.
v1.28.0 - hybrid linear-attention priced correctly, Qwen3.8 in the atlas, Linux CI
The planner now prices hybrid linear-attention models correctly - two days after the class shipped.
Qwen3.8-27B landed 2026-08-14 with 48 of its 64 layers as linear attention; every prior model this tool had met was full-attention throughout.
- KV priced on full-attention layers only (U-51, staked as prereg #101 P-5 before measuring). The old formula assumed every layer caches K+V with position - a measured 4x over-estimate on the hybrid (260 KB/pos read, ~64 real). The count now comes from the file: a block carrying an
attn_kprojection caches K+V. Full-attention models byte-identical (regression-pinned); hybrids printKV 68 KB/pos (hybrid: 17 of 65 layers cache KV). - Recipes atlas: Qwen3.8-27B added - the first measured depth-aware band published for it, probed launch-day+1 (fragile band 51-64, back-fragile).
- Linux end-to-end CI - a GPU-less ubuntu runner asserts
calibrateexits cleanly with no GPU (the exact issue #2 failure class), then runs a real llama-bench andplan --gguf. Green on first run. AMD/Vulkan detection lands as v1.28.1 with the contributed patch. - The receipt: predicted 1.80 tok/s for Qwen3.8-27B on a 2016 GTX 1060 before the model generated a token; measured 2.04 +/- 0.02. Both logs committed.
- Also since 1.27: the quant-quality campaign page (docs/QUANT_QUALITY.md) and prereg #102's honest negative (effective rank does NOT predict the fragile band - the probe stays).
pip install -U quantprobe
🤖 Generated with Claude Code
v1.26.2 - install this one
Fixes bench --contribute sending the machine as None under auto-detect - the payload now carries the same resolved hardware the prediction used, guarded with the exact failing shape. Found by a pre-launch gauntlet walking the exact commands a new user runs, on the clean index-installed package. All v1.26 features: see v1.26.1 notes.
v1.26.1 - the batching release
Install: pip install -U quantprobe (1.26.1 supersedes 1.26.0, whose wheel misreports its version string - functionally identical, see CHANGELOG.)
Since 1.25.0, all measured on the reference box and staked before measurement:
- C-06 overturned: the "2x batching ceiling" was our own sweep stopping at 8 streams. A GTX 1060 serves 32 concurrent 7B streams at 219 aggregate tok/s (9.5x single-stream); the jump sits exactly at llama.cpp's mat-vec width cap.
- U-39 confirmed as staked: batching does NOT survive expert offload (2.0x cap) - so the best model inverts with user count: 1 user -> 30B MoE; 32 users -> dense 7B, 219 vs 40 aggregate.
plannow prints both halves as placement-gated serving advice. - X-1: speculation's draft length is a kernel decision - drafts of 4-7 are strictly dominated on pre-Ampere (48-51 tok/s) vs m>=8 (88.5-132.1). Up to 5.8x single-stream on copy-heavy work, byte-identical output. The advisory ships in
plan. - Business validation: the recommended 2.5-bit 30B scored 40/40 machine-checked tasks against a pre-staked bar; a four-model capability ladder (52 executable predicates, T4 designed to fail today's models) ships in the repo.
- A2A, staked: depth-aware vs uniform Q2_K at equal bytes (+0.48%): -13.2% perplexity, -39.5% median KLD, +5.1 pts same-token, +6.6% tok/s - with the speed-invariance miss published as a miss.
- Two corrections of our own published numbers against primary sources (E-12 byte model; the Gemma-26B "C-02 violation" dissolved by its own GGUF header), prereg #92 killed by its own gates, probe workdir/exit-code fixes, 154 tests.
Every claim links to a pre-registration with its verdict - hits and misses at the same size.
v1.24.0 — three defects that were live, and a disk tier we measured and missed
Three defects were live in 1.23.0. One of them could only ever make the tool look cautious.
pip install --upgrade quantprobeThe one worth upgrading for
upgrade_advisor built its counterfactual by copying the baseline and overriding one resource — but it dropped n_layer and true_size_gb on the way in. evaluate() re-derived both from presets, so the thing being priced was not your model with more RAM. It was a different model with more RAM.
The error is one-directional: it could only ever suppress good upgrades, never invent bad ones. So every symptom looked like the tool being conservative. If it told you "more RAM won't help," it may simply have been mis-pricing the question. 31 of 340 grid cells.
Also fixed:
- The speculation block printed a multiplier the row could not reach — 17 of 127 cells, true bound 1.025–1.229× against a printed 2.10×.
- A
+73%prefill figure was quoted flat on every row, including all-in-VRAM rows where the same flag measured −39%. And it ignored which ubatch was actually emitted, so a 3 GB card sized to-ub 1024(measured +38.7%) was told +73%. - Partial calibration printed the same "calibration applied" line as a complete one — while measuring 12.5% median error against 8.8% for the fully-preset baseline. Worse than no calibration, presented identically.
- The disk probe took one sample and asked you to spot the bad ones. Its docstring said "treat a number above ~1.5 GB/s as evidence of a warm cache." Measured: with 73% of a file warmed, 6 of 8 draws returned RAM speed (max 2.854 GB/s — a 6.3× error), and 1 in 8 even after deliberate eviction. It now takes the minimum over N disjoint regions.
The disk tier: measured for the first time, and we missed
Every previous release validated against 14 ladder rows, all VRAM- or RAM-resident. Zero touched the disk tier. A component no validation row reads can stay wrong indefinitely.
So we staked a prediction and measured it:
| predicted | 0.332 tok/s |
| measured | 0.476 tok/s |
| error | −30.4% — outside our own band |
The law is pessimistic about streaming from disk. We have not repriced it, because one datapoint is not a coefficient.
What the miss cost to chase, in order: the access-pattern explanation was refuted (scattered 0.452 vs contiguous 0.459 — and the same experiment independently confirmed the corrected disk calibration). The byte deficit is real but over-explains the speed-up by 1.84×, so two errors are partially cancelling. A per-fault latency mechanism was staked, appeared to confirm at r²=0.9999, and was withdrawn — fault counts were derived from byte counts, making "per-fault latency" and "lower throughput" the same equation in different units.
The disk tier ships disclosed as 30% pessimistic rather than quietly fitted.
What is new
- Layer-by-layer streaming placement — one layer resident, the rest streaming, so VRAM scales with layer size instead of model size. Shown but never selected as the winner: its number is an upper bound with two named unpriced terms.
- KL divergence as a quality delta. Perplexity called a Q2_K regression "23% worse." The model picks a different token on 27.4% of positions. llama.cpp was already computing this on the passes we ran; we were discarding it.
- Every cited evidence file is now in the repository, and a gate enforces it. The register cited 109 paths; 37 were missing. For a project claiming every number is re-derivable, an unverifiable citation is the worst defect available — it looks like rigour and isn't.
Refutations this cycle
Eight, five of them our own claims, including two sub-noise-floor "improvements" I announced and retracted, a per-fault mechanism I staked and withdrew, and a "damage hides in the tail" framing the data corrected — the tail wasn't special; KL beats perplexity at every percentile.
Full ledger: FINDINGS.md · preregistrations · CHANGELOG
Still not validated
The disk tier's 30% pessimism, the 1.82× streaming-efficiency gap between llama.cpp and raw reads, expert-usage skew (inferred by elimination, never observed), and one ladder row — gemma4-12B — that returned 13.23 / 12.25 / 15.62 across three passes and should not be cited until diagnosed.
All stated in the changelog at the same size as the wins.
v1.23.0 — the feature we tested and did not ship
A feature we promised, tested, and did not ship - plus the finding that replaced it.
We told an external reporter (E-08, RTX 5070) that this release would turn the all-in-VRAM
FLOOR into a point estimate, using the 61 public benchmarks we had collected. Pre-registration
#72 staked that with their measurement as the holdout. It failed its own gate and does not
ship. On one basis (efficiency = tok/s x file bytes / spec bandwidth) the public corpus spans
0.512-0.812 across 8 GPU architectures - and our 2016 Pascal card measures 0.509-0.577, INSIDE
that range. Their box sits at 0.810: the population maximum. Fitting a constant until their
number landed in band would have been the exact failure C-02 taught us to refuse.
- L-18 (new law): the all-in-VRAM spread is a property of the POPULATION, not of our old
GPU and not of any architecture. 1.6x wide, irreducible from public data, collapsed only by
measuring the specific machine. The floor advice now cites those 61 benchmarks as evidence
and points atcalibrateas the concrete fix instead of apologising. - U-23 (shipped, with its limit stated):
--no-mmapis no longer unconditional on expert
splits. Above 75% of the usable RAM pool the emit keeps mmap so pages stay evictable, and
says why - naming the +13.7% decode it is giving up. Honest limit, in the register: the gate
reasons about model share, so it does NOT catch the reporter's own case (their 330 MiB free
came from other processes and the mapped file). Reading actual available memory is U-24. - The mark: quantprobe has an icon - old-style pixel art, one 12x12 bitmap that generates
both the SVG and the terminal banner. Barequantprobenow prints it (with plain-text
fallbacks for pipes, NO_COLOR, and legacy Windows consoles). - Register at 92 entries: E-08 (the first out-of-sample validation on hardware we do not own -
58.1 predicted vs 54-57 measured), E-09 (rabbit: disk-tier bandwidth-indifference), L-18,
U-23 closed, U-24 opened.
v1.22.0 — the IQ ladder priced in, and native MTP breaks the MoE-speculation drought
The IQ ladder priced in, and the speculation map's first version qualifier.
- IQ formats are measured, not guessed (prereg #70): FORMAT_EBW gains IQ2_XS 51.1 / IQ3_S
61.1 / IQ3_XXS 68.3 / IQ4_NL 117.0 - the divide is CODEBOOK vs not, and IQ4_NL's kernel is
Q4_0-class. The format advice now offers IQ4_NL (+14% over Q4_K_M at the same size class WITH
imatrix quality) and warns off codebook IQ for VRAM decode on pre-Ampere. The staked split-arm
retrodiction MISSED and is published with its diagnosis (U-19 refuted as hypothesized; the
residual is structural, U-20 - which now also carries public out-of-sample support from a
four-point residency curve on RDNA3). - Native MTP is the first positive MoE-split speculation (prereg #71): models with a
trained-in MTP head (Qwen3.6 class) measure +11.4% at --spec-draft-n-max 2 (93.2%
acceptance) on the expert-split placement where every external draft loses. K MUST stay at 2:
K=4 measured 0.61x on the same pair - the expert-union tax is alive, the head just out-accepts
it at short drafts. speculation_advice prints the exception with its limits. - Register at 86 entries: E-07 (colibri cross-engine confirmations), the 61-entry public
benchmark corpus + audit script ship in-tree (weights/public_bench_audit.py), and the
draft-note %% display fix.
v1.21.0 — the dense-split release: +33.5% from a CPU-resident draft, three defects closed
The dense-split release: speculation's best cell shipped as advice, and three registered defects closed.
The headline is pre-registration #69: on a dense model split across GPU/CPU, a small same-family
draft model is the BEST speculation cell this box has measured - +33.5% decode at K=2
(5.54 -> 7.40 tok/s on a 14B, 76% acceptance, novel code) with the draft running on CPU
(-ngld 0), so it costs zero VRAM. The mechanism is the mirror of the MoE union tax: a K+1-token
verify batch reads each CPU-resident layer once, so the CPU share of every token amortizes. The
staked K-shift MISSED and is published as such: every K>=3 lands at or below baseline (llama.cpp's
default 3 is a measured LOSS here), because the CPU draft spends the same RAM bandwidth the
amortization saves. plan now prints the whole recipe on dense-split placements
(dense_draft_note), completing the speculation map: dense split 1.335x > dense all-in-VRAM
1.11x > MoE split 0.74-0.81x (never pays).
Three queued defects closed, each with its test:
- C-11 - the dense split budgeted
vc*0.9with no desktop reserve and no compute buffer, so
at 16k depth it emitted a config that overcommitted VRAM and measured -58% (driver memory
fallback). The budget now subtracts both (the reserve, and the #23 measured 0.5874 MiB/ub-token
slope at the default -ub), counted once, same discipline as the MoE path: a 14B emits 21/48
layers at ctx 0 and 16/48 at 16384 instead of a flat 28/48. Disclosed cost: ~5 layers more
conservative at shallow ctx than a config that measured healthy; the cliff config is gone. - U-17 - the IQ-on-CPU warning is now priced, not prose: every RAM weight read is discounted
by a per-IQ-byte penalty on the file's measured IQ share. The retrodiction gate rewrote the
plan: the hypothesized 2.7x would have overshot ~7x; the calibrated e2e value is k = 0.242
(pure-CPU IQ arm now exact: 11.4 vs 11.44 measured). The split IQ arm improves (28.0 -> 26.9 vs
23.60) but stays over - its GPU share is still priced at K-quant eta, registered as U-19 with
V-11's 1.55x pointing the way. - U-18 -
fetchno longer treats "a file with that name exists" as "the download is
complete": it compares local size against the remote and fails loudly on mismatch, naming the
collision;--forcereplaces the file. This is the exact failure that cost pre-registration
#69 three crashed runs (a June-era 0.5B under the target's filename fed llama-speculative an
incompatible tokenizer).
Also in this release: the U-16 split-ub gate (split placements emit -ub 1024, recovering the
+29% prefill the flat cap left on the table), run/bench/plan flag unification for --threads and
-ub (no command drops what another prints), and the residency buffer term measured rather than
estimated (0.9 GB = #23 buffer + margin, emitting 15 residents where the sweep measured the
optimum). Pre-registrations #67-#69 and their raw logs ship in-tree.