Skip to main content

hyphae_retrieval/
model.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use std::time::Duration;
4
5/// One candidate vector with a globally unique binary key.
6#[derive(Clone, Debug, PartialEq)]
7pub struct VectorRecord {
8    /// Globally unique nonempty key.
9    pub key: Vec<u8>,
10    /// Finite nonzero semantic vector.
11    pub vector: Vec<f64>,
12}
13
14impl VectorRecord {
15    /// Creates a candidate. Vector invariants are validated globally during
16    /// search so malformed shards cannot yield partial results.
17    pub fn new(key: impl Into<Vec<u8>>, vector: impl Into<Vec<f64>>) -> Self {
18        Self {
19            key: key.into(),
20            vector: vector.into(),
21        }
22    }
23}
24
25/// Exact cosine search and abstention policy.
26#[derive(Clone, Debug, PartialEq)]
27pub struct RetrievalRequest {
28    /// Finite nonzero query vector.
29    pub query: Vec<f64>,
30    /// Maximum returned matches; must be nonzero.
31    pub limit: usize,
32    /// Inclusive minimum cosine score in `[-1, 1]`.
33    pub minimum_score: f64,
34    /// Minimum difference between the best and runner-up score in `[0, 2]`.
35    pub minimum_margin: f64,
36}
37
38/// Runtime and shape limits for exact global retrieval.
39#[derive(Clone, Debug, PartialEq)]
40pub struct RetrievalLimits {
41    /// Maximum candidates inspected across every shard.
42    pub max_candidates: u64,
43    /// Maximum vector dimension.
44    pub max_dimensions: usize,
45    /// Maximum requested result count.
46    pub max_returned: usize,
47    /// Cooperative monotonic timeout.
48    pub timeout: Duration,
49}
50
51impl Default for RetrievalLimits {
52    fn default() -> Self {
53        Self {
54            max_candidates: 100_000,
55            max_dimensions: 4_096,
56            max_returned: 1_000,
57            timeout: Duration::from_secs(30),
58        }
59    }
60}
61
62/// One globally ranked exact match.
63#[derive(Clone, Debug, PartialEq)]
64pub struct RetrievalMatch {
65    /// Candidate key.
66    pub key: Vec<u8>,
67    /// Exact cosine similarity in `[-1, 1]`.
68    pub score: f64,
69}
70
71/// Stable reason why semantic retrieval declined to return matches.
72#[derive(Clone, Copy, Debug, Eq, PartialEq)]
73pub enum AbstentionReason {
74    /// No candidates were available.
75    NoCandidates,
76    /// The best score was below the configured threshold.
77    BelowThreshold,
78    /// The best and runner-up scores were too close.
79    Ambiguous,
80}
81
82/// Evidence for a normal abstention outcome.
83#[derive(Clone, Debug, PartialEq)]
84pub struct Abstention {
85    /// Stable machine-readable reason.
86    pub reason: AbstentionReason,
87    /// Best observed score when candidates existed.
88    pub best_score: Option<f64>,
89    /// Runner-up score when at least two candidates existed.
90    pub runner_up_score: Option<f64>,
91    /// Global candidates inspected.
92    pub scanned_candidates: u64,
93}
94
95/// Complete exact retrieval outcome.
96#[derive(Clone, Debug, PartialEq)]
97pub enum RetrievalOutcome {
98    /// Policy accepted the globally ranked matches.
99    Matches {
100        /// Matches after global sort and final limit.
101        matches: Vec<RetrievalMatch>,
102        /// Global candidates inspected.
103        scanned_candidates: u64,
104    },
105    /// Policy explicitly declined to return semantic matches.
106    Abstained(Abstention),
107}