Commit Graph
40 Commits
Author SHA1 Message Date
367bb2dbbb docs: update README with context scaling data + gate script info
- Added context scaling table (2K-32K, flat 99% of q8_0)
- Added optimized dequant to speed journey
- Linked context scaling deep dive doc
- Updated gate script description (now checks PPL + speed)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 20:25:24 -05:00
eed5a6310e ci: quality+speed gate — checks PPL + context scaling before push
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 20:22:52 -05:00
9be9ca18c1 docs: extended context scaling verified — 0.99x q8_0 through 32K context
Tested 2K/4K/8K/16K/32K: ratio stays 0.987x-0.995x (flat).
PPL: 5.471 (32-chunk, +1.1% of q8_0).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 20:21:22 -05:00
034d4c911e docs: context scaling FIXED — optimized dequant gives flat 98% of q8_0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 20:13:40 -05:00
e5fcbe34db docs: group-32 rotation failed (PPL 7.06)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 19:31:11 -05:00
0255ba2d7f docs: context scaling fix investigation — group-32 rotation approach
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 19:22:06 -05:00
6406922ace docs: update all docs with q8_0 parity results (2747 tok/s, 4.6x compression)
- README: top-of-tree table, speed journey, updated roadmap and contributing
- quality-benchmarks.md: verified PPL numbers with error bars (5.460 ± 0.141)
- turbo-speed-investigation.md: full 4-step optimization breakdown

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 18:01:14 -05:00
d50ef98f5b docs: block-32 breakthrough — q8_0 parity at 4.6x compression
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 17:34:27 -05:00
1bd4fcb181 docs: experiment 3 results — graph WHT gives 2095 tok/s (0.78x q8_0)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 17:23:25 -05:00
d06ff09f1c docs: experiment 1 results — half4 WHT gives 1411 tok/s (+31%)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 17:00:58 -05:00
445a3dc4c7 docs: move engineering docs here from llama.cpp fork
These belong in our repo, not in a fork of someone else's project.

Added:
- docs/quality-benchmarks.md — perplexity validation, bisection log, top-of-tree table
- docs/turbo-speed-investigation.md — Metal gotchas, fp16 WHT, optimization history
- docs/pre-rotate-queries-investigation.md — WHT/RoPE commutativity issue
- docs/pre-rotate-queries-plan.md — original optimization plan
- scripts/turbo-quality-gate.sh — pre-push perplexity check

README links updated to point locally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 16:16:58 -05:00
2d592a6f30 docs: link engineering docs from llama.cpp fork in README
Add Engineering Docs section linking quality benchmarks, speed
investigation, pre-rotate-queries debugging log, and quality gate
script. Update roadmap and contributing sections to reflect current
state (fp16 WHT done, SIMD cooperative dequant in progress).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 16:15:54 -05:00
bd2843e67d docs: update speed table with fp16 WHT results (1074 tok/s, 0.40x q8_0)
Replace outdated 10.7 tok/s generation numbers with validated prefill
benchmarks. Add speed optimization history table showing progression
from fp32 WHT (739) to fp16 WHT (1074). Note pre-rotate-queries
abandoned due to WHT/RoPE commutativity issue.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
2026-03-25 16:12:32 -05:00
4c67c02340 fix: honest README — PPL 6.19 confirmed, speed claims corrected
Previous speed claims (51-77 tok/s, 91-97% of q8_0) were INVALID.
Pre-rotate-queries never executed due to GQA head layout mismatch.
Those benchmarks measured speed of producing garbage output.

Correct numbers:
- Quality: PPL 6.194 (+1.4% of q8_0) ✅
- Speed: ~10.7 tok/s (8× gap from inverse rotation in dequant)
- Compression: 4.6×

Speed optimization path: pre-rotate-queries with per-head GQA reshape.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 14:17:34 -05:00
bd3b4036c3 feat: near-parity with q8_0 — 91% MoE, 97% Qwopus at 4.6× compression
Block size 32 + MSE-only + pre-rotate-queries:
- MoE: 77.7 tok/s gen (91% of q8_0), 218.5 prompt (98%)
- Qwopus: 17.0 tok/s gen (97% of q8_0), 89.5 prompt (108% — faster!)

4.6× KV cache compression with near-zero speed cost.
Target was 75+ tok/s on MoE. Hit 77.7.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 11:58:51 -05:00
b8c4650c03 feat: final v1 benchmarks — 73-88% of q8_0 speed at 4.9× compression
MSE-only + pre-rotate-queries:
- MoE 35B: 62.2 tok/s gen (73% of q8_0), 200 tok/s prompt (90%)
- Qwopus 27B: 15.5 tok/s gen (88% of q8_0), 83 tok/s prompt (100%)

