Skip to main content

VectorCodec

Trait VectorCodec 

Source
pub trait VectorCodec: Send + Sync {
    type Quantized: AsRef<UnifiedQuantizedVector>;
    type Query;

    // Required methods
    fn encode(&self, v: &[f32]) -> Self::Quantized;
    fn prepare_query(&self, q: &[f32]) -> Self::Query;
    fn fast_symmetric_distance(
        &self,
        q: &Self::Quantized,
        v: &Self::Quantized,
    ) -> f32;
    fn exact_asymmetric_distance(
        &self,
        q: &Self::Query,
        v: &Self::Quantized,
    ) -> f32;

    // Provided methods
    fn adc_lut(&self, _q: &Self::Query) -> Option<AdcLut> { ... }
    fn train(&mut self, samples: &[&[f32]]) -> Result<(), CodecError> { ... }
}
Expand description

The dual-phase quantization codec trait.

Quantized is the on-disk / in-memory packed form (one per vector). Query is the prepared query — may be raw FP32, may be rotated, may hold a precomputed ADC LUT, depending on the codec.

§Extensibility audit — future algorithms

The following six algorithms can each be added as a new impl VectorCodec without changing the trait surface:

TurboQuant — learned rotation matrix applied before scalar quantization. The rotation is held in the codec struct (same pattern as OpqCodec.rotation) and applied inside encode and prepare_query. No trait change needed. QuantMode::TurboQuant4b already exists as a layout discriminant.

PolarQuant — encodes magnitude and direction as separate components. Both components are packed into a single packed_bits region whose layout the codec controls. The encode return type is Vec<u8> of arbitrary length via UnifiedQuantizedVector::packed_bits, so multi-component payloads fit without a trait change. QuantMode::PolarQuant is already reserved.

ITQ3_S — Iterative Quantization with 3-bit codes, learned via SVD. Requires a calibration/fitting step before encoding begins. Existing codecs expose this as a concrete static calibrate method (e.g. Sq8Codec::calibrate, RaBitQCodec::calibrate). The train method added below makes this fitting phase reachable through the trait for generic dispatchers that hold a C: VectorCodec without knowing the concrete type. The default impl is a no-op so all existing impls compile without change.

OSAQ — Optimized Symmetric/Asymmetric Quantization. Uses symmetric encoding for indexed vectors and asymmetric encoding for queries. The existing trait already separates these paths: encode is the index path, prepare_query is the query path, and type Query is a distinct associated type. No trait change needed.

RaBiT — Rotation + Binary quantization with full-precision query and 1-bit index. Exactly the pattern implemented by RaBitQCodec: type Query holds a full-precision Vec<f32>, type Quantized holds 1-bit sign codes, and exact_asymmetric_distance uses the full query against binary candidates. No trait change needed.

LVQ — Locally-adaptive Vector Quantization with per-vector scale/offset. The QuantHeader carries global_scale and residual_norm — two f32 scalars sufficient for per-vector min/max parameters. If a codec needs additional per-vector state it can prepend a small structured header inside packed_bits (the codec controls that region’s layout entirely). No trait change needed.

Required Associated Types§

Source

type Quantized: AsRef<UnifiedQuantizedVector>

The packed quantized form. Must be convertible to a UnifiedQuantizedVector reference via AsRef.

Source

type Query

The prepared query form (codec-specific).

Required Methods§

Source

fn encode(&self, v: &[f32]) -> Self::Quantized

Encode a single FP32 vector into the codec’s packed form.

Source

fn prepare_query(&self, q: &[f32]) -> Self::Query

Prepare a query for distance computations against this codec. May rotate, normalize, build a LUT, etc.

Source

fn fast_symmetric_distance( &self, q: &Self::Quantized, v: &Self::Quantized, ) -> f32

Fast symmetric distance — bitwise / heuristic. Used during HNSW upper-layer routing. Both arguments are quantized; no scalar correction; no outlier resolution. Hot path; must be inline-friendly.

Source

fn exact_asymmetric_distance(&self, q: &Self::Query, v: &Self::Quantized) -> f32

Exact asymmetric distance — full ADC with scalar correction and sparse outlier resolution. Used at base-layer rerank only. Slower but high-fidelity.

Provided Methods§

Source

fn adc_lut(&self, _q: &Self::Query) -> Option<AdcLut>

Optional: precompute ADC lookup table for codecs that use one (PQ, IVF-PQ, TurboQuant). Returns None for codecs that don’t (RaBitQ, BBQ, ternary, binary).

Source

fn train(&mut self, samples: &[&[f32]]) -> Result<(), CodecError>

Optional: fit the codec’s learned parameters on a set of training vectors.

Called once before encoding begins, typically at index-build time. Codecs with no learnable parameters (binary sign-bit, ternary) can use the default no-op. Codecs with an SVD- or k-means-based fitting phase (ITQ3_S, OPQ, PQ, TurboQuant) override this to update their internal rotation matrices or codebooks.

Returns Ok(()) on success. The error type is CodecError so callers that drive training through a generic bound can propagate failures without knowing the concrete codec.

The default implementation is a no-op and always returns Ok(()).

Implementors§