quant-codec-core 0.1.0-alpha.1

Shared codec/profile/shape/eval traits and typed IDs for governed compression experiments
Documentation

quant-codec-core

The smallest stable interface layer shared by the governed compression workspace (poly-kv, fib-quant, turbo-quant, scr-runtime-compression, quant-eval).

quant-codec-core is boring, deterministic, dependency-light, and free of runtime authority. It defines:

  • Typed ID and digest primitives (CodecId, CodecProfileDigest, ArtifactDigest, ModelFingerprint, TokenizerFingerprint).
  • A shape model for KV-cache tensors (KvTensorShape, KvRole, KvLayout, DType, LayerId, HeadId, TokenSpan).
  • A trait surface that concrete codec implementations must satisfy (CodecProfile, VectorCodec, KvCacheCodec).
  • An EvalReport type for codec quality comparison.

This crate is the type contract for the codec workspace. It does not own the codec math, the GPU dispatch, the runtime, the manifests, the receipts, or the policy. It owns types and traits, nothing more.

Why a separate crate?

A codec is a complex thing. It has a profile, a shape, a digest, a name, a version, an encoding, a decoding, and an evaluation. If each of the codecs in the workspace (fib-quant, turbo-quant, polar, qjl, future biquant, etc.) re-invents these, you get duplicated IDs, duplicate digests with subtly different canonical forms, and shape types that don't compose.

quant-codec-core is the one place in the workspace where the ID is a CodecId and the digest is a CodecProfileDigest and they mean the same thing everywhere.

Quick Start

use quant_codec_core::{
    CodecId, CodecProfileDigest, KvRole, KvTensorShape, KvLayout, DType,
    CodecProfile,
};

fn main() {
    // Define a shape for a model.
    let shape = KvTensorShape {
        layers: 32,
        key_heads: 8,
        value_heads: 8,
        seq_len: 2048,
        head_dim: 128,
        layout: KvLayout::LayersHeadsTokensDim,
        dtype: DType::F16,
    };

    // Validate invariants.
    assert!(shape.layers > 0);
    assert_eq!(shape.key_heads, shape.value_heads, "MHA");

    // Build a codec ID.
    let id = CodecId::new("fib-quant").expect("non-empty");
    assert_eq!(id.as_str(), "fib-quant");
}

What's in the box

IDs and digests

Type Purpose
CodecId(String) Identifier for a concrete codec (e.g. "fib-quant", "turbo-quant", "qjl").
CodecProfileDigest([u8; 32]) 256-bit deterministic digest of a codec's profile. Used to identify "the same profile" across versions.
ArtifactDigest([u8; 32]) 256-bit deterministic digest of an encoded artifact.
ModelFingerprint(String) Identifier for the model that produced the source data (e.g. "qwen3-7b", "nomic-embed-v1.5").
TokenizerFingerprint(String) Identifier for the tokenizer.

All five validate empty IDs as errors and provide Display, Debug, Clone, Eq, Hash, Serialize, Deserialize. Digest inputs are canonicalized via the workspace's blake3 chain so different serialization orderings produce the same digest.

Shape model

The shape types describe a KV-cache tensor — the dominant data shape in LLM inference.

pub enum KvRole { Key, Value }
pub enum DType { F32, F16, BF16, I8, U8, PackedBits }
pub enum KvLayout {
    LayersHeadsTokensDim,
    LayersTokensHeadsDim,
    RuntimeSpecific(String),
}

pub struct LayerId(pub u32);
pub struct HeadId(pub u32);
pub struct TokenSpan { pub start: u64, pub end: u64 }

pub struct KvTensorShape {
    pub layers: u32,
    pub key_heads: u32,
    pub value_heads: u32,
    pub seq_len: u64,
    pub head_dim: u32,
    pub layout: KvLayout,
    pub dtype: DType,
}

Validation rules:

  • layers > 0
  • head_dim > 0
  • seq_len > 0
  • Token spans are half-open [start, end) and non-empty
  • GQA/MQA: key_heads != value_heads represents grouped/multi-query attention; key_heads == value_heads is multi-head attention (MHA)

Trait surface

Concrete codec implementations must implement these traits:

pub trait CodecProfile {
    fn codec_id(&self) -> CodecId;
    fn codec_version(&self) -> &str;
    fn profile_digest(&self) -> CodecProfileDigest;
    fn fixed_rate_bits(&self) -> Option<u16>;
    fn block_dim(&self) -> Option<u16>;
    fn is_lossy(&self) -> bool;
}

pub trait VectorCodec {
    type EncodedBlock;
    type Error;

    fn encode_block(&self, input: &[f32]) -> Result<Self::EncodedBlock, Self::Error>;
    fn decode_block(&self, block: &Self::EncodedBlock, out: &mut [f32]) -> Result<(), Self::Error>;
}

pub trait KvCacheCodec: VectorCodec {
    type EncodedCache;

    fn encode_kv_cache(
        &self,
        tensors: &[f32],
        shape: KvTensorShape,
    ) -> Result<Self::EncodedCache, Self::Error>;

    fn decode_slice(
        &self,
        cache: &Self::EncodedCache,
        request: KvSliceRequest,
        out: &mut [f32],
    ) -> Result<(), Self::Error>;
}

CodecProfile::is_lossy() is the critical safety predicate. Codecs that declare is_lossy = true are not allowed to be the fallback path for an exact-fallback contract — the caller must keep the raw data separately.

Eval types

pub struct EvalReport {
    pub mse: Option<f64>,
    pub cosine_similarity: Option<f64>,
    pub max_abs_error: Option<f64>,
    pub bytes_exact: u64,
    pub bytes_encoded: u64,
    pub passed: bool,
    pub notes: Vec<String>,
}

The eval report is a data type, not a runner. The actual benchmark harness lives in quant-eval. quant-codec-core provides the report struct so all codecs can produce a result of the same shape.

Source-of-truth ownership

quant-codec-core is authoritative for:

  • ID and digest shapes and validation
  • The KvTensorShape model
  • The CodecProfile / VectorCodec / KvCacheCodec trait surface
  • The EvalReport struct

quant-codec-core is forbidden from owning:

  • Codec math (lives in fib-quant, turbo-quant)
  • GPU dispatch (lives in gpu-backend)
  • Runtime manifests / receipts (lives in poly-kv)
  • Benchmark runners (lives in quant-eval)
  • Adaptive routing (lives in quant-governor)

This is enforced by the AGENTS.md boundary contract in the parent repo.

Test coverage

  • 12 unit tests in src/ covering:
    • Shape validation (positive and negative)
    • Token span validation
    • Digest stability across runs
    • Serde round-trip for all public types
    • Trait mock compile test
  • cargo test clean, cargo clippy --all-targets -- -D warnings clean.

MSRV

Rust 1.75 (2021 edition). Stable features only.

Dependencies

  • serde (optional, behind the serde feature)
  • thiserror
  • blake3 (for digest computation)

Zero platform-specific code, zero FFI, zero async, zero ML dependencies. Builds in <1s.

License

MIT OR Apache-2.0 (dual-licensed). See LICENSE-MIT and LICENSE-APACHE for the full texts.

Changelog

See CHANGELOG.md for the release history.

Where it's used

quant-codec-core is a foundational dependency of:

  • poly-kv (the shared KV-cache pool primitive)
  • fib-quant (the radial-angular vector codec)
  • turbo-quant (the experimental vector compression sidecar)
  • scr-runtime-compression (the runtime integration adapter)
  • quant-eval (the benchmark suite)

Any system that needs a typed codec contract — the shape of the data, the digest of the profile, the trait the codec implements — can adopt quant-codec-core directly.