Expand description
§iqdb-ivf
Inverted-file (IVF) approximate nearest-neighbour index for the iQDB
vector database. IvfIndex partitions the vector space with
deterministic k-means and answers queries by exhaustively scanning only
the IvfConfig::n_probes clusters whose centroids are nearest to the
query. It is the complement to a graph index: more memory-efficient at
very large scale and with more predictable latency, because every query
probes the same fixed number of clusters.
Two variants share one surface. IVF-Flat (the default) stores
vectors verbatim and scores probed clusters exactly. IVF-PQ
(use_pq = true) compresses each vector to a Product-Quantization code
and scores by asymmetric distance (ADC), optionally exact-reranking a
shortlist against the retained vectors. Both honour metadata filters and
the same smaller-is-nearer ordering contract as every other iQDB index.
§Tiered API
- Tier 1 — the lazy path.
IvfConfig::defaultplusIvfIndex::new,IvfIndex::train, and theiqdb_index::IndexCoreinsert/search calls cover the whole common case with no generics to name. - Tier 2 — the configured path. The builder-style
IvfConfig::with_n_clusters/IvfConfig::with_n_probes/IvfConfig::with_use_pq(and friends) tune partitioning, recall, and compression, whileIvfIndex::set_n_probes,IvfIndex::set_pq_refine_factor,IvfIndex::suggest_n_probes,IvfIndex::retrain, andIvfIndex::cluster_statstune and inspect a live index. - Tier 3 — the trait seam.
IvfIndeximplementsiqdb_index::Indexandiqdb_index::IndexCore, so it is interchangeable with any other backend behind those traits.
§Design
- Storage is
n_clustersinverted lists, each owning the(VectorId, Arc<[f32]>, Option<Metadata>, seq)tuples for the vectors assigned to its centroid. The payload is wrapped inArc<[f32]>so the engine shares one allocation between this index and its record store — the same zero-copy contractiqdb-flatandiqdb-hnswuse. - Training is mandatory.
IvfIndex::newreturns an untrained index; the four entry points that depend on centroids (insert,insert_batch,search, andsearch_batch) short-circuit withiqdb_types::IqdbError::InvalidConfiguntil the caller invokesIvfIndex::train. This UX cliff is intentional and documented loudly. - K-means runs through a seeded SplitMix64 PRNG, accumulating centroid
sums in
f64and reducing in fixed order, so identicalseedplus identical sample produce byte-identical centroids on every platform. - All distance math is delegated to
iqdb_distance::compute_batch; IVF never reimplements a metric. Foriqdb_types::DistanceMetric::DotProductthe raw inner product is negated at the boundary soiqdb_types::Hit::distanceis always smaller-is-nearer, identical across all five metrics. - Top-
kselection uses a bounded max-heap keyed on(distance, seq)viaf32::total_cmp—O(n log k), NaN-safe, and deterministic: ties break on insertion order (lower sequence number wins). - Metadata filtering goes through
iqdb_filter::FilterEvaluator; pathological filters surface asiqdb_types::IqdbError::InvalidFilterat query time, before any cluster data is touched.
§Example
use std::sync::Arc;
use iqdb_index::{Index, IndexCore};
use iqdb_ivf::{IvfConfig, IvfIndex};
use iqdb_types::{DistanceMetric, SearchParams, VectorId};
let cfg = IvfConfig::default()
.with_n_clusters(2)
.with_n_probes(2)
.with_training_sample_size(16)
.with_seed(7);
let mut idx = IvfIndex::new(2, DistanceMetric::Euclidean, cfg)?;
// Train on a representative sample before any insert / search.
let sample: Vec<Vec<f32>> = vec![
vec![0.0, 0.0], vec![0.1, -0.1], vec![-0.1, 0.1],
vec![10.0, 10.0], vec![10.1, 9.9], vec![9.9, 10.1],
];
let sample_refs: Vec<&[f32]> = sample.iter().map(|v| v.as_slice()).collect();
idx.train(&sample_refs)?;
idx.insert(VectorId::from(1u64), Arc::<[f32]>::from(&[0.0, 0.0][..]), None)?;
idx.insert(VectorId::from(2u64), Arc::<[f32]>::from(&[10.0, 10.0][..]), None)?;
let hits = idx.search(&[0.0, 0.0], &SearchParams::new(1, DistanceMetric::Euclidean))?;
assert_eq!(hits.len(), 1);
assert_eq!(hits[0].id, VectorId::U64(1));Structs§
- Hit
- One result of a similarity search: a matched record and its distance.
- IvfCluster
Stats - Diagnostic snapshot of inverted-list occupancy.
- IvfConfig
- Configuration for
crate::IvfIndexconstruction (seeiqdb_index::Index::new). - IvfIndex
- IVF-Flat approximate nearest-neighbour index.
Constants§
- VERSION
- The version of this crate, taken from
Cargo.tomlat compile time.