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}