Better quality than paper's Algorithm 2 (cosine 0.985 vs 0.958).
Q rotation overhead is negligible (<1%) — WHT replacement not needed.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 11:35:59 -05:00
b63c5aca98 feat: update benchmarks — 51.4 tok/s MoE, 14.6 tok/s Qwopus with pre-rotate-queries
Pre-rotate-queries optimization delivers:
- MoE 35B-A3B: 51.4 tok/s (60% of q8_0) at 4.9× compression
- Qwopus 27B: 14.6 tok/s (83% of q8_0) at 4.9× compression

The dense 27B model is now practical for long-context inference.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:31:11 -05:00
128809e426 docs: update README with speed ceiling data and pre-rotate-queries plan
Speed ceiling test: removing rotation from dequant gives 49.1 tok/s
(57% of q8_0), confirming pre-rotate-queries optimization target.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:00:39 -05:00
b483a097b3 fix: update benchmarks with real Metal numbers (was CPU fallback) #23
Previous benchmarks were CPU due to #include bug in Metal shader.
Real Metal GPU numbers:
- MoE: 10.7 tok/s gen (8× slower than q8_0, was 35×)
- Qwopus: 5.3 tok/s gen (3.3× slower than q8_0, was 13.5×)
- Prompt: 60-67 tok/s MoE, 25-30 tok/s Qwopus

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:16:29 -05:00
af40f0182a docs: update README with correct llama.cpp fork URL
Build instructions now point to the actual fork:
https://github.com/TheTom/llama-cpp-turboquant/tree/feature/turboquant-kv-cache

