fib-quant
Experimental Rust implementation of FibQuant-style radial-angular vector quantization for KV-cache compression. ~50× compression in the binary-packed form. 100% recall on the canonical benchmark corpus (single-level).
Experimental, not production-ready. This is an independent implementation based on the public FibQuant reference (Lee & Kim 2026). It is not the original paper code — see the Attribution section below.
fib-quant decomposes a vector into spherical blocks, quantizes
each block against a Fibonacci-optimized codebook, and stores only
the codebook indices. The result: a 768-dim f32 vector (3,072 bytes)
becomes ~860 bytes in JSON, or ~64 bytes with binary packing. And it
still finds the right document at rank 1 in 100% of the canonical
test queries.
This is the cold-tier codec in the poly-kv pool. It handles shared context that's large, stable, and accessed by many agents:
┌──────────────────────────────────┐
│ SHARED POOL — fib-quant │ ← you are here
│ System prompts, few-shot │
│ examples, shared docs │
│ 50× compression, cos 0.863 │
└──────────┬──────────┬────────────┘
│ │
┌────▼───┐ ┌───▼────┐
│ Agent0 │ │ Agent1 │ ... ← turbo-quant hot tier
└────────┘ └────────┘
What's in the box
- Codec (
src/codec.rs, 1121 lines) —FibQuantizerwithencode,decode,encode_with_receipt,encode_batch,decode_batch,decode_batch_fast,encode_layers. Theencode_batchpath is the Rayon-parallel path that wins the poly-kv pool build. - Codebook (
src/codebook.rs, 207 lines) —FibCodebookV1withbuild_initial_codebookand Lloyd-Max refinement. Parity-verified against the reference. - Rotation (
src/rotation.rs, 216 lines) — fast Walsh-Hadamard rotation withStoredRotation, a CPU fallback, and an optional CUDA dispatch viagpu-backend. - Spherical beta (
src/spherical_beta.rs, 139 lines) — spherical-Beta direction samplers for codebook seeding:sample_spherical_beta,beta_d_k,radius_quantile,radius_quantile_k2_closed_form. - Profiles (
src/profile.rs, 424 lines) — typedFibQuantProfileV1withpaper_default(ambient_dim, block_dim, codebook_size, seed)(k=4, N=32 defaults shown in examples below). Includes validation and rate computation. - Receipts (
src/receipt.rs, 128 lines) — typedFibQuantCompressionReceiptV1capturing every parameter of the encode pipeline for audit. - Scoring (
src/scoring.rs, 411 lines) —GramTableandFibScorerfor approximate inner-product scoring without full decode, using a precomputed codebook Gram table. - Residual VQ (
src/residual.rs, 491 lines) — two-level vector quantization withFibResidualQuantizer,FibResidualCodeV1, andResidualCodebookV1for improved reconstruction quality. - Wire format (
src/wire.rs, 333 lines) — self-describing wire format (FibCodeWireV1,WireHeader) that carries profile metadata so downstream consumers can decode without external profile knowledge. - Sidecar search (
src/sidecar.rs, 430 lines) —FibSidecarIndex<Id>wrappingFibScorerfor approximate nearest-inner-product search withScoredCandidateandSearchReceiptV1. - Eval harness (
src/eval.rs, 519 lines) — benchmark harness withFibBenchmarkCorpus,run_benchmark, andFibBenchmarkReceiptV1capturing recall@K, nDCG@K, compression ratio, MSE, and timing. - Compat layer (
src/compat.rs, 248 lines,compatfeature) — implementsVectorCodec,CodecProfile, andKvCacheCodectraits fromquant-codec-coreso fib-quant can be used through the shared codec trait boundary bypoly-kv,quant-governor, andscr-runtime-compression. - KV-cache codec (
src/kv/, ~3,300 lines,kvfeature) — a separateKvCacheCodecimpl that operates onKvTensorShaperather than rawVec<f32>. Includes attention-quality metrics, shape contracts, policy-role-aware dispatch, and a streaming encoder (KvStreamEncoderinsrc/kv/stream.rs, 800 lines) for incremental token-by-token construction. - KV receipts (
src/kv/receipt.rs) —KvCompressionReceiptV1,KvDecodeReceiptV1, andKvEvalReceiptV1for KV-cache pipeline audit.
Quick Start
use ;
Run it: cargo run --release --example encode_decode.
New modules
Scoring — approximate inner product without full decode
FibScorer uses a precomputed codebook Gram table
(GramTable, G[i,j] = <codeword_i, codeword_j>) to estimate the
inner product of a query vector against a stored FibCodeV1 without
running the full decode pipeline (rotation inverse + norm scaling).
The estimate is approximate — bounded by codebook quantization noise
— and avoids decoding the stored vector entirely. For a codebook of
size N=32, the Gram table is 4 KB.
use ;
let profile = paper_default?;
let quantizer = new?;
// FibScorer::new takes ownership of the quantizer.
let scorer = new?;
let query = vec!;
// Encode before moving the quantizer into the scorer, or use
// a separate quantizer instance for encoding.
Residual — two-level VQ for better fidelity
After encoding with the main codebook, the quantization residual
still contains signal. FibResidualQuantizer encodes this residual
with a second, smaller codebook (typically 4–8 codewords), adding
2–3 bits per block. Cosine fidelity improves from ~0.863
(single-level) to ~0.93+ (two-level) for typical nomic-768
workloads, at the cost of ~10–15% size increase.
use ;
let profile = paper_default?;
let quantizer = new?;
let residual = build?;
Wire format — self-describing codes
FibCodeWireV1 wraps a FibCodeV1 with a 59-byte header carrying
seed, dim, k, N, norm_format, and profile digest. This enables
decode without any external profile knowledge — the compact FB1/FB2
formats strip all metadata, forcing consumers to hardcode profile
fields.
use ;
let profile = paper_default?;
let quantizer = new?;
let code = quantizer.encode?;
let wire_bytes = to_wire_bytes?;
// Decode without needing the original profile — from_wire_bytes
// returns (FibCodeV1, FibQuantProfileV1):
let = from_wire_bytes?;
Sidecar — approximate search index
FibSidecarIndex<Id> stores caller-owned IDs alongside encoded
FibCodeV1 artifacts and provides approximate nearest-inner-product
search via the Gram-table estimator. The index is a sidecar: it
produces approximate candidates that callers must rerank with an
exact inner-product computation against the original (un-encoded)
vectors before acting on the result.
use ;
let profile = paper_default?;
// Encode first, then build the scorer for search.
let quantizer = new?;
let code = quantizer.encode?;
// Build a fresh quantizer to move into the scorer.
let profile2 = paper_default?;
let scorer = new?;
let mut index = new;
index.add;
let candidates = index.search?;
// Rerank candidates against original vectors before use.
Eval — benchmark harness
run_benchmark takes a FibBenchmarkCorpus (database vectors,
queries, ground-truth top-K) and a &FibQuantizer, then returns a
FibBenchmarkReceiptV1 with recall@K, nDCG@K, compression ratio,
cosine similarity, MSE, and timing. Standalone helpers recall_at_k
and ndcg_at_k are also exported.
use ;
let corpus = FibBenchmarkCorpus ;
let profile = paper_default?;
let quantizer = new?;
let receipt = run_benchmark?;
println!;
Streaming KV encoder
KvStreamEncoder (behind the kv feature) allows building a
KvEncodedTensorV1 one token at a time instead of requiring the
full tensor upfront. Pages are flushed automatically when they
reach tokens_per_page from the page geometry. The output is
identical to the batch encode_kv_tensor for the same input.
Currently supports batch = 1, layers = 1, kv_heads = 1 shapes
(the common single-stream inference case).
C Kernels
Starting in v0.1.0-beta.4, the encode/decode and compressed-attention
hot paths in fib-quant are backed by C kernels compiled with
-O3 -mavx2 -mfma via the cc crate. The original Rust implementations
are preserved in src/archive/ with headers documenting the replacement.
| Kernel | C file | Purpose |
|---|---|---|
| Codec | c-kernels/codec.c |
encode_vector_block and decode_vector_block inner loops |
| Compressed attention | c-kernels/attention.c |
Compressed attention logits + softmax computation |
The FFI boundary is in src/ffi.rs — extern "C" declarations wrapping
the C functions. src/codec.rs, src/scoring.rs, and
src/kv/compressed_attention.rs call through the FFI layer when the C
kernels are available. The unsafe_code lint is allowed at the crate
level for the FFI module.
All C kernels are compiled at build time via build.rs. No pre-built
binaries. The cc build dependency is required.
Benchmarks — measured
Compression ratios (768-dim nomic-embed-v1.5)
| Format | Bytes per vector | Ratio |
|---|---|---|
| Raw f32 | 3,072 | 1.0× |
| fib-quant JSON (default profile) | 860 | 3.6× |
fib-quant binary-packed (PackedFibCode) |
~64 | ~48× |
| fib-quant KV-cache JSON | 1,200 | 2.6× |
| fib-quant KV-cache binary | ~80 | ~38× |
The "theoretical 50×" is the binary-packed compact form. The "JSON 3.6×" is what you get with the default wire format — the JSON envelope is 12× bigger than the actual codebook indices. If you're optimizing for storage, use the binary wire format.
Retrieval quality (P26 measurement, semantic-memory harness)
8 queries, 200 docs, 768-dim, k=10, oversample=4:
| Route | Recall@1 | Recall@10 | nDCG@10 | Mean rank drift |
|---|---|---|---|---|
| exact_scan (no compression) | 1.000 | 1.000 | 1.000 | — |
| fib-quant only | 1.000 | 1.000 | 1.000 | 0.33 |
| turbo-quant only | 1.000 | 1.000 | 1.000 | 0.03 |
| poly-kv (two-tier) | 1.000 | 1.000 | 1.000 | 0.25 |
Cosine fidelity: 0.863 (single vector), 0.9996 (after turbo-quant rerank in poly-kv).
The benchmark numbers above are from the P26 measurement run and are valid for single-level quantization. Two-level residual VQ improves cosine fidelity to ~0.93+ but has not been benchmarked for retrieval quality yet.
Encode_batch throughput — "Do All" perf pass 2026-06-01
The encode_batch loop is the dominant cost in the poly-kv
pool build. After the June 1 perf pass (AVX2+FMA SIMD +
Rayon):
| Workload | Old (f64 ref) | + SIMD | + Rayon (parallel) | + full stack |
|---|---|---|---|---|
| qwen3 2560 n=80 | 13763ms | — | 1250ms | 346ms (40×) |
| nomic 768 n=80 | 4552ms | 94ms | 407ms | 133ms (34×) |
| qwen3 2560 n=4 | 1449ms | 418ms | 893ms | 256ms (5.7×) |
Numbers from poly-kv/benchmarks/DO_ALL_PERF_PASS_2026-06-01.md.
GPU path — measured
| Shape | n | CPU | Hadamard-GPU | Full-GPU | Best |
|---|---|---|---|---|---|
| d=64 | 80 | 14ms | 13ms (-7%) | 14ms | Hadamard |
| d=128 | 80 | 57ms | 54ms (-5%) | 56ms | Hadamard |
| d=768 | 80 | 2143ms | 2103ms (-2%) | 2133ms | Hadamard |
| d=2560 | 4 | 1571ms | 1564ms (0%) | 1554ms (0%) | tie |
Honest takeaway: fib-quant's encode_batch is 2-7%
faster on a real GPU (msi i7-6700HQ + GTX 1070) with the
Hadamard path engaged. The codebook_lookup kernel exists and
is parity-verified, but the per-call H2D/D2H overhead
currently negates its win. A device-side pipeline is the
next step.
Test coverage
- 23 integration test files in
tests/:bitpack_indices,codebook_determinism,compact_bytes_roundtrip,corruption_rejection,decode_batch_fast_parity,direction_generators,encode_decode_roundtrip,kv_attention_quality,kv_corruption_rejection,kv_encode_decode_reference,kv_policy_role_aware,kv_property_shapes,kv_shape_contracts,lloyd_refinement,norm_payload_rejection,paper_k2_radius_closed_form,paper_smoke_regression,profile_digest,profile_resource_bounds,property_bitpack,property_codec,rotation_identity,spherical_beta_sampler.
- 4 examples:
build_codebook,encode_batch_microbench,encode_decode,test_compact_decode. - 4 benches (criterion):
codebook_build,encode_decode,kv_attention_ref,kv_encode_decode. - 122 tests pass with
cargo test --all-features(was 47 before the new module additions, 105 before C kernel integration). cargo clippy --all-features --all-targets -- -D warningsclean (modulo upstreamgpu-backendlints on newer toolchains).
MSRV
Rust 1.75 (2021 edition). #![forbid(unsafe_code)] at the
crate level, except the FFI module (src/ffi.rs) which uses
unsafe for extern "C" calls to the C kernels.
A C compiler (GCC or Clang with AVX2/FMA support) is required for
the C kernel build step via the cc crate.
Dependencies
serde(withderive).serde_json.blake3.half(f16 support for scoring/scaling).nalgebra(withserde-serialize).rand+rand_chacha(dev).gpu-backend(optional) — for the GPU Hadamard dispatch.rayon(optional, behind theparallelfeature) — for parallel batch encoding.quant-codec-core(optional, behind thecompatfeature) — for the shared codec trait boundary.cc(build dependency, for C kernel compilation).proptest(dev).criterion(dev).
License
Apache-2.0. See LICENSE-APACHE for the full text.
Changelog
See CHANGELOG.md for the release history.
Attribution
This crate is an independent Rust implementation of the FibQuant compression technique described in the public literature (Lee & Kim, 2026). It is not the original authors' reference code, and does not claim affiliation with the FibQuant paper authors. The mathematical approach (radial-angular block decomposition with Fibonacci-sampled codebook seeding) follows the published specification.
The kv-cache codec profile, the parallel encode pipeline,
the GPU dispatch path, the receipt infrastructure, and the
test suite are original to this implementation.
Where it's used
fib-quant is the cold-tier codec for:
poly-kv— the shared pool is fib-quant compressed. Every shared system prompt, every shared few-shot example, every shared doc goes throughencode_batch.semantic-memory— whenAdmissibilityClass::Standardis selected byquant-governor, semantic-memory can route to the fib-quant sidecar for candidate generation.scr-runtime-compression— thefibfeature is the fib-quant adapter for the runtime.
Any system that needs a high-ratio, medium-fidelity vector
codec — search-only recall, cold tier, ~50× storage savings
— can adopt fib-quant directly.