Skip to main content

mnem_ann/
lib.rs

1//! # mnem-ann
2//!
3//! Approximate-nearest-neighbour vector indexes for mnem. Alternative
4//! backend to [`mnem_core::index::vector::BruteForceVectorIndex`]; the
5//! trait surface is shared so a retriever built against `VectorIndex`
6//! works with either impl.
7//!
8//! | Index | Recall | Query latency | Build latency | When to use |
9//! |---|---|---|---|---|
10//! | [`mnem_core::index::vector::BruteForceVectorIndex`] | 100% | O(n * dim) | O(1) | N ≤ ~10k; cold repos; CI tests |
11//! | [`HnswVectorIndex`] (this crate, `hnsw` feature) | ~99% | O(log n * dim) | O(n * log n * dim) | N > 10k; warm long-lived servers |
12//!
13//! Both return `Vec<VectorHit>` sorted by descending score with
14//! `NodeId`-ASC tiebreak for byte-stable replay.
15//!
16//! ## Why a separate crate
17//!
18//! `mnem-core` is `#![forbid(unsafe_code)]` and WASM-clean.
19//! Most high-performance ANN implementations carry SIMD
20//! intrinsics or architecture-specific unsafe blocks that don't
21//! compile to wasm32. Keeping HNSW out of core preserves both
22//! properties; users on WASM targets simply don't depend on this
23//! crate.
24//!
25//! ## Example
26//!
27//! ```no_run
28//! use std::sync::Arc;
29//! use mnem_ann::HnswVectorIndex;
30//! use mnem_core::index::vector::VectorIndex;
31//! use mnem_core::repo::ReadonlyRepo;
32//!
33//! # fn demo(repo: &ReadonlyRepo) -> Result<(), Box<dyn std::error::Error>> {
34//! let idx = HnswVectorIndex::build_from_repo(repo, "openai:text-embedding-3-small")?;
35//! let query = vec![0.1_f32; idx.dim() as usize];
36//! let hits  = idx.search(&query, 10)?;
37//! for h in hits {
38//!     println!("{}  {:.3}", h.node_id.to_uuid_string(), h.score);
39//! }
40//! # Ok(()) }
41//! ```
42
43#![forbid(unsafe_code)]
44#![deny(missing_docs)]
45
46#[cfg(feature = "hnsw")]
47mod hnsw;
48
49pub mod knn_edges;
50
51#[cfg(feature = "hnsw")]
52pub use hnsw::{HnswConfig, HnswVectorIndex};
53
54pub use knn_edges::{DistanceMetric, KnnEdge, KnnEdgeIndex, derive_knn_edges_from_vectors};
55
56#[cfg(feature = "hnsw")]
57pub use knn_edges::derive_knn_edges;