1pub use crate::interpretability::{
28 ActionableInsight,
29 AttentionAnalysisResult,
31 AttentionBottleneck,
32 AttentionFlowAnalysis,
33 AttentionFlowPath,
34 AttentionHeadResult,
35 AttentionInsight,
36 AttentionLayerResult,
37 AttentionPatterns,
38 AttentionStatistics,
39 AttributionMethod,
40
41 AttributionMethodResult,
42 AttributionVisualizationData,
43 BlockPattern,
44 BottleneckType,
45 BoundaryCrossingPoint,
46 ChangeDirection,
47 Counterfactual,
48 CounterfactualQualityMetrics,
49 CounterfactualResult,
51 DecisionBoundaryAnalysis,
52 DiagonalPattern,
53 FeatureAttribution,
54 FeatureAttributionResult,
56 FeatureChange,
57 FeatureContribution,
58 FeatureImportance,
59 FeatureInteraction,
60 FeatureSensitivityAnalysis,
61 FlowEfficiencyMetrics,
62 FlowTransformation,
63 HeadCluster,
64 HeadRedundancyAnalysis,
65 HeadSpecializationAnalysis,
66 HeadSpecializationType,
67 ImplementationDifficulty,
68 InsightType,
69
70 InteractionEffect,
71 InteractionEffectType,
72 InteractionType,
73
74 InterpretabilityAnalyzer,
76
77 InterpretabilityConfig,
79 InterpretabilityReport,
81 LayerAttentionPatterns,
82 LayerAttentionStats,
83 LayerFlowStats,
84 LayerFlowStep,
85 LimeAnalysisResult,
87 MethodAgreementAnalysis,
88 NeighborhoodStats,
89
90 PerturbationAnalysis,
91 PerturbationResult,
92 PruningImpact,
93 PruningRecommendation,
94 RedundancyType,
95 RedundantHeadPair,
96 RepetitivePattern,
97 RiskLevel,
98 ShapAnalysisResult,
100 ShapSummary,
101
102 SparsityDistribution,
103 SpecializationEvolution,
104 SpecializationTransition,
105 SpecializationTrend,
106 ThresholdAnalysis,
107 TimeHorizon,
108
109 TimelinePoint,
110 TokenAttentionScore,
111 TopFeature,
112 VerticalPattern,
113};
114
115#[cfg(test)]
116mod tests {
117 use crate::interpretability::{
118 AttributionMethod, InterpretabilityAnalyzer, InterpretabilityConfig,
119 };
120 use std::collections::HashMap;
121
122 #[tokio::test]
123 async fn test_interpretability_analyzer_creation() {
124 let config = InterpretabilityConfig::default();
125 let _analyzer = InterpretabilityAnalyzer::new(config);
126 }
127
128 #[tokio::test]
129 async fn test_shap_analysis() {
130 let config = InterpretabilityConfig::default();
131 let mut analyzer = InterpretabilityAnalyzer::new(config);
132
133 let mut instance = HashMap::new();
134 instance.insert("feature1".to_string(), 1.0);
135 instance.insert("feature2".to_string(), 2.0);
136
137 let model_predictions = vec![0.8, 0.7, 0.9];
138 let background_data = vec![{
139 let mut bg = HashMap::new();
140 bg.insert("feature1".to_string(), 0.5);
141 bg.insert("feature2".to_string(), 1.0);
142 bg
143 }];
144
145 let result = analyzer.analyze_shap(&instance, &model_predictions, &background_data).await;
146 assert!(result.is_ok());
147 }
148
149 #[tokio::test]
150 async fn test_lime_analysis() {
151 let config = InterpretabilityConfig::default();
152 let mut analyzer = InterpretabilityAnalyzer::new(config);
153
154 let mut instance = HashMap::new();
155 instance.insert("feature1".to_string(), 1.0);
156 instance.insert("feature2".to_string(), 2.0);
157
158 let model_fn: Box<dyn Fn(&HashMap<String, f64>) -> f64> =
159 Box::new(|input: &HashMap<String, f64>| input.values().sum::<f64>() * 0.1);
160
161 let result = analyzer.analyze_lime(&instance, model_fn).await;
162 assert!(result.is_ok());
163 }
164
165 #[tokio::test]
166 async fn test_feature_attribution_integrated_gradients() {
167 let config = InterpretabilityConfig {
168 enable_feature_attribution: true,
169 attribution_methods: vec![AttributionMethod::IntegratedGradients],
170 ..InterpretabilityConfig::default()
171 };
172 let mut analyzer = InterpretabilityAnalyzer::new(config);
173
174 let mut instance = HashMap::new();
175 instance.insert("feature1".to_string(), 0.5);
176 instance.insert("feature2".to_string(), 1.5);
177 instance.insert("feature3".to_string(), 2.0);
178
179 let model_predictions = vec![0.7, 0.6, 0.8];
180 let background_data = vec![{
181 let mut bg = HashMap::new();
182 bg.insert("feature1".to_string(), 0.0);
183 bg.insert("feature2".to_string(), 0.0);
184 bg.insert("feature3".to_string(), 0.0);
185 bg
186 }];
187
188 let result = analyzer.analyze_shap(&instance, &model_predictions, &background_data).await;
189 assert!(result.is_ok());
190 let shap_result = result.expect("SHAP analysis failed");
191 assert!(
192 !shap_result.feature_contributions.is_empty(),
193 "attributions must be non-empty"
194 );
195 }
196}