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 #[cfg(feature = "lazygraphrag")]
29 pub concept_selection: ConceptSelectionConfig,
30}
31
32impl Default for EnhancementsConfig {
33 fn default() -> Self {
34 Self {
35 enabled: true,
36 query_analysis: QueryAnalysisConfig::default(),
37 adaptive_retrieval: AdaptiveRetrievalConfig::default(),
38 performance_benchmarking: BenchmarkingConfig::default(),
39 enhanced_function_registry: FunctionRegistryConfig::default(),
40 #[cfg(feature = "lightrag")]
41 lightrag: LightRAGConfig::default(),
42 #[cfg(feature = "leiden")]
43 leiden: LeidenCommunitiesConfig::default(),
44 #[cfg(feature = "cross-encoder")]
45 cross_encoder: CrossEncoderConfig::default(),
46 #[cfg(feature = "lazygraphrag")]
47 concept_selection: ConceptSelectionConfig::default(),
48 }
49 }
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct QueryAnalysisConfig {
55 pub enabled: bool,
57 pub min_confidence: f32,
59 pub enable_strategy_suggestion: bool,
61 pub enable_keyword_analysis: bool,
63 pub enable_complexity_scoring: bool,
65}
66
67impl Default for QueryAnalysisConfig {
68 fn default() -> Self {
69 Self {
70 enabled: true,
71 min_confidence: 0.6,
72 enable_strategy_suggestion: true,
73 enable_keyword_analysis: true,
74 enable_complexity_scoring: true,
75 }
76 }
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct AdaptiveRetrievalConfig {
82 pub enabled: bool,
84 pub use_query_analysis: bool,
86 pub enable_cross_strategy_fusion: bool,
88 pub diversity_threshold: f32,
90 pub enable_diversity_selection: bool,
92 pub enable_confidence_weighting: bool,
94}
95
96impl Default for AdaptiveRetrievalConfig {
97 fn default() -> Self {
98 Self {
99 enabled: true,
100 use_query_analysis: true,
101 enable_cross_strategy_fusion: true,
102 diversity_threshold: 0.8,
103 enable_diversity_selection: true,
104 enable_confidence_weighting: true,
105 }
106 }
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct BenchmarkingConfig {
112 pub enabled: bool,
114 pub auto_recommendations: bool,
116 pub comprehensive_testing: bool,
118 pub iterations: usize,
120 pub include_parallel: bool,
122 pub enable_memory_profiling: bool,
124}
125
126impl Default for BenchmarkingConfig {
127 fn default() -> Self {
128 Self {
129 enabled: false, auto_recommendations: true,
131 comprehensive_testing: false,
132 iterations: 3,
133 include_parallel: true,
134 enable_memory_profiling: false,
135 }
136 }
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct FunctionRegistryConfig {
142 pub enabled: bool,
144 pub categorization: bool,
146 pub usage_statistics: bool,
148 pub dynamic_registration: bool,
150 pub performance_monitoring: bool,
152 pub recommendation_system: bool,
154}
155
156impl Default for FunctionRegistryConfig {
157 fn default() -> Self {
158 Self {
159 enabled: true,
160 categorization: true,
161 usage_statistics: true,
162 dynamic_registration: true,
163 performance_monitoring: false,
164 recommendation_system: true,
165 }
166 }
167}
168
169#[cfg(feature = "lightrag")]
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct LightRAGConfig {
173 pub enabled: bool,
175 pub max_keywords: usize,
177 pub high_level_weight: f32,
179 pub low_level_weight: f32,
181 pub merge_strategy: String,
183 pub language: String,
185 pub enable_cache: bool,
187}
188
189#[cfg(feature = "lightrag")]
190impl Default for LightRAGConfig {
191 fn default() -> Self {
192 Self {
193 enabled: true,
194 max_keywords: 20, high_level_weight: 0.6,
196 low_level_weight: 0.4,
197 merge_strategy: "weighted".to_string(),
198 language: "English".to_string(),
199 enable_cache: true,
200 }
201 }
202}
203
204#[cfg(feature = "leiden")]
206#[derive(Debug, Clone, Serialize, Deserialize)]
207pub struct LeidenCommunitiesConfig {
208 pub enabled: bool,
210 pub max_cluster_size: usize,
212 pub use_lcc: bool,
214 pub seed: Option<u64>,
216 pub resolution: f32,
218 pub max_levels: usize,
220 pub min_improvement: f32,
222 pub enable_hierarchical: bool,
224 pub generate_summaries: bool,
226 pub max_summary_length: usize,
228 pub use_extractive_summary: bool,
230 pub adaptive_routing: AdaptiveRoutingConfig,
232}
233
234#[derive(Debug, Clone, Serialize, Deserialize)]
236pub struct AdaptiveRoutingConfig {
237 pub enabled: bool,
239 pub default_level: usize,
241 pub keyword_weight: f32,
243 pub length_weight: f32,
245 pub entity_weight: f32,
247}
248
249impl Default for AdaptiveRoutingConfig {
250 fn default() -> Self {
251 Self {
252 enabled: true,
253 default_level: 1,
254 keyword_weight: 0.5,
255 length_weight: 0.3,
256 entity_weight: 0.2,
257 }
258 }
259}
260
261#[cfg(feature = "leiden")]
262impl Default for LeidenCommunitiesConfig {
263 fn default() -> Self {
264 Self {
265 enabled: true,
266 max_cluster_size: 10,
267 use_lcc: true,
268 seed: None,
269 resolution: 1.0,
270 max_levels: 5,
271 min_improvement: 0.001,
272 enable_hierarchical: true,
273 generate_summaries: true,
274 max_summary_length: 5,
275 use_extractive_summary: true,
276 adaptive_routing: AdaptiveRoutingConfig::default(),
277 }
278 }
279}
280
281#[cfg(feature = "cross-encoder")]
283#[derive(Debug, Clone, Serialize, Deserialize)]
284pub struct CrossEncoderConfig {
285 pub enabled: bool,
287 pub model_name: String,
289 pub max_length: usize,
291 pub batch_size: usize,
293 pub top_k: usize,
295 pub min_confidence: f32,
297 pub normalize_scores: bool,
299}
300
301#[cfg(feature = "cross-encoder")]
302impl Default for CrossEncoderConfig {
303 fn default() -> Self {
304 Self {
305 enabled: true,
306 model_name: "cross-encoder/ms-marco-MiniLM-L-6-v2".to_string(),
307 max_length: 512,
308 batch_size: 32,
309 top_k: 10,
310 min_confidence: 0.0,
311 normalize_scores: true,
312 }
313 }
314}
315
316#[cfg(feature = "lazygraphrag")]
318#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct ConceptSelectionConfig {
320 pub enabled: bool,
322 pub top_k: usize,
324 pub min_score: f32,
326 pub degree_weight: f32,
328 pub pagerank_weight: f32,
330 pub idf_weight: f32,
332 pub use_semantic_matching: bool,
334 pub max_query_concepts: usize,
336}
337
338#[cfg(feature = "lazygraphrag")]
339impl Default for ConceptSelectionConfig {
340 fn default() -> Self {
341 Self {
342 enabled: true,
343 top_k: 20,
344 min_score: 0.1,
345 degree_weight: 0.4,
346 pagerank_weight: 0.4,
347 idf_weight: 0.2,
348 use_semantic_matching: true,
349 max_query_concepts: 10,
350 }
351 }
352}
353
354impl EnhancementsConfig {
355 pub fn has_any_enabled(&self) -> bool {
357 self.enabled
358 && (self.query_analysis.enabled
359 || self.adaptive_retrieval.enabled
360 || self.performance_benchmarking.enabled
361 || self.enhanced_function_registry.enabled
362 || {
363 #[cfg(feature = "lightrag")]
364 {
365 self.lightrag.enabled
366 }
367 #[cfg(not(feature = "lightrag"))]
368 {
369 false
370 }
371 }
372 || {
373 #[cfg(feature = "leiden")]
374 {
375 self.leiden.enabled
376 }
377 #[cfg(not(feature = "leiden"))]
378 {
379 false
380 }
381 }
382 || {
383 #[cfg(feature = "cross-encoder")]
384 {
385 self.cross_encoder.enabled
386 }
387 #[cfg(not(feature = "cross-encoder"))]
388 {
389 false
390 }
391 }
392 || {
393 #[cfg(feature = "lazygraphrag")]
394 {
395 self.concept_selection.enabled
396 }
397 #[cfg(not(feature = "lazygraphrag"))]
398 {
399 false
400 }
401 })
402 }
403
404 pub fn get_enabled_enhancements(&self) -> Vec<String> {
406 let mut enabled = Vec::new();
407
408 if !self.enabled {
409 return enabled;
410 }
411
412 if self.query_analysis.enabled {
413 enabled.push("Query Analysis".to_string());
414 }
415 if self.adaptive_retrieval.enabled {
416 enabled.push("Adaptive Retrieval".to_string());
417 }
418 if self.performance_benchmarking.enabled {
419 enabled.push("Performance Benchmarking".to_string());
420 }
421 if self.enhanced_function_registry.enabled {
422 enabled.push("Enhanced Function Registry".to_string());
423 }
424 #[cfg(feature = "lightrag")]
425 if self.lightrag.enabled {
426 enabled.push("LightRAG Dual-Level Retrieval".to_string());
427 }
428 #[cfg(feature = "leiden")]
429 if self.leiden.enabled {
430 enabled.push("Leiden Community Detection".to_string());
431 }
432 #[cfg(feature = "cross-encoder")]
433 if self.cross_encoder.enabled {
434 enabled.push("Cross-Encoder Reranking".to_string());
435 }
436 #[cfg(feature = "lazygraphrag")]
437 if self.concept_selection.enabled {
438 enabled.push("Concept Selection (G2ConS)".to_string());
439 }
440
441 enabled
442 }
443
444 pub fn disable_all(&mut self) {
446 self.enabled = false;
447 }
448
449 pub fn enable_only(&mut self, components: &[&str]) {
451 self.query_analysis.enabled = false;
453 self.adaptive_retrieval.enabled = false;
454 self.performance_benchmarking.enabled = false;
455 self.enhanced_function_registry.enabled = false;
456 #[cfg(feature = "lightrag")]
457 {
458 self.lightrag.enabled = false;
459 }
460 #[cfg(feature = "leiden")]
461 {
462 self.leiden.enabled = false;
463 }
464 #[cfg(feature = "cross-encoder")]
465 {
466 self.cross_encoder.enabled = false;
467 }
468 #[cfg(feature = "lazygraphrag")]
469 {
470 self.concept_selection.enabled = false;
471 }
472
473 for component in components {
475 match component.to_lowercase().as_str() {
476 "query_analysis" | "query" => self.query_analysis.enabled = true,
477 "adaptive_retrieval" | "adaptive" => self.adaptive_retrieval.enabled = true,
478 "performance_benchmarking" | "benchmark" => {
479 self.performance_benchmarking.enabled = true
480 },
481 "enhanced_function_registry" | "registry" => {
482 self.enhanced_function_registry.enabled = true
483 },
484 #[cfg(feature = "lightrag")]
485 "lightrag" | "dual_level" => self.lightrag.enabled = true,
486 #[cfg(feature = "leiden")]
487 "leiden" | "communities" => self.leiden.enabled = true,
488 #[cfg(feature = "cross-encoder")]
489 "cross_encoder" | "reranking" => self.cross_encoder.enabled = true,
490 #[cfg(feature = "lazygraphrag")]
491 "concept_selection" | "g2cons" => self.concept_selection.enabled = true,
492 _ => eprintln!("Unknown enhancement component: {component}"),
493 }
494 }
495
496 self.enabled = true;
497 }
498
499 pub fn get_summary(&self) -> EnhancementsSummary {
501 let total = {
502 #[allow(unused_mut)] let mut count = 4; #[cfg(feature = "lightrag")]
505 {
506 count += 1;
507 }
508 #[cfg(feature = "leiden")]
509 {
510 count += 1;
511 }
512 #[cfg(feature = "cross-encoder")]
513 {
514 count += 1;
515 }
516 count
517 };
518
519 EnhancementsSummary {
520 master_enabled: self.enabled,
521 total_components: total,
522 enabled_components: self.get_enabled_enhancements().len(),
523 components: vec![
524 ComponentStatus {
525 name: "Query Analysis".to_string(),
526 enabled: self.query_analysis.enabled,
527 features: vec![
528 (
529 "Strategy Suggestion".to_string(),
530 self.query_analysis.enable_strategy_suggestion,
531 ),
532 (
533 "Keyword Analysis".to_string(),
534 self.query_analysis.enable_keyword_analysis,
535 ),
536 (
537 "Complexity Scoring".to_string(),
538 self.query_analysis.enable_complexity_scoring,
539 ),
540 ],
541 },
542 ComponentStatus {
543 name: "Adaptive Retrieval".to_string(),
544 enabled: self.adaptive_retrieval.enabled,
545 features: vec![
546 (
547 "Cross-Strategy Fusion".to_string(),
548 self.adaptive_retrieval.enable_cross_strategy_fusion,
549 ),
550 (
551 "Diversity Selection".to_string(),
552 self.adaptive_retrieval.enable_diversity_selection,
553 ),
554 (
555 "Confidence Weighting".to_string(),
556 self.adaptive_retrieval.enable_confidence_weighting,
557 ),
558 ],
559 },
560 ComponentStatus {
561 name: "Performance Benchmarking".to_string(),
562 enabled: self.performance_benchmarking.enabled,
563 features: vec![
564 (
565 "Auto Recommendations".to_string(),
566 self.performance_benchmarking.auto_recommendations,
567 ),
568 (
569 "Comprehensive Testing".to_string(),
570 self.performance_benchmarking.comprehensive_testing,
571 ),
572 (
573 "Memory Profiling".to_string(),
574 self.performance_benchmarking.enable_memory_profiling,
575 ),
576 ],
577 },
578 ComponentStatus {
579 name: "Enhanced Function Registry".to_string(),
580 enabled: self.enhanced_function_registry.enabled,
581 features: vec![
582 (
583 "Categorization".to_string(),
584 self.enhanced_function_registry.categorization,
585 ),
586 (
587 "Usage Statistics".to_string(),
588 self.enhanced_function_registry.usage_statistics,
589 ),
590 (
591 "Dynamic Registration".to_string(),
592 self.enhanced_function_registry.dynamic_registration,
593 ),
594 ],
595 },
596 #[cfg(feature = "lightrag")]
597 ComponentStatus {
598 name: "LightRAG Dual-Level Retrieval".to_string(),
599 enabled: self.lightrag.enabled,
600 features: vec![
601 (
602 "Dual-Level Keywords".to_string(),
603 true, ),
605 (
606 format!("Max Keywords: {}", self.lightrag.max_keywords),
607 true,
608 ),
609 (format!("Merge: {}", self.lightrag.merge_strategy), true),
610 ],
611 },
612 #[cfg(feature = "leiden")]
613 ComponentStatus {
614 name: "Leiden Community Detection".to_string(),
615 enabled: self.leiden.enabled,
616 features: vec![
617 (
618 format!("Max Cluster Size: {}", self.leiden.max_cluster_size),
619 true,
620 ),
621 (format!("Resolution: {:.2}", self.leiden.resolution), true),
622 (
623 "Refinement Phase".to_string(),
624 true, ),
626 (
627 "Hierarchical Clustering".to_string(),
628 self.leiden.enable_hierarchical,
629 ),
630 (
631 "Auto-Generate Summaries".to_string(),
632 self.leiden.generate_summaries,
633 ),
634 (
635 format!("Max Levels: {}", self.leiden.max_levels),
636 self.leiden.enable_hierarchical,
637 ),
638 (
639 "Adaptive Query Routing".to_string(),
640 self.leiden.adaptive_routing.enabled,
641 ),
642 ],
643 },
644 #[cfg(feature = "cross-encoder")]
645 ComponentStatus {
646 name: "Cross-Encoder Reranking".to_string(),
647 enabled: self.cross_encoder.enabled,
648 features: vec![
649 (format!("Model: {}", self.cross_encoder.model_name), true),
650 (format!("Top-K: {}", self.cross_encoder.top_k), true),
651 (
652 "Score Normalization".to_string(),
653 self.cross_encoder.normalize_scores,
654 ),
655 ],
656 },
657 ],
658 }
659 }
660}
661
662#[derive(Debug)]
664pub struct EnhancementsSummary {
665 pub master_enabled: bool,
667 pub total_components: usize,
669 pub enabled_components: usize,
671 pub components: Vec<ComponentStatus>,
673}
674
675#[derive(Debug)]
677pub struct ComponentStatus {
678 pub name: String,
680 pub enabled: bool,
682 pub features: Vec<(String, bool)>,
684}
685
686impl EnhancementsSummary {
687 pub fn print(&self) {
689 println!("🚀 GraphRAG Enhancements Configuration");
690 println!("{}", "=".repeat(50));
691 println!(
692 "Master Switch: {}",
693 if self.master_enabled {
694 "✅ Enabled"
695 } else {
696 "❌ Disabled"
697 }
698 );
699 println!(
700 "Components: {}/{} enabled",
701 self.enabled_components, self.total_components
702 );
703
704 for component in &self.components {
705 let status = if component.enabled && self.master_enabled {
706 "✅"
707 } else {
708 "❌"
709 };
710 println!("\n{} {}", status, component.name);
711
712 if component.enabled && self.master_enabled {
713 for (feature, enabled) in &component.features {
714 let feature_status = if *enabled { " ✓" } else { " ✗" };
715 println!(" {feature_status} {feature}");
716 }
717 }
718 }
719 }
720
721 pub fn get_enabled_percentage(&self) -> f32 {
723 if !self.master_enabled {
724 return 0.0;
725 }
726 (self.enabled_components as f32 / self.total_components as f32) * 100.0
727 }
728}
729
730#[cfg(test)]
731mod tests {
732 use super::*;
733
734 #[test]
735 fn test_default_config() {
736 let config = EnhancementsConfig::default();
737 assert!(config.enabled);
738 assert!(config.query_analysis.enabled);
739 assert!(config.adaptive_retrieval.enabled);
740 assert!(!config.performance_benchmarking.enabled); assert!(config.enhanced_function_registry.enabled);
742 }
743
744 #[test]
745 fn test_enable_only() {
746 let mut config = EnhancementsConfig::default();
747 config.enable_only(&["query_analysis", "adaptive_retrieval"]);
748
749 assert!(config.query_analysis.enabled);
750 assert!(config.adaptive_retrieval.enabled);
751 assert!(!config.performance_benchmarking.enabled);
752 assert!(!config.enhanced_function_registry.enabled);
753 }
754
755 #[test]
756 fn test_disable_all() {
757 let mut config = EnhancementsConfig::default();
758 config.disable_all();
759
760 assert!(!config.enabled);
761 assert!(!config.has_any_enabled());
762 }
763
764 #[test]
765 fn test_summary() {
766 let config = EnhancementsConfig::default();
767 let summary = config.get_summary();
768
769 let expected = {
770 let mut count = 4;
771 #[cfg(feature = "lightrag")]
772 {
773 count += 1;
774 }
775 #[cfg(feature = "leiden")]
776 {
777 count += 1;
778 }
779 #[cfg(feature = "cross-encoder")]
780 {
781 count += 1;
782 }
783 count
784 };
785 assert_eq!(summary.total_components, expected);
786 assert!(summary.get_enabled_percentage() > 0.0);
787 }
788}