weavatrix_semantic/
config.rs1use crate::{Result, SemanticError};
2use weavatrix_graph::Confidence;
3
4#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
6pub enum SelectionMode {
7 #[default]
9 Mutual,
10 Union,
12 Directed,
14}
15
16impl SelectionMode {
17 pub(crate) const fn as_str(self) -> &'static str {
18 match self {
19 Self::Mutual => "mutual",
20 Self::Union => "union",
21 Self::Directed => "directed",
22 }
23 }
24}
25
26#[derive(Debug, Clone, PartialEq)]
28pub struct LinkConfig {
29 model: String,
30 min_similarity: f64,
31 top_k: usize,
32 selection: SelectionMode,
33 confidence: Confidence,
34 max_vectors: usize,
35}
36
37impl LinkConfig {
38 #[must_use]
40 pub fn new(model: impl Into<String>, min_similarity: f64, top_k: usize) -> Self {
41 Self {
42 model: model.into(),
43 min_similarity,
44 top_k,
45 selection: SelectionMode::Mutual,
46 confidence: Confidence::Low,
47 max_vectors: usize::MAX,
48 }
49 }
50
51 #[must_use]
53 pub const fn with_selection(mut self, selection: SelectionMode) -> Self {
54 self.selection = selection;
55 self
56 }
57
58 #[must_use]
60 pub const fn with_confidence(mut self, confidence: Confidence) -> Self {
61 self.confidence = confidence;
62 self
63 }
64
65 #[must_use]
71 pub const fn with_max_vectors(mut self, max_vectors: usize) -> Self {
72 self.max_vectors = max_vectors;
73 self
74 }
75
76 #[must_use]
78 pub fn model(&self) -> &str {
79 &self.model
80 }
81
82 #[must_use]
84 pub const fn min_similarity(&self) -> f64 {
85 self.min_similarity
86 }
87
88 #[must_use]
90 pub const fn top_k(&self) -> usize {
91 self.top_k
92 }
93
94 #[must_use]
96 pub const fn selection(&self) -> SelectionMode {
97 self.selection
98 }
99
100 #[must_use]
102 pub const fn confidence(&self) -> Confidence {
103 self.confidence
104 }
105
106 #[must_use]
108 pub const fn max_vectors(&self) -> usize {
109 self.max_vectors
110 }
111
112 pub(crate) fn validate(&self) -> Result<()> {
113 if self.model.is_empty() {
114 return Err(SemanticError::EmptyModel);
115 }
116 if self.model.trim() != self.model {
117 return Err(SemanticError::ModelHasSurroundingWhitespace);
118 }
119 if !self.min_similarity.is_finite() || !(0.0..=1.0).contains(&self.min_similarity) {
120 return Err(SemanticError::InvalidSimilarityThreshold);
121 }
122 if self.top_k == 0 {
123 return Err(SemanticError::ZeroTopK);
124 }
125 if self.max_vectors == 0 {
126 return Err(SemanticError::ZeroMaxVectors);
127 }
128 Ok(())
129 }
130}