1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct EnhancementsConfig {
8 pub enabled: bool,
10 pub query_analysis: QueryAnalysisConfig,
12 pub adaptive_retrieval: AdaptiveRetrievalConfig,
14 pub performance_benchmarking: BenchmarkingConfig,
16 pub enhanced_function_registry: FunctionRegistryConfig,
18 #[cfg(feature = "lightrag")]
20 pub lightrag: LightRAGConfig,
21 #[cfg(feature = "leiden")]
23 pub leiden: LeidenCommunitiesConfig,
24 #[cfg(feature = "cross-encoder")]
26 pub cross_encoder: CrossEncoderConfig,
27}
28
29impl Default for EnhancementsConfig {
30 fn default() -> Self {
31 Self {
32 enabled: true,
33 query_analysis: QueryAnalysisConfig::default(),
34 adaptive_retrieval: AdaptiveRetrievalConfig::default(),
35 performance_benchmarking: BenchmarkingConfig::default(),
36 enhanced_function_registry: FunctionRegistryConfig::default(),
37 #[cfg(feature = "lightrag")]
38 lightrag: LightRAGConfig::default(),
39 #[cfg(feature = "leiden")]
40 leiden: LeidenCommunitiesConfig::default(),
41 #[cfg(feature = "cross-encoder")]
42 cross_encoder: CrossEncoderConfig::default(),
43 }
44 }
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct QueryAnalysisConfig {
50 pub enabled: bool,
52 pub min_confidence: f32,
54 pub enable_strategy_suggestion: bool,
56 pub enable_keyword_analysis: bool,
58 pub enable_complexity_scoring: bool,
60}
61
62impl Default for QueryAnalysisConfig {
63 fn default() -> Self {
64 Self {
65 enabled: true,
66 min_confidence: 0.6,
67 enable_strategy_suggestion: true,
68 enable_keyword_analysis: true,
69 enable_complexity_scoring: true,
70 }
71 }
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct AdaptiveRetrievalConfig {
77 pub enabled: bool,
79 pub use_query_analysis: bool,
81 pub enable_cross_strategy_fusion: bool,
83 pub diversity_threshold: f32,
85 pub enable_diversity_selection: bool,
87 pub enable_confidence_weighting: bool,
89}
90
91impl Default for AdaptiveRetrievalConfig {
92 fn default() -> Self {
93 Self {
94 enabled: true,
95 use_query_analysis: true,
96 enable_cross_strategy_fusion: true,
97 diversity_threshold: 0.8,
98 enable_diversity_selection: true,
99 enable_confidence_weighting: true,
100 }
101 }
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct BenchmarkingConfig {
107 pub enabled: bool,
109 pub auto_recommendations: bool,
111 pub comprehensive_testing: bool,
113 pub iterations: usize,
115 pub include_parallel: bool,
117 pub enable_memory_profiling: bool,
119}
120
121impl Default for BenchmarkingConfig {
122 fn default() -> Self {
123 Self {
124 enabled: false, auto_recommendations: true,
126 comprehensive_testing: false,
127 iterations: 3,
128 include_parallel: true,
129 enable_memory_profiling: false,
130 }
131 }
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct FunctionRegistryConfig {
137 pub enabled: bool,
139 pub categorization: bool,
141 pub usage_statistics: bool,
143 pub dynamic_registration: bool,
145 pub performance_monitoring: bool,
147 pub recommendation_system: bool,
149}
150
151impl Default for FunctionRegistryConfig {
152 fn default() -> Self {
153 Self {
154 enabled: true,
155 categorization: true,
156 usage_statistics: true,
157 dynamic_registration: true,
158 performance_monitoring: false,
159 recommendation_system: true,
160 }
161 }
162}
163
164#[cfg(feature = "lightrag")]
166#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct LightRAGConfig {
168 pub enabled: bool,
170 pub max_keywords: usize,
172 pub high_level_weight: f32,
174 pub low_level_weight: f32,
176 pub merge_strategy: String,
178 pub language: String,
180 pub enable_cache: bool,
182}
183
184#[cfg(feature = "lightrag")]
185impl Default for LightRAGConfig {
186 fn default() -> Self {
187 Self {
188 enabled: true,
189 max_keywords: 20, high_level_weight: 0.6,
191 low_level_weight: 0.4,
192 merge_strategy: "weighted".to_string(),
193 language: "English".to_string(),
194 enable_cache: true,
195 }
196 }
197}
198
199#[cfg(feature = "leiden")]
201#[derive(Debug, Clone, Serialize, Deserialize)]
202pub struct LeidenCommunitiesConfig {
203 pub enabled: bool,
205 pub max_cluster_size: usize,
207 pub use_lcc: bool,
209 pub seed: Option<u64>,
211 pub resolution: f32,
213 pub max_levels: usize,
215 pub min_improvement: f32,
217 pub enable_hierarchical: bool,
219 pub generate_summaries: bool,
221 pub max_summary_length: usize,
223 pub use_extractive_summary: bool,
225 pub adaptive_routing: AdaptiveRoutingConfig,
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize)]
231pub struct AdaptiveRoutingConfig {
232 pub enabled: bool,
234 pub default_level: usize,
236 pub keyword_weight: f32,
238 pub length_weight: f32,
240 pub entity_weight: f32,
242}
243
244impl Default for AdaptiveRoutingConfig {
245 fn default() -> Self {
246 Self {
247 enabled: true,
248 default_level: 1,
249 keyword_weight: 0.5,
250 length_weight: 0.3,
251 entity_weight: 0.2,
252 }
253 }
254}
255
256#[cfg(feature = "leiden")]
257impl Default for LeidenCommunitiesConfig {
258 fn default() -> Self {
259 Self {
260 enabled: true,
261 max_cluster_size: 10,
262 use_lcc: true,
263 seed: None,
264 resolution: 1.0,
265 max_levels: 5,
266 min_improvement: 0.001,
267 enable_hierarchical: true,
268 generate_summaries: true,
269 max_summary_length: 5,
270 use_extractive_summary: true,
271 adaptive_routing: AdaptiveRoutingConfig::default(),
272 }
273 }
274}
275
276#[cfg(feature = "cross-encoder")]
278#[derive(Debug, Clone, Serialize, Deserialize)]
279pub struct CrossEncoderConfig {
280 pub enabled: bool,
282 pub model_name: String,
284 pub max_length: usize,
286 pub batch_size: usize,
288 pub top_k: usize,
290 pub min_confidence: f32,
292 pub normalize_scores: bool,
294}
295
296#[cfg(feature = "cross-encoder")]
297impl Default for CrossEncoderConfig {
298 fn default() -> Self {
299 Self {
300 enabled: true,
301 model_name: "cross-encoder/ms-marco-MiniLM-L-6-v2".to_string(),
302 max_length: 512,
303 batch_size: 32,
304 top_k: 10,
305 min_confidence: 0.0,
306 normalize_scores: true,
307 }
308 }
309}
310
311impl EnhancementsConfig {
312 pub fn has_any_enabled(&self) -> bool {
314 self.enabled
315 && (self.query_analysis.enabled
316 || self.adaptive_retrieval.enabled
317 || self.performance_benchmarking.enabled
318 || self.enhanced_function_registry.enabled
319 || {
320 #[cfg(feature = "lightrag")]
321 {
322 self.lightrag.enabled
323 }
324 #[cfg(not(feature = "lightrag"))]
325 {
326 false
327 }
328 }
329 || {
330 #[cfg(feature = "leiden")]
331 {
332 self.leiden.enabled
333 }
334 #[cfg(not(feature = "leiden"))]
335 {
336 false
337 }
338 }
339 || {
340 #[cfg(feature = "cross-encoder")]
341 {
342 self.cross_encoder.enabled
343 }
344 #[cfg(not(feature = "cross-encoder"))]
345 {
346 false
347 }
348 })
349 }
350
351 pub fn get_enabled_enhancements(&self) -> Vec<String> {
353 let mut enabled = Vec::new();
354
355 if !self.enabled {
356 return enabled;
357 }
358
359 if self.query_analysis.enabled {
360 enabled.push("Query Analysis".to_string());
361 }
362 if self.adaptive_retrieval.enabled {
363 enabled.push("Adaptive Retrieval".to_string());
364 }
365 if self.performance_benchmarking.enabled {
366 enabled.push("Performance Benchmarking".to_string());
367 }
368 if self.enhanced_function_registry.enabled {
369 enabled.push("Enhanced Function Registry".to_string());
370 }
371 #[cfg(feature = "lightrag")]
372 if self.lightrag.enabled {
373 enabled.push("LightRAG Dual-Level Retrieval".to_string());
374 }
375 #[cfg(feature = "leiden")]
376 if self.leiden.enabled {
377 enabled.push("Leiden Community Detection".to_string());
378 }
379 #[cfg(feature = "cross-encoder")]
380 if self.cross_encoder.enabled {
381 enabled.push("Cross-Encoder Reranking".to_string());
382 }
383
384 enabled
385 }
386
387 pub fn disable_all(&mut self) {
389 self.enabled = false;
390 }
391
392 pub fn enable_only(&mut self, components: &[&str]) {
394 self.query_analysis.enabled = false;
396 self.adaptive_retrieval.enabled = false;
397 self.performance_benchmarking.enabled = false;
398 self.enhanced_function_registry.enabled = false;
399 #[cfg(feature = "lightrag")]
400 {
401 self.lightrag.enabled = false;
402 }
403 #[cfg(feature = "leiden")]
404 {
405 self.leiden.enabled = false;
406 }
407 #[cfg(feature = "cross-encoder")]
408 {
409 self.cross_encoder.enabled = false;
410 }
411
412 for component in components {
414 match component.to_lowercase().as_str() {
415 "query_analysis" | "query" => self.query_analysis.enabled = true,
416 "adaptive_retrieval" | "adaptive" => self.adaptive_retrieval.enabled = true,
417 "performance_benchmarking" | "benchmark" => {
418 self.performance_benchmarking.enabled = true
419 }
420 "enhanced_function_registry" | "registry" => {
421 self.enhanced_function_registry.enabled = true
422 }
423 #[cfg(feature = "lightrag")]
424 "lightrag" | "dual_level" => self.lightrag.enabled = true,
425 #[cfg(feature = "leiden")]
426 "leiden" | "communities" => self.leiden.enabled = true,
427 #[cfg(feature = "cross-encoder")]
428 "cross_encoder" | "reranking" => self.cross_encoder.enabled = true,
429 _ => eprintln!("Unknown enhancement component: {component}"),
430 }
431 }
432
433 self.enabled = true;
434 }
435
436 pub fn get_summary(&self) -> EnhancementsSummary {
438 let total = {
439 #[allow(unused_mut)] let mut count = 4; #[cfg(feature = "lightrag")]
442 {
443 count += 1;
444 }
445 #[cfg(feature = "leiden")]
446 {
447 count += 1;
448 }
449 #[cfg(feature = "cross-encoder")]
450 {
451 count += 1;
452 }
453 count
454 };
455
456 EnhancementsSummary {
457 master_enabled: self.enabled,
458 total_components: total,
459 enabled_components: self.get_enabled_enhancements().len(),
460 components: vec![
461 ComponentStatus {
462 name: "Query Analysis".to_string(),
463 enabled: self.query_analysis.enabled,
464 features: vec![
465 (
466 "Strategy Suggestion".to_string(),
467 self.query_analysis.enable_strategy_suggestion,
468 ),
469 (
470 "Keyword Analysis".to_string(),
471 self.query_analysis.enable_keyword_analysis,
472 ),
473 (
474 "Complexity Scoring".to_string(),
475 self.query_analysis.enable_complexity_scoring,
476 ),
477 ],
478 },
479 ComponentStatus {
480 name: "Adaptive Retrieval".to_string(),
481 enabled: self.adaptive_retrieval.enabled,
482 features: vec![
483 (
484 "Cross-Strategy Fusion".to_string(),
485 self.adaptive_retrieval.enable_cross_strategy_fusion,
486 ),
487 (
488 "Diversity Selection".to_string(),
489 self.adaptive_retrieval.enable_diversity_selection,
490 ),
491 (
492 "Confidence Weighting".to_string(),
493 self.adaptive_retrieval.enable_confidence_weighting,
494 ),
495 ],
496 },
497 ComponentStatus {
498 name: "Performance Benchmarking".to_string(),
499 enabled: self.performance_benchmarking.enabled,
500 features: vec![
501 (
502 "Auto Recommendations".to_string(),
503 self.performance_benchmarking.auto_recommendations,
504 ),
505 (
506 "Comprehensive Testing".to_string(),
507 self.performance_benchmarking.comprehensive_testing,
508 ),
509 (
510 "Memory Profiling".to_string(),
511 self.performance_benchmarking.enable_memory_profiling,
512 ),
513 ],
514 },
515 ComponentStatus {
516 name: "Enhanced Function Registry".to_string(),
517 enabled: self.enhanced_function_registry.enabled,
518 features: vec![
519 (
520 "Categorization".to_string(),
521 self.enhanced_function_registry.categorization,
522 ),
523 (
524 "Usage Statistics".to_string(),
525 self.enhanced_function_registry.usage_statistics,
526 ),
527 (
528 "Dynamic Registration".to_string(),
529 self.enhanced_function_registry.dynamic_registration,
530 ),
531 ],
532 },
533 #[cfg(feature = "lightrag")]
534 ComponentStatus {
535 name: "LightRAG Dual-Level Retrieval".to_string(),
536 enabled: self.lightrag.enabled,
537 features: vec![
538 (
539 "Dual-Level Keywords".to_string(),
540 true, ),
542 (
543 format!("Max Keywords: {}", self.lightrag.max_keywords),
544 true,
545 ),
546 (
547 format!("Merge: {}", self.lightrag.merge_strategy),
548 true,
549 ),
550 ],
551 },
552 #[cfg(feature = "leiden")]
553 ComponentStatus {
554 name: "Leiden Community Detection".to_string(),
555 enabled: self.leiden.enabled,
556 features: vec![
557 (
558 format!("Max Cluster Size: {}", self.leiden.max_cluster_size),
559 true,
560 ),
561 (
562 format!("Resolution: {:.2}", self.leiden.resolution),
563 true,
564 ),
565 (
566 "Refinement Phase".to_string(),
567 true, ),
569 (
570 "Hierarchical Clustering".to_string(),
571 self.leiden.enable_hierarchical,
572 ),
573 (
574 "Auto-Generate Summaries".to_string(),
575 self.leiden.generate_summaries,
576 ),
577 (
578 format!("Max Levels: {}", self.leiden.max_levels),
579 self.leiden.enable_hierarchical,
580 ),
581 (
582 "Adaptive Query Routing".to_string(),
583 self.leiden.adaptive_routing.enabled,
584 ),
585 ],
586 },
587 #[cfg(feature = "cross-encoder")]
588 ComponentStatus {
589 name: "Cross-Encoder Reranking".to_string(),
590 enabled: self.cross_encoder.enabled,
591 features: vec![
592 (
593 format!("Model: {}", self.cross_encoder.model_name),
594 true,
595 ),
596 (
597 format!("Top-K: {}", self.cross_encoder.top_k),
598 true,
599 ),
600 (
601 "Score Normalization".to_string(),
602 self.cross_encoder.normalize_scores,
603 ),
604 ],
605 },
606 ],
607 }
608 }
609}
610
611#[derive(Debug)]
613pub struct EnhancementsSummary {
614 pub master_enabled: bool,
616 pub total_components: usize,
618 pub enabled_components: usize,
620 pub components: Vec<ComponentStatus>,
622}
623
624#[derive(Debug)]
626pub struct ComponentStatus {
627 pub name: String,
629 pub enabled: bool,
631 pub features: Vec<(String, bool)>,
633}
634
635impl EnhancementsSummary {
636 pub fn print(&self) {
638 println!("🚀 GraphRAG Enhancements Configuration");
639 println!("{}", "=".repeat(50));
640 println!(
641 "Master Switch: {}",
642 if self.master_enabled {
643 "✅ Enabled"
644 } else {
645 "❌ Disabled"
646 }
647 );
648 println!(
649 "Components: {}/{} enabled",
650 self.enabled_components, self.total_components
651 );
652
653 for component in &self.components {
654 let status = if component.enabled && self.master_enabled {
655 "✅"
656 } else {
657 "❌"
658 };
659 println!("\n{} {}", status, component.name);
660
661 if component.enabled && self.master_enabled {
662 for (feature, enabled) in &component.features {
663 let feature_status = if *enabled { " ✓" } else { " ✗" };
664 println!(" {feature_status} {feature}");
665 }
666 }
667 }
668 }
669
670 pub fn get_enabled_percentage(&self) -> f32 {
672 if !self.master_enabled {
673 return 0.0;
674 }
675 (self.enabled_components as f32 / self.total_components as f32) * 100.0
676 }
677}
678
679#[cfg(test)]
680mod tests {
681 use super::*;
682
683 #[test]
684 fn test_default_config() {
685 let config = EnhancementsConfig::default();
686 assert!(config.enabled);
687 assert!(config.query_analysis.enabled);
688 assert!(config.adaptive_retrieval.enabled);
689 assert!(!config.performance_benchmarking.enabled); assert!(config.enhanced_function_registry.enabled);
691 }
692
693 #[test]
694 fn test_enable_only() {
695 let mut config = EnhancementsConfig::default();
696 config.enable_only(&["query_analysis", "adaptive_retrieval"]);
697
698 assert!(config.query_analysis.enabled);
699 assert!(config.adaptive_retrieval.enabled);
700 assert!(!config.performance_benchmarking.enabled);
701 assert!(!config.enhanced_function_registry.enabled);
702 }
703
704 #[test]
705 fn test_disable_all() {
706 let mut config = EnhancementsConfig::default();
707 config.disable_all();
708
709 assert!(!config.enabled);
710 assert!(!config.has_any_enabled());
711 }
712
713 #[test]
714 fn test_summary() {
715 let config = EnhancementsConfig::default();
716 let summary = config.get_summary();
717
718 let expected = {
719 let mut count = 4;
720 #[cfg(feature = "lightrag")]
721 {
722 count += 1;
723 }
724 #[cfg(feature = "leiden")]
725 {
726 count += 1;
727 }
728 #[cfg(feature = "cross-encoder")]
729 {
730 count += 1;
731 }
732 count
733 };
734 assert_eq!(summary.total_components, expected);
735 assert!(summary.get_enabled_percentage() > 0.0);
736 }
737}