1#![deny(missing_docs)]
2pub mod output_parser;
42pub mod plan_parser;
44
45pub use output_parser::{JsonListParser, JsonOutputParser, OutputParser, RegexOutputParser};
47pub use plan_parser::{ParsedStep, parse_plan_steps, steps_to_tasks};
48
49mod complexity;
51mod entity_enhancer;
52mod relevance_scorer;
53mod retrieval_classifier;
54mod router;
55pub mod strategies;
57mod strategy_selector;
58mod summarizer;
59mod validator;
60
61pub use complexity::{ComplexityResult, ComplexityScorer, ComplexityScorerBuilder};
62pub use entity_enhancer::{
63 EnhancedEntity, EnhancedRelationship, EnhancementResult, EntityEnhancer, EntityEnhancerBuilder,
64 RelationType, SemanticEntityType,
65};
66pub use relevance_scorer::{RelevanceResult, RelevanceScorer, RelevanceScorerBuilder};
67pub use retrieval_classifier::{
68 ClassificationResult, RetrievalClassifier, RetrievalClassifierBuilder,
69 RetrievalNeed as LocalRetrievalNeed,
70};
71pub use router::{LocalRouter, LocalRouterBuilder, RouteResult};
72pub use strategies::{
73 ChainOfThoughtStrategy, ReActStrategy, ReasoningStrategy, ReflexionStrategy, StrategyPreset,
74 StrategyStep, TreeOfThoughtsStrategy,
75};
76pub use strategy_selector::{
77 RecommendedStrategy, StrategyResult, StrategySelector, StrategySelectorBuilder, TaskType,
78};
79pub use summarizer::{
80 ExtractedFact, FactCategory, LocalSummarizer, LocalSummarizerBuilder, SummarizationResult,
81};
82pub use validator::{LocalValidator, LocalValidatorBuilder, ValidationResult};
83
84use std::time::Instant;
85use tracing::{info, warn};
86
87#[derive(Clone, Debug)]
89pub struct LocalInferenceConfig {
90 pub routing_enabled: bool,
93 pub validation_enabled: bool,
95 pub complexity_enabled: bool,
97
98 pub summarization_enabled: bool,
101 pub retrieval_gating_enabled: bool,
103 pub relevance_scoring_enabled: bool,
105 pub strategy_selection_enabled: bool,
107 pub entity_enhancement_enabled: bool,
109
110 pub routing_model: Option<String>,
113 pub validation_model: Option<String>,
115 pub complexity_model: Option<String>,
117 pub summarization_model: Option<String>,
119 pub retrieval_model: Option<String>,
121 pub relevance_model: Option<String>,
123 pub strategy_model: Option<String>,
125 pub entity_model: Option<String>,
127
128 pub log_inference: bool,
130}
131
132impl Default for LocalInferenceConfig {
133 fn default() -> Self {
134 Self {
135 routing_enabled: false,
137 validation_enabled: false,
138 complexity_enabled: false,
139 summarization_enabled: false,
141 retrieval_gating_enabled: false,
142 relevance_scoring_enabled: false,
143 strategy_selection_enabled: false,
144 entity_enhancement_enabled: false,
145 routing_model: Some("lfm2-350m".to_string()),
147 validation_model: Some("lfm2-350m".to_string()),
148 complexity_model: Some("lfm2-350m".to_string()),
149 summarization_model: Some("lfm2-1.2b".to_string()),
151 retrieval_model: Some("lfm2-350m".to_string()),
152 relevance_model: Some("lfm2-350m".to_string()),
153 strategy_model: Some("lfm2-1.2b".to_string()),
154 entity_model: Some("lfm2-350m".to_string()),
155 log_inference: true,
156 }
157 }
158}
159
160impl LocalInferenceConfig {
161 pub fn tier1_enabled() -> Self {
163 Self {
164 routing_enabled: true,
165 validation_enabled: true,
166 complexity_enabled: true,
167 ..Default::default()
168 }
169 }
170
171 pub fn tier2_enabled() -> Self {
173 Self {
174 summarization_enabled: true,
175 retrieval_gating_enabled: true,
176 relevance_scoring_enabled: true,
177 strategy_selection_enabled: true,
178 entity_enhancement_enabled: true,
179 ..Default::default()
180 }
181 }
182
183 pub fn all_enabled() -> Self {
185 Self {
186 routing_enabled: true,
187 validation_enabled: true,
188 complexity_enabled: true,
189 summarization_enabled: true,
190 retrieval_gating_enabled: true,
191 relevance_scoring_enabled: true,
192 strategy_selection_enabled: true,
193 entity_enhancement_enabled: true,
194 ..Default::default()
195 }
196 }
197
198 pub fn routing_only() -> Self {
200 Self {
201 routing_enabled: true,
202 ..Default::default()
203 }
204 }
205
206 pub fn validation_only() -> Self {
208 Self {
209 validation_enabled: true,
210 ..Default::default()
211 }
212 }
213
214 pub fn summarization_only() -> Self {
216 Self {
217 summarization_enabled: true,
218 ..Default::default()
219 }
220 }
221}
222
223pub fn log_inference(task: &str, model: &str, latency_ms: u64, success: bool) {
225 if success {
226 info!(
227 target: "local_llm",
228 task = task,
229 model = model,
230 latency_ms = latency_ms,
231 "Local inference completed"
232 );
233 } else {
234 warn!(
235 target: "local_llm",
236 task = task,
237 model = model,
238 latency_ms = latency_ms,
239 "Local inference failed, falling back to pattern-based"
240 );
241 }
242}
243
244pub struct InferenceTimer {
246 start: Instant,
247 task: String,
248 model: String,
249}
250
251impl InferenceTimer {
252 pub fn new(task: impl Into<String>, model: impl Into<String>) -> Self {
254 Self {
255 start: Instant::now(),
256 task: task.into(),
257 model: model.into(),
258 }
259 }
260
261 pub fn finish(self, success: bool) {
263 let latency_ms = self.start.elapsed().as_millis() as u64;
264 log_inference(&self.task, &self.model, latency_ms, success);
265 }
266
267 pub fn elapsed_ms(&self) -> u64 {
269 self.start.elapsed().as_millis() as u64
270 }
271}
272
273#[cfg(test)]
274mod tests {
275 use super::*;
276
277 #[test]
278 fn test_config_default() {
279 let config = LocalInferenceConfig::default();
280 assert!(!config.routing_enabled);
281 assert!(!config.validation_enabled);
282 assert!(!config.complexity_enabled);
283 assert!(!config.summarization_enabled);
284 assert!(!config.retrieval_gating_enabled);
285 assert!(!config.relevance_scoring_enabled);
286 }
287
288 #[test]
289 fn test_config_tier1_enabled() {
290 let config = LocalInferenceConfig::tier1_enabled();
291 assert!(config.routing_enabled);
292 assert!(config.validation_enabled);
293 assert!(config.complexity_enabled);
294 assert!(!config.summarization_enabled);
295 }
296
297 #[test]
298 fn test_config_tier2_enabled() {
299 let config = LocalInferenceConfig::tier2_enabled();
300 assert!(!config.routing_enabled);
301 assert!(config.summarization_enabled);
302 assert!(config.retrieval_gating_enabled);
303 assert!(config.relevance_scoring_enabled);
304 assert!(config.strategy_selection_enabled);
305 assert!(config.entity_enhancement_enabled);
306 }
307
308 #[test]
309 fn test_config_all_enabled() {
310 let config = LocalInferenceConfig::all_enabled();
311 assert!(config.routing_enabled);
312 assert!(config.validation_enabled);
313 assert!(config.complexity_enabled);
314 assert!(config.summarization_enabled);
315 assert!(config.retrieval_gating_enabled);
316 assert!(config.relevance_scoring_enabled);
317 assert!(config.strategy_selection_enabled);
318 assert!(config.entity_enhancement_enabled);
319 }
320
321 #[test]
322 fn test_config_summarization_only() {
323 let config = LocalInferenceConfig::summarization_only();
324 assert!(!config.routing_enabled);
325 assert!(config.summarization_enabled);
326 assert_eq!(config.summarization_model, Some("lfm2-1.2b".to_string()));
327 }
328
329 #[test]
330 fn test_inference_timer() {
331 let timer = InferenceTimer::new("test_task", "test_model");
332 std::thread::sleep(std::time::Duration::from_millis(10));
333 assert!(timer.elapsed_ms() >= 10);
334 }
335}