Listed all modified files from upstream llama.cpp.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 08:28:32 -05:00
43bdecc76b docs: comprehensive README rewrite for public release
- Single coherent flow: results → getting started → architecture → roadmap
- Removed duplicate sections and local paths
- Added Contributing section
- Added proper paper links (arXiv URLs)
- Copyright notice in License section
- Changed "we" to "I" throughout
- Added benchmark_results.md and run_benchmark.py to project structure

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 07:58:27 -05:00
b28a2319db feat: add benchmark results and updated roadmap to README
Added full benchmark tables for both models (MoE + Dense) with all
4 cache types. Added compression quality table from Python prototype.
Added key validation section (rotation Gaussianization proof).
Updated roadmap with current status and issue links.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 07:54:28 -05:00
7e469a0dc9 feat: benchmark results — turbo3/turbo4 vs q8_0/q4_0 on M5 Max #22
Results on Qwen 3.5 35B-A3B MoE and Qwopus v2 27B:
- turbo3: 4.9× compression, 2.4 tok/s MoE / 1.3 tok/s Dense
- q8_0 baseline: 85.0 tok/s MoE / 17.6 tok/s Dense
- Speed regression: 13-35× (unoptimized Metal shader, tracked in #23)
- Compression ratio target met, speed optimization needed

Codex review corrections applied:
- Fixed methodology description (was inconsistent with actual test params)
- Changed "~35×" to "13-35×" (varies by model)
- Marked quality claims as qualitative/unquantified
- Noted compression ratios are theoretical not empirically measured
- Added missing analysis caveats (single run, no stddev, no warm-up)

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 01:06:59 -05:00
45586131b0 fix: remove CLAUDE.md and dev workflow from public repo
- Removed CLAUDE.md from tracking (private dev config)
- Removed .claude/ agents from tracking
- Added CLAUDE.md and .claude/ to .gitignore
- Removed development workflow section from README

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 00:22:22 -05:00
6634deebd0 feat: README overhaul, Apache 2.0 license, benchmark script #22
README updates (per Codex review):
- Fixed overstated "zero accuracy loss" claim — now shows actual metrics
- Added proper llama.cpp fork build instructions with prerequisites
- Added "Plus" branding explanation (post-v1 improvements planned)
- Added prerequisites section (Python, cmake, Xcode)
- Fixed inconsistent build paths (build-turbo vs build)
- Removed unsubstantiated Prince Canuma comparison claim

Added:
- Apache 2.0 LICENSE file (Copyright 2026 Tom Turney)
- benchmarks/benchmark_llama.sh script

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 00:09:59 -05:00
338e978b09 feat: validate rotation Gaussianization on real KV tensors #18 #20
Critical experiment: real Qwen3-1.7B K cache has kurtosis=900.
After norm extraction + random rotation: kurtosis=2.9 (Gaussian=3.0).
Std matches 1/sqrt(d) to 6 decimal places. Ratio = 1.000 exactly.

Paper's core mathematical claim is validated on real data.
Gaussian codebook is correct — no per-layer calibration needed (#20 closed).

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:36:34 -05:00
4e8443f24e fix: real model validation — DynamicCache API, Phase A results #18
Fixed HuggingFace DynamicCache extraction (transformers 5.x API).
First real tensor validation on Qwen3-1.7B complete.

Key findings:
- Real KV tensors have kurtosis=918 (K) vs Gaussian=3.0
- Norm extraction critical: norms range 6.8-603.8
- 3.5-bit outlier: cosine 0.945, ratio 8.0× on real tensors
- 4-bit uniform: cosine 0.975 on real tensors
- Attention cosines 0.64-0.82 (lower than synthetic due to heavy tails)

Results posted to issue #18.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:34:03 -05:00
c1a10e4a64 feat: input validation, README, real model validation script #12 #18
- Add input validation to rotation.py: d>=1, pow2 checks on hadamard
  and FWHT, with ValueError messages (#12)
- Add README.md with quick start, results, architecture, roadmap
- Add benchmarks/validate_real_model.py for Phase A validation (#18)
- Close #9, #16 (superseded by #18)

5 new tests for validation guards. 137 total tests passing.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:29:24 -05:00
1fa6d79b10 feat: outlier comparison benchmark — matches Prince Canuma's ratios
2.5-bit: 4.9× compression (Prince: 4.9×) ✅
3.5-bit: 3.8× compression (Prince: 3.8×) ✅

Quality at 3.5-bit: MSE 0.0009, cosine 0.947
Quality at 2.5-bit: MSE 0.0029, cosine 0.856

Pending: real KV tensor validation from llama.cpp NIAH test.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:21:53 -05:00
d0e70cd24f feat: outlier channel strategy for 2.5-bit and 3.5-bit quantization #17
Splits channels into outlier (higher bits) and normal (lower bits):
- 2.5-bit: 64/128 at 3b + 64/128 at 2b
- 3.5-bit: 64/128 at 4b + 64/128 at 3b

This matches Prince Canuma's MLX approach for achieving 4.9× compression.

8 tests, 91% coverage on outlier.py.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:20:55 -05:00
c3aad548ff test: achieve 100% code coverage across all modules
Added tests for:
- codebook.py: extreme narrow finite interval fallback, both-infinite pragma
- turboquant.py: compressed_size_bits method
- utils.py: pack_indices invalid bit_width ValueError

133 tests, 100% coverage (330 statements, 0 missed).

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:18:46 -05:00
f1c2397680 feat: integration test at real Qwen 3.5 KV cache dimensions #16
Simulates KV cache compression at Qwen 3.5 27B and 35B-A3B dimensions:
28 layers × 8 KV heads × 128 head_dim × up to 8192 tokens.

Results:
- 3-bit K+V: 2.6× compression, K cosine 0.91, attention cosine 0.98
- 4-bit K+V: 1.9× compression, K cosine 0.96, attention cosine 0.99
- Prince Canuma gets 4.9× at 2.5-bit (uses outlier channel strategy)

Next: implement outlier channel strategy for non-integer bit rates
(2.5-bit, 3.5-bit) to match Prince's compression ratios.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:15:14 -05:00
dccd96bc71 fix: add norm extraction to PolarQuant — critical for real KV tensors #15
CRITICAL BUG (found by roast review): PolarQuant codebook was calibrated
for unit-norm vectors only. Real KV cache tensors have norms ~10-50,
causing every coordinate to saturate to extreme centroids.

Fix (per paper page 5): extract L2 norms before quantization, normalize
to unit vectors, quantize, then rescale on dequantization. Norms stored
as float32 metadata alongside indices.

API change: quantize() now returns (indices, norms), dequantize() takes
(indices, norms). All downstream code updated (TurboQuant, KVCache, tests).

Added test_non_unit_norm_vectors at scales [0.01, 1.0, 10.0, 50.0, 100.0].
Zero vector now correctly reconstructs to zero (norm=0).

128 tests, 98% coverage, all green.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:11:22 -05:00
361ea4cab0 feat: add demo benchmark script for quick validation
Shows single-vector compression, full KV cache compression, and inner
product preservation at 2/3/4-bit quantization levels.

Results:
- 3-bit: 4.9× compression, cosine sim 0.83, IP error 0.02
- 4-bit: 3.8× compression, cosine sim 0.86, IP error 0.01
- KV cache: 4 layers × 8 heads × 512 tokens compressed in 60ms

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:05:53 -05:00
8ec1a07bfb feat: TurboQuant, KV cache compressor, utils, distortion suite #6 #7 #8 #10
TurboQuant (Algorithm 2): PolarQuant(b-1) + QJL(1) = b bits total.
19 tests, 93% coverage.

KVCacheCompressor: TurboQuant for K cache (IP), TurboQuantMSE for V cache (MSE).
5 tests, 100% coverage.

Utils: bit packing, memory footprint calculation.
9 tests, 98% coverage.

Distortion validation suite: MSE bounds, IP bounds, monotonicity.
20 tests verifying against paper Table 2.

Full suite: 127 tests, 98% total coverage.

Codex review on TurboQuant:
- Noted that double-side IP estimation is biased (documented, tested)
- True bit rate is b + 32/d (norm overhead documented)
- QJL correction factor is inside QJL.dequantize (verified)

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:04:56 -05:00
4d34f5148c feat: PolarQuant quantizer + QJL 1-bit quantizer #4 #5
PolarQuant (Algorithm 1): random rotation + optimal scalar quantization.
14 tests, 97% coverage on polar_quant.py.

QJL (Quantized Johnson-Lindenstrauss): 1-bit sign quantization of residuals
with unbiased inner product preservation.
9 tests, 96% coverage on qjl.py.

Codex review:
- PolarQuant assumes unit-norm input (paper convention, documented)
- QJL docstring corrected (not zero overhead — stores d×d matrix)
- QJL scaling comment added (m=d assumption)
- Removed dead code in quantize_and_residual

Roast running in background.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:02:06 -05:00
fe7c5f9ad2 feat: codebook construction for PolarQuant (codebook.py) #3
Implements optimal scalar quantization codebooks:
- Closed-form centroids for 1-bit (±√(2/πd)) and 2-bit ({±0.453, ±1.51}/√d)
- Lloyd-Max algorithm for 3+ bit codebooks on Gaussian approximation
- Vectorized nearest centroid lookup via searchsorted

22 tests, 93% coverage.

Reviews:
- Codex: fixed extreme tail CDF cancellation (use sf() for upper tail),
  added asymptotic fallback for extreme intervals, removed unused vars
- Roast: running in background (will address in follow-up if needed)
- Added brute-force correctness test for nearest_centroid_indices

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:00:07 -05:00
e680643d7c fix: address roast review findings on scaffold #1
- Remove setup.py (version drift timebomb — pyproject.toml is sufficient)
- Fix CI: remove || true silent failure swallower, add pip caching
- Fix .gitignore: add .coverage, htmlcov/, .mypy_cache/, .DS_Store, *.so
- Fix CLAUDE.md: "CI before commit" → "CI before merge" (was impossible)
- Created #14 for mypy/ruff in CI (deferred to P3)

Roast review by @roast subagent.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:55:30 -05:00
0e642a883c feat: random rotation matrix generation (rotation.py) #2
Implements dense Haar-distributed rotation (QR decomposition) and fast
structured rotation (Walsh-Hadamard + random signs).

Dense rotation is the primary path for PolarQuant — verified orthogonal,
det=+1, norm-preserving, IP-preserving, and post-rotation distribution
matches paper's Beta(d/2, d/2) → Gaussian(0, 1/d).

29 tests, 100% coverage on rotation.py.

Reviews completed:
- Codex review on tests: fixed Haar distribution test methodology,
  switched FWHT reference to scipy, clarified non-pow2 behavior
- Codex review on implementation: documented slogdet cost, float64
  requirement, and non-pow2 limitations
- Roast review: found non-pow2 transpose bug (#11), missing input
  validation (#12), single D-H-D round vs paper's 3-round (#13)

Known limitations (tracked in issues):
- Fast rotation broken for non-pow2 dims (#11)
- No input validation (#12)
- Single D-H-D round (#13)

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:53:52 -05:00
8fa1d293f9 infra: project scaffold — CI, pyproject, CLAUDE.md, PLAN.md #1
Set up bare project infrastructure:
- .gitignore, pyproject.toml, setup.py
- GitHub Actions CI with Python 3.10/3.11/3.12 matrix
- CI enforces >95% coverage when tests exist, skips gracefully when empty
- CLAUDE.md with full development workflow rules
- PLAN.md with phased implementation plan
- Empty turboquant/, tests/, benchmarks/ packages

No algorithm code — scaffold only.

Co-Authored-By: tturney@psyguard.ai
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:43:16 -05:00