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