Skip to main content

urna_runtime/
lib.rs

1//! mmap-backed runtime for `.urna` files.
2//!
3//! Owns the mmap so `MmapUrnaFile` is `'static`. Section metadata is parsed
4//! once at open time using `UrnaView`, then the mmap is moved into `Self`
5//! and embeddings are read directly from `&self._mmap[offset..]`.
6//!
7//! Supports float32 / float16 / int8 dtypes with a SIMD dispatcher
8//! (AVX2 / NEON / scalar). Optional ANN (`hnsw`) and lexical (`bm25`)
9//! sections rerank into the exact cosine path so the final score is
10//! always the real cosine value.
11
12pub mod ann;
13mod blobs;
14pub mod bm25;
15mod dtype;
16pub mod error;
17pub mod graph;
18mod inspect;
19mod materialize;
20mod mmap_cold;
21mod mmap_file;
22mod order;
23mod rerank;
24mod search;
25pub mod simd;
26mod space_search;
27mod spaces;
28
29pub use blobs::apply_blob_span_overlay;
30pub use dtype::DType;
31pub use error::RuntimeError;
32pub use mmap_file::MmapUrnaFile;
33pub use simd::SimdBackend;
34
35#[derive(Clone, Debug, PartialEq)]
36pub struct SearchHit {
37    pub chunk_id: String,
38    pub score: f32,
39    pub score_type: &'static str,
40    pub source_uri: String,
41    pub offset_start: u64,
42    pub offset_end: u64,
43    pub embedding_model: String,
44    pub index_type: &'static str,
45    pub reranked: bool,
46    pub file_hash: String,
47    pub content_hash: String,
48    pub citation_id: String,
49}
50
51/// What precision the mandatory exact-cosine rerank read its vectors from.
52/// the honesty backbone of `--disclose explain` and `retrieve()`: every
53/// returned `score` IS a real cosine, but at WHICH precision depends on
54/// whether a full-precision `embeddings_fp` (0x09) slab is present.
55///
56/// - `FullPrecision`: a 0x09 fp slab is present (or the stored dtype is
57///   float32), so the rerank read full-precision vectors. "real cosine".
58/// - `StoredPrecision`: no fp slab and the stored dtype is lossy
59///   (float16/int8/int4), so the rerank read the stored quantized slab.
60///   "real cosine at stored precision". still a real recomputed cosine,
61///   never a candidate-generator proxy, but at the on-disk precision.
62///
63/// this enum is computed in the runtime from
64/// `embeddings_fp_slab().is_some()` + the stored dtype and never lies: a
65/// sub-int8 corpus without an fp source reports `StoredPrecision`, so a
66/// newcomer is never shown a stored-precision number as full-precision.
67#[derive(Clone, Copy, Debug, PartialEq, Eq)]
68pub enum RerankSourceKind {
69    /// score recomputed against a full-precision source (0x09 fp slab, or
70    /// the stored slab when the stored dtype is already float32).
71    FullPrecision,
72    /// score recomputed against the lossy stored slab (float16/int8/int4),
73    /// no fp source present. disclosed as "real cosine at stored precision".
74    StoredPrecision,
75}
76
77impl RerankSourceKind {
78    /// classify the precision the rerank reads from by its effective dtype
79    /// (the 0x09 fp slab's dtype when present, else the stored dtype). only
80    /// float32 is full-precision; float16/int8/int4 are stored-precision.
81    /// this is the single source of the honesty marker.
82    pub fn from_dtype(dtype: DType) -> Self {
83        match dtype {
84            DType::Float32 => Self::FullPrecision,
85            DType::Float16 | DType::Int8 | DType::Int4 => Self::StoredPrecision,
86        }
87    }
88
89    /// the one-line honesty marker for `--disclose explain` / `retrieve()`.
90    pub fn disclosure(self) -> &'static str {
91        match self {
92            Self::FullPrecision => "real cosine",
93            Self::StoredPrecision => "real cosine at stored precision",
94        }
95    }
96    /// stable machine token for the json answer-pack / SearchExplain.
97    pub fn as_str(self) -> &'static str {
98        match self {
99            Self::FullPrecision => "full_precision",
100            Self::StoredPrecision => "stored_precision",
101        }
102    }
103}
104
105/// ADDITIVE per-search provenance, attached to every `SearchResult`. zero
106/// format bytes, no `URNA_FORMAT_VERSION` bump: it is computed entirely in
107/// the runtime from the search path and the open file. feeds the lens
108/// `--disclose explain` honesty line and the agent-native `retrieve()`
109/// answer-pack. the load-bearing field is `rerank_source`.
110///
111/// candidate counts are the per-path candidate-set sizes the rerank saw
112/// (0 when that path did not run). `recall_estimate` is `1.0` only on the
113/// exact path (the recall=1.0 ground truth) and `NaN` on every candidate-
114/// generating path (ann/hybrid/graph), mirroring `SearchResult::recall`:
115/// we never claim a recall we did not measure.
116#[derive(Clone, Copy, Debug, PartialEq)]
117pub struct SearchExplain {
118    /// the route taken: "exact" | "hnsw" | "graph" | "hybrid".
119    pub route: &'static str,
120    /// exact-flat candidates considered (the whole corpus on the exact path
121    /// and the graph seed path; 0 when the path used an ann shortlist).
122    pub exact_candidates: usize,
123    /// ann shortlist size (hnsw / hybrid vector path); 0 otherwise.
124    pub ann_candidates: usize,
125    /// bm25 lexical shortlist size (hybrid path); 0 otherwise.
126    pub bm25_candidates: usize,
127    /// graph bfs frontier union size (graph path); 0 otherwise.
128    pub graph_candidates: usize,
129    /// how the candidate lists were combined: "none" | "rrf".
130    pub fusion_mode: &'static str,
131    /// the precision the mandatory exact rerank read from. the honesty
132    /// backbone: see `RerankSourceKind`.
133    pub rerank_source: RerankSourceKind,
134    /// `1.0` on the exact path, `NaN` on every candidate-generating path
135    /// (we never claim a recall we did not measure).
136    pub recall_estimate: f32,
137}
138
139impl SearchExplain {
140    /// the exact-flat path: the whole corpus scored, recall=1.0 ground
141    /// truth, no fusion.
142    pub(crate) fn exact(n: usize, src: RerankSourceKind) -> Self {
143        Self {
144            route: "exact",
145            exact_candidates: n,
146            ann_candidates: 0,
147            bm25_candidates: 0,
148            graph_candidates: 0,
149            fusion_mode: "none",
150            rerank_source: src,
151            recall_estimate: 1.0,
152        }
153    }
154
155    /// the hnsw path: an ann shortlist into the exact rerank, recall=NaN.
156    pub(crate) fn hnsw(ann: usize, src: RerankSourceKind) -> Self {
157        Self {
158            route: "hnsw",
159            exact_candidates: 0,
160            ann_candidates: ann,
161            bm25_candidates: 0,
162            graph_candidates: 0,
163            fusion_mode: "none",
164            rerank_source: src,
165            recall_estimate: f32::NAN,
166        }
167    }
168
169    /// the graph path: exact-cosine top-ef seed, bfs frontier union into
170    /// the exact rerank, recall=NaN.
171    pub(crate) fn graph(seed: usize, frontier: usize, src: RerankSourceKind) -> Self {
172        Self {
173            route: "graph",
174            exact_candidates: seed,
175            ann_candidates: 0,
176            bm25_candidates: 0,
177            graph_candidates: frontier,
178            fusion_mode: "none",
179            rerank_source: src,
180            recall_estimate: f32::NAN,
181        }
182    }
183
184    /// the hybrid path: vector (ann or exact) ∪ bm25, rrf fusion into the
185    /// exact rerank, recall=NaN.
186    pub(crate) fn hybrid(ann: usize, exact: usize, bm25: usize, src: RerankSourceKind) -> Self {
187        Self {
188            route: "hybrid",
189            exact_candidates: exact,
190            ann_candidates: ann,
191            bm25_candidates: bm25,
192            graph_candidates: 0,
193            fusion_mode: "rrf",
194            rerank_source: src,
195            recall_estimate: f32::NAN,
196        }
197    }
198}
199
200#[derive(Clone, Debug, PartialEq)]
201pub struct SearchResult {
202    pub hits: Vec<SearchHit>,
203    pub query_time_ms: f64,
204    pub index_type: &'static str,
205    pub recall: f32,
206    pub truncated: bool,
207    pub k_requested: i32,
208    pub k_returned: usize,
209    /// ADDITIVE per-search provenance (route, candidate counts, fusion
210    /// mode, rerank-source honesty marker, recall estimate). no format
211    /// bytes; computed in the runtime. see `SearchExplain`.
212    pub explain: SearchExplain,
213}