1use serde::{Deserialize, Serialize};
2use std::fs;
3use std::path::Path;
4
5#[derive(Debug, Serialize, Deserialize, Clone)]
6pub struct Config {
7 pub paths: Paths,
8 pub index: Index,
9 pub search: Search,
10 pub memory_layers: MemoryLayers,
11 pub performance: Performance,
12 pub logging: Logging,
13 #[serde(default)]
14 pub embedding: Embedding,
15 #[serde(default)]
16 pub server: Server,
17 #[serde(default)]
18 pub federation: Federation,
19}
20
21#[derive(Debug, Serialize, Deserialize, Clone)]
22pub struct Paths {
23 pub layers_dir: String,
24 pub output_dir: String,
25 pub temp_dir: String,
26}
27
28#[derive(Debug, Serialize, Deserialize, Clone)]
29pub struct Index {
30 pub block_size: usize,
31 pub max_depth: u8,
32 pub header_size: usize,
33}
34
35#[derive(Debug, Serialize, Deserialize, Clone)]
36pub struct Search {
37 pub default_k: usize,
38 pub zoom_weight: f32,
39 pub keyword_boost: f32,
40 #[serde(default)]
41 pub semantic_weight: f32,
42 #[serde(default)]
43 pub emotional_bias_weight: f32,
44}
45
46#[derive(Debug, Serialize, Deserialize, Clone)]
47pub struct MemoryLayers {
48 pub layers: Vec<String>,
49}
50
51#[derive(Debug, Serialize, Deserialize, Clone)]
52pub struct Performance {
53 pub use_mmap: bool,
54 pub cache_size: usize,
55 pub build_workers: usize,
56 #[serde(default)]
57 pub use_gpu: bool,
58 #[serde(default)]
59 pub compression: bool,
60 #[serde(default = "default_cache_ttl")]
61 pub cache_ttl_secs: u64,
62}
63
64fn default_cache_ttl() -> u64 {
65 300
66}
67
68#[derive(Debug, Serialize, Deserialize, Clone)]
69pub struct Embedding {
70 #[serde(default = "default_provider")]
71 pub provider: String,
72 #[serde(default = "default_model")]
73 pub model: String,
74 #[serde(default = "default_dim")]
75 pub dim: usize,
76 #[serde(default = "default_max_depth")]
77 pub max_depth: u8,
78 #[serde(default)]
79 pub onnx_model_path: Option<String>,
80 #[serde(default)]
81 pub tokenizer_path: Option<String>,
82}
83
84fn default_provider() -> String {
85 "mock".to_string()
86}
87fn default_model() -> String {
88 "sentence-transformers/all-MiniLM-L6-v2".to_string()
89}
90fn default_dim() -> usize {
91 384
92}
93fn default_max_depth() -> u8 {
94 4
95}
96
97impl Default for Embedding {
98 fn default() -> Self {
99 Self {
100 provider: default_provider(),
101 model: default_model(),
102 dim: default_dim(),
103 max_depth: default_max_depth(),
104 onnx_model_path: None,
105 tokenizer_path: None,
106 }
107 }
108}
109
110#[derive(Debug, Serialize, Deserialize, Clone)]
111pub struct Server {
112 #[serde(default = "default_port")]
113 pub port: u16,
114 #[serde(default)]
115 pub cors_origin: Option<String>,
116}
117
118fn default_port() -> u16 {
119 6060
120}
121
122impl Default for Server {
123 fn default() -> Self {
124 Self {
125 port: default_port(),
126 cors_origin: None,
127 }
128 }
129}
130
131#[derive(Debug, Serialize, Deserialize, Clone)]
132pub struct Logging {
133 pub level: String,
134 pub file: Option<String>,
135}
136
137#[derive(Debug, Serialize, Deserialize, Clone, Default)]
138pub struct Federation {
139 #[serde(default)]
140 pub indices: Vec<FederatedIndex>,
141}
142
143#[derive(Debug, Serialize, Deserialize, Clone)]
144pub struct FederatedIndex {
145 pub name: String,
146 pub config_path: String,
147 #[serde(default = "default_weight")]
148 pub weight: f32,
149}
150
151fn default_weight() -> f32 {
152 1.0
153}
154
155impl Config {
156 pub fn load<P: AsRef<Path>>(path: P) -> Result<Self, Box<dyn std::error::Error>> {
158 if !path.as_ref().exists() {
159 return Ok(Self::default());
160 }
161
162 let file = fs::File::open(path)?;
163 let mmap = unsafe { memmap2::Mmap::map(&file)? };
165
166 let config: Config = bincode::deserialize(&mmap)?;
167 Ok(config)
168 }
169
170 pub fn save<P: AsRef<Path>>(&self, path: P) -> Result<(), Box<dyn std::error::Error>> {
172 let bytes = bincode::serialize(self)?;
173 fs::write(path, bytes)?;
174 Ok(())
175 }
176}
177
178impl Default for Config {
179 fn default() -> Self {
180 Self {
181 paths: Paths {
182 layers_dir: "./layers".to_string(),
183 output_dir: "./data".to_string(),
184 temp_dir: "./tmp".to_string(),
185 },
186 index: Index {
187 block_size: 256,
188 max_depth: 8,
189 header_size: 32,
190 },
191 search: Search {
192 default_k: 10,
193 zoom_weight: 2.0,
194 keyword_boost: 0.1,
195 semantic_weight: 0.0,
196 emotional_bias_weight: 0.0,
197 },
198 memory_layers: MemoryLayers {
199 layers: vec![
200 "long_term".to_string(),
201 "short_term".to_string(),
202 "associative".to_string(),
203 "echo_cache".to_string(),
204 ],
205 },
206 performance: Performance {
207 use_mmap: true,
208 cache_size: 64,
209 build_workers: 4,
210 use_gpu: false,
211 compression: false,
212 cache_ttl_secs: default_cache_ttl(),
213 },
214 logging: Logging {
215 level: "info".to_string(),
216 file: Some("microscope.log".to_string()),
217 },
218 embedding: Embedding::default(),
219 server: Server::default(),
220 federation: Federation::default(),
221 }
222 }
223}