Skip to main content

Module ann

Module ann 

Source
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 0x07 and 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 ids

Construction 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§

HnswIndex
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 larger ef_search to 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 with intpack (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.