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