1use crate::types::*;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct EngineConfig {
9 pub dim: u32,
11
12 pub metric: Metric,
14
15 pub bps: BpsConfig,
17
18 pub rdf: RdfConfig,
20
21 pub rerank: RerankConfig,
23
24 pub router: RouterConfig,
26
27 pub lsm: LsmConfig,
29
30 pub query: QueryConfig,
32}
33
34impl Default for EngineConfig {
35 fn default() -> Self {
36 Self {
37 dim: DEFAULT_DIM,
38 metric: Metric::DotProduct,
39 bps: BpsConfig::default(),
40 rdf: RdfConfig::default(),
41 rerank: RerankConfig::default(),
42 router: RouterConfig::default(),
43 lsm: LsmConfig::default(),
44 query: QueryConfig::default(),
45 }
46 }
47}
48
49impl EngineConfig {
50 pub fn with_dim(dim: u32) -> Self {
52 let num_blocks = (dim + DEFAULT_BPS_BLOCK_SIZE as u32 - 1) / DEFAULT_BPS_BLOCK_SIZE as u32;
53 Self {
54 dim,
55 bps: BpsConfig {
56 block_size: DEFAULT_BPS_BLOCK_SIZE,
57 num_blocks: num_blocks as u16,
58 ..Default::default()
59 },
60 ..Default::default()
61 }
62 }
63
64 pub fn padded_dim(&self) -> u32 {
66 let mut p = 1u32;
67 while p < self.dim {
68 p *= 2;
69 }
70 p
71 }
72
73 pub fn validate(&self) -> crate::Result<()> {
75 if self.dim == 0 {
76 return Err(crate::Error::Config("Dimension must be > 0".into()));
77 }
78 if self.bps.block_size == 0 {
79 return Err(crate::Error::Config("BPS block size must be > 0".into()));
80 }
81 if self.rdf.top_t == 0 {
82 return Err(crate::Error::Config("RDF top_t must be > 0".into()));
83 }
84 Ok(())
85 }
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct BpsConfig {
91 pub block_size: u16,
93 pub num_blocks: u16,
95 pub num_projections: u16,
97}
98
99impl BpsConfig {
100 pub const MAX_SAFE_SLOTS: u32 = 257;
103
104 pub fn validate(&self) -> Result<(), String> {
107 let total_slots = self.num_blocks as u32 * self.num_projections as u32;
108 if total_slots > Self::MAX_SAFE_SLOTS {
109 return Err(format!(
110 "BPS configuration would overflow u16: {} blocks × {} projections = {} slots (max {})",
111 self.num_blocks,
112 self.num_projections,
113 total_slots,
114 Self::MAX_SAFE_SLOTS
115 ));
116 }
117 Ok(())
118 }
119
120 pub fn max_distance(&self) -> u32 {
122 self.num_blocks as u32 * self.num_projections as u32 * 255
123 }
124}
125
126impl Default for BpsConfig {
127 fn default() -> Self {
128 let num_blocks =
129 (DEFAULT_DIM + DEFAULT_BPS_BLOCK_SIZE as u32 - 1) / DEFAULT_BPS_BLOCK_SIZE as u32;
130 Self {
131 block_size: DEFAULT_BPS_BLOCK_SIZE,
132 num_blocks: num_blocks as u16,
133 num_projections: DEFAULT_BPS_PROJECTIONS,
134 }
135 }
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize)]
140pub struct RdfConfig {
141 pub top_t: u16,
143 pub stripe_shift: u8,
145 pub stop_dim_threshold: u32,
147 pub idf_weight: f32,
149 pub var_weight: f32,
151}
152
153impl Default for RdfConfig {
154 fn default() -> Self {
155 Self {
156 top_t: DEFAULT_RDF_TOP_T,
157 stripe_shift: DEFAULT_STRIPE_SHIFT,
158 stop_dim_threshold: DEFAULT_STOP_DIM_THRESHOLD,
159 idf_weight: 0.5,
160 var_weight: 0.5,
161 }
162 }
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct RerankConfig {
168 pub num_outliers: u8,
170 pub percentile_quantization: bool,
172 pub scale_percentile: f32,
174}
175
176impl Default for RerankConfig {
177 fn default() -> Self {
178 Self {
179 num_outliers: DEFAULT_NUM_OUTLIERS,
180 percentile_quantization: true,
181 scale_percentile: 0.99,
182 }
183 }
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct RouterConfig {
189 pub n_lists: u32,
191 pub n_probe: u32,
193 pub enabled: bool,
195}
196
197impl Default for RouterConfig {
198 fn default() -> Self {
199 Self {
200 n_lists: 128,
201 n_probe: 8,
202 enabled: false,
203 }
204 }
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct LsmConfig {
210 pub max_mutable_size: usize,
212 pub max_segments: usize,
214 pub compaction_ratio: usize,
216}
217
218impl Default for LsmConfig {
219 fn default() -> Self {
220 Self {
221 max_mutable_size: 100_000,
222 max_segments: 8,
223 compaction_ratio: 4,
224 }
225 }
226}
227
228#[derive(Debug, Clone, Serialize, Deserialize)]
230pub struct QueryConfig {
231 pub k: usize,
233 pub l_a: usize,
235 pub l_b: usize,
237 pub r: usize,
239 pub adaptive: bool,
241 pub widening_factor: f32,
243 pub score_gap_threshold: f32,
245}
246
247impl Default for QueryConfig {
248 fn default() -> Self {
249 Self {
250 k: 10,
251 l_a: 5000,
252 l_b: 20000,
253 r: 500,
254 adaptive: true,
255 widening_factor: 2.0,
256 score_gap_threshold: 0.1,
257 }
258 }
259}