Expand description
Pure-Rust HNSW index for approximate nearest neighbor search.
This is a minimal, self-contained HNSW implementation tailored to
.urna’s contract:
- Vectors are L2-normalized → distance is
1 - cosine(smaller = closer). - Index lives in section
0x07and is bit-equal across rebuilds. - Search returns a candidate set; the runtime reranks with the exact dot product against the embeddings section so the final score is the real cosine.
On-disk layout (encoding=raw, payload version 1):
u32 LE payload_version = 1
u32 LE m - out-degree at non-zero levels
u32 LE m_max0 - out-degree at level 0 (typically 2*m)
u32 LE ef_construction
u32 LE entry_point - node id of the entry vertex
u32 LE max_level - highest layer with any node (0-based)
u32 LE n_nodes - equal to header.n_embeddings
for each node i in 0..n_nodes:
u32 LE level_i - top layer this node lives in
for layer in 0..=level_i:
u32 LE k_i_l - neighbor count at this layer
u32 LE * k_i_l - neighbor idsConstruction uses HNSW (Malkov & Yashunin, 2018) with a deterministic
level distribution so the same input produces the same graph.
Neighbor selection lives in select_neighbors; today it uses the
_simple variant (top-m by distance), Phase 2 swaps in the
Algorithm 4 heuristic for higher recall.
Modules§
- select_
neighbors - neighbor selection during HNSW construction.
Structs§
- Hnsw
Index - A built HNSW index. Reads borrow from the on-disk payload at open time; the graph is owned (small relative to embeddings).
Constants§
- DEFAULT_
EF_ CONSTRUCTION - Default candidate-list size during construction. Larger = better
recall, slower build. 400 is our chosen production default -
empirically gives recall@10 ≥ 0.95 at typical corpus sizes
(n ≤ 100k, dim ≤ 768) when paired with
ef_search ≥ 400. Lower values save build time but require largeref_searchto match. - DEFAULT_
M - Default neighbor count at non-zero layers. 16 is a common HNSW sweet spot for ~1M points; for smaller corpora the recall-vs-size curve is flat enough that the default is fine.
- HNSW_
PAYLOAD_ VERSION - on-disk payload version for the hnsw section (
0x07). v1 stored every neighbour id as a raw u32; v2 bitpacks the level/count/neighbour columns withintpack(order-preserving, so the graph and its recall are unchanged). the reader still accepts v1 files. the section is optional and excluded from content_hash, so this bump is additive within v1.