Skip to main content

trustformers_debug/
llm_debugging.rs

1//! Large Language Model (LLM) Specific Debugging
2//!
3//! This module provides specialized debugging capabilities for large language models,
4//! focusing on safety, alignment, factuality, toxicity detection, and performance
5//! characteristics specific to modern LLMs.
6// reason: debug/profiling scaffolding — structs are constructed and their fields/methods
7// are retained for the data model, serialization completeness, and future consumers that
8// do not yet read every member. Consolidated from many item-level #[allow(dead_code)].
9#![allow(dead_code)]
10
11use anyhow::Result;
12// use scirs2_core::ndarray::*; // SciRS2 Integration Policy - was: use ndarray::{Array, ArrayD, IxDyn};
13use serde::{Deserialize, Serialize};
14use std::collections::{HashMap, HashSet};
15use std::time::{Duration, Instant};
16
17/// Main LLM debugging framework
18#[derive(Debug)]
19pub struct LLMDebugger {
20    config: LLMDebugConfig,
21    safety_analyzer: SafetyAnalyzer,
22    factuality_checker: FactualityChecker,
23    alignment_monitor: AlignmentMonitor,
24    hallucination_detector: HallucinationDetector,
25    bias_detector: BiasDetector,
26    performance_profiler: LLMPerformanceProfiler,
27    conversation_analyzer: ConversationAnalyzer,
28}
29
30/// Configuration for LLM debugging
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct LLMDebugConfig {
33    /// Enable safety analysis (toxicity, harmful content)
34    pub enable_safety_analysis: bool,
35    /// Enable factuality checking
36    pub enable_factuality_checking: bool,
37    /// Enable alignment monitoring
38    pub enable_alignment_monitoring: bool,
39    /// Enable hallucination detection
40    pub enable_hallucination_detection: bool,
41    /// Enable bias detection
42    pub enable_bias_detection: bool,
43    /// Enable performance profiling for LLM-specific metrics
44    pub enable_llm_performance_profiling: bool,
45    /// Enable conversation flow analysis
46    pub enable_conversation_analysis: bool,
47    /// Threshold for safety score (0.0 to 1.0)
48    pub safety_threshold: f32,
49    /// Threshold for factuality score (0.0 to 1.0)
50    pub factuality_threshold: f32,
51    /// Maximum conversation length to analyze
52    pub max_conversation_length: usize,
53    /// Sampling rate for expensive analyses
54    pub analysis_sampling_rate: f32,
55}
56
57impl Default for LLMDebugConfig {
58    fn default() -> Self {
59        Self {
60            enable_safety_analysis: true,
61            enable_factuality_checking: true,
62            enable_alignment_monitoring: true,
63            enable_hallucination_detection: true,
64            enable_bias_detection: true,
65            enable_llm_performance_profiling: true,
66            enable_conversation_analysis: true,
67            safety_threshold: 0.8,
68            factuality_threshold: 0.7,
69            max_conversation_length: 100,
70            analysis_sampling_rate: 1.0,
71        }
72    }
73}
74
75/// Safety analyzer for detecting harmful, toxic, or inappropriate content
76#[derive(Debug)]
77pub struct SafetyAnalyzer {
78    toxic_patterns: HashSet<String>,
79    harm_categories: Vec<HarmCategory>,
80    safety_metrics: SafetyMetrics,
81}
82
83/// Categories of potential harm in LLM outputs
84#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
85pub enum HarmCategory {
86    Toxicity,       // Toxic, offensive, or inappropriate language
87    Violence,       // Violence or threats
88    SelfHarm,       // Self-harm or suicide-related content
89    Harassment,     // Harassment or bullying
90    HateSpeech,     // Hate speech or discrimination
91    Sexual,         // Sexual or adult content
92    Privacy,        // Privacy violations or doxxing
93    Misinformation, // Misinformation or conspiracy theories
94    Manipulation,   // Social manipulation or deception
95    Illegal,        // Illegal activities or advice
96}
97
98/// Safety metrics for tracking harmful content
99#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct SafetyMetrics {
101    pub overall_safety_score: f32,
102    pub harm_category_scores: HashMap<HarmCategory, f32>,
103    pub flagged_responses: usize,
104    pub total_responses_analyzed: usize,
105    pub average_response_safety: f32,
106    pub safety_trend: SafetyTrend,
107}
108
109/// Trend in safety scores over time
110#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
111pub enum SafetyTrend {
112    Improving,
113    Stable,
114    Degrading,
115    Volatile,
116}
117
118/// Factuality checker for verifying the accuracy of LLM outputs
119#[derive(Debug)]
120pub struct FactualityChecker {
121    fact_databases: Vec<String>,
122    uncertainty_indicators: HashSet<String>,
123    factuality_metrics: FactualityMetrics,
124}
125
126/// Metrics for tracking factual accuracy
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct FactualityMetrics {
129    pub overall_factuality_score: f32,
130    pub verified_facts: usize,
131    pub unverified_claims: usize,
132    pub conflicting_information: usize,
133    pub uncertainty_expressions: usize,
134    pub knowledge_gaps: Vec<String>,
135    pub confidence_distribution: Vec<f32>,
136}
137
138/// Alignment monitor for ensuring LLM outputs align with intended behavior
139#[derive(Debug)]
140pub struct AlignmentMonitor {
141    alignment_objectives: Vec<AlignmentObjective>,
142    alignment_metrics: AlignmentMetrics,
143    value_alignment_score: f32,
144}
145
146/// Types of alignment objectives for LLMs
147#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
148pub enum AlignmentObjective {
149    Helpfulness,    // Be helpful and informative
150    Harmlessness,   // Avoid causing harm
151    Honesty,        // Be truthful and transparent
152    Fairness,       // Treat all users fairly
153    Privacy,        // Respect privacy and confidentiality
154    Transparency,   // Be clear about limitations
155    Consistency,    // Maintain consistent behavior
156    Responsibility, // Take appropriate responsibility for outputs
157}
158
159/// Metrics for alignment monitoring
160#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct AlignmentMetrics {
162    pub objective_scores: HashMap<AlignmentObjective, f32>,
163    pub overall_alignment_score: f32,
164    pub alignment_violations: usize,
165    pub value_consistency_score: f32,
166    pub behavioral_drift: f32,
167    pub alignment_trend: AlignmentTrend,
168}
169
170/// Trend in alignment scores over time
171#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
172pub enum AlignmentTrend {
173    Improving,
174    Stable,
175    Degrading,
176    Inconsistent,
177}
178
179/// Hallucination detector for identifying false or fabricated information
180#[derive(Debug)]
181pub struct HallucinationDetector {
182    confidence_thresholds: HashMap<String, f32>,
183    consistency_checker: ConsistencyChecker,
184    hallucination_metrics: HallucinationMetrics,
185}
186
187/// Metrics for hallucination detection
188#[derive(Debug, Clone, Serialize, Deserialize)]
189pub struct HallucinationMetrics {
190    pub hallucination_rate: f32,
191    pub confidence_accuracy_correlation: f32,
192    pub factual_consistency_score: f32,
193    pub internal_consistency_score: f32,
194    pub source_attribution_accuracy: f32,
195    pub detected_fabrications: usize,
196    pub uncertain_responses: usize,
197}
198
199/// Consistency checker for internal consistency in responses
200#[derive(Debug)]
201pub struct ConsistencyChecker {
202    previous_responses: Vec<String>,
203    consistency_cache: HashMap<String, f32>,
204}
205
206/// Bias detector for identifying various forms of bias in LLM outputs
207#[derive(Debug)]
208pub struct BiasDetector {
209    bias_categories: Vec<BiasCategory>,
210    demographic_groups: Vec<String>,
211    bias_metrics: BiasMetrics,
212}
213
214/// Types of bias to detect in LLM outputs
215#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
216pub enum BiasCategory {
217    Gender,        // Gender-based bias
218    Race,          // Racial or ethnic bias
219    Religion,      // Religious bias
220    Age,           // Age-based bias
221    SocioEconomic, // Socioeconomic bias
222    Geographic,    // Geographic or cultural bias
223    Political,     // Political bias
224    Linguistic,    // Language or accent bias
225    Ability,       // Disability or ability bias
226    Appearance,    // Physical appearance bias
227}
228
229/// Metrics for bias detection
230#[derive(Debug, Clone, Serialize, Deserialize)]
231pub struct BiasMetrics {
232    pub overall_bias_score: f32,
233    pub bias_category_scores: HashMap<BiasCategory, f32>,
234    pub demographic_fairness: HashMap<String, f32>,
235    pub representation_bias: f32,
236    pub stereotype_propagation: f32,
237    pub bias_amplification: f32,
238    pub fairness_violations: usize,
239}
240
241/// Performance profiler specific to LLM characteristics
242#[derive(Debug)]
243pub struct LLMPerformanceProfiler {
244    generation_metrics: GenerationMetrics,
245    efficiency_metrics: EfficiencyMetrics,
246    quality_metrics: QualityMetrics,
247    scalability_metrics: ScalabilityMetrics,
248}
249
250/// Metrics for text generation performance
251#[derive(Debug, Clone, Serialize, Deserialize)]
252pub struct GenerationMetrics {
253    pub tokens_per_second: f32,
254    pub average_response_length: f32,
255    pub generation_latency_p50: f32,
256    pub generation_latency_p95: f32,
257    pub generation_latency_p99: f32,
258    pub first_token_latency: f32,
259    pub completion_rate: f32,
260    pub timeout_rate: f32,
261}
262
263/// Metrics for computational efficiency
264#[derive(Debug, Clone, Serialize, Deserialize)]
265pub struct EfficiencyMetrics {
266    pub memory_efficiency: f32,
267    pub compute_utilization: f32,
268    pub energy_consumption: f32,
269    pub carbon_footprint_estimate: f32,
270    pub cost_per_token: f32,
271    pub batch_processing_efficiency: f32,
272    pub cache_hit_rate: f32,
273}
274
275/// Metrics for output quality
276#[derive(Debug, Clone, Serialize, Deserialize)]
277pub struct QualityMetrics {
278    pub coherence_score: f32,
279    pub relevance_score: f32,
280    pub fluency_score: f32,
281    pub informativeness_score: f32,
282    pub creativity_score: f32,
283    pub factual_accuracy: f32,
284    pub readability_score: f32,
285    pub engagement_score: f32,
286}
287
288/// Metrics for scalability analysis
289#[derive(Debug, Clone, Serialize, Deserialize)]
290pub struct ScalabilityMetrics {
291    pub concurrent_user_capacity: usize,
292    pub throughput_scaling: f32,
293    pub memory_scaling: f32,
294    pub latency_degradation: f32,
295    pub bottleneck_analysis: Vec<String>,
296    pub resource_utilization_efficiency: f32,
297}
298
299/// Conversation analyzer for multi-turn dialog analysis
300#[derive(Debug)]
301pub struct ConversationAnalyzer {
302    conversation_history: Vec<ConversationTurn>,
303    dialog_metrics: DialogMetrics,
304    context_tracking: ContextTracker,
305}
306
307/// Single turn in a conversation
308#[derive(Debug, Clone, Serialize, Deserialize)]
309pub struct ConversationTurn {
310    pub turn_id: usize,
311    pub user_input: String,
312    pub model_response: String,
313    pub timestamp: chrono::DateTime<chrono::Utc>,
314    pub context_length: usize,
315    pub response_time: Duration,
316}
317
318/// Metrics for dialog analysis
319#[derive(Debug, Clone, Serialize, Deserialize)]
320pub struct DialogMetrics {
321    pub conversation_coherence: f32,
322    pub context_maintenance: f32,
323    pub topic_consistency: f32,
324    pub response_appropriateness: f32,
325    pub conversation_engagement: f32,
326    pub turn_taking_naturalness: f32,
327    pub memory_utilization: f32,
328    pub dialog_success_rate: f32,
329}
330
331/// Context tracking for conversation continuity
332#[derive(Debug)]
333pub struct ContextTracker {
334    active_topics: HashSet<String>,
335    entity_mentions: HashMap<String, usize>,
336    context_window: Vec<String>,
337    attention_weights: Vec<f32>,
338}
339
340impl LLMDebugger {
341    /// Create a new LLM debugger
342    pub fn new(config: LLMDebugConfig) -> Self {
343        Self {
344            config: config.clone(),
345            safety_analyzer: SafetyAnalyzer::new(&config),
346            factuality_checker: FactualityChecker::new(&config),
347            alignment_monitor: AlignmentMonitor::new(&config),
348            hallucination_detector: HallucinationDetector::new(&config),
349            bias_detector: BiasDetector::new(&config),
350            performance_profiler: LLMPerformanceProfiler::new(),
351            conversation_analyzer: ConversationAnalyzer::new(&config),
352        }
353    }
354
355    /// Comprehensive LLM analysis of a model response
356    pub async fn analyze_response(
357        &mut self,
358        user_input: &str,
359        model_response: &str,
360        context: Option<&[String]>,
361        generation_metrics: Option<GenerationMetrics>,
362    ) -> Result<LLMAnalysisReport> {
363        let start_time = Instant::now();
364
365        // Safety analysis
366        let safety_analysis = if self.config.enable_safety_analysis {
367            Some(self.safety_analyzer.analyze_safety(model_response).await?)
368        } else {
369            None
370        };
371
372        // Factuality checking
373        let factuality_analysis = if self.config.enable_factuality_checking {
374            Some(self.factuality_checker.check_factuality(model_response, context).await?)
375        } else {
376            None
377        };
378
379        // Alignment monitoring
380        let alignment_analysis = if self.config.enable_alignment_monitoring {
381            Some(self.alignment_monitor.check_alignment(user_input, model_response).await?)
382        } else {
383            None
384        };
385
386        // Hallucination detection
387        let hallucination_analysis = if self.config.enable_hallucination_detection {
388            Some(
389                self.hallucination_detector
390                    .detect_hallucinations(model_response, context)
391                    .await?,
392            )
393        } else {
394            None
395        };
396
397        // Bias detection
398        let bias_analysis = if self.config.enable_bias_detection {
399            Some(self.bias_detector.detect_bias(model_response).await?)
400        } else {
401            None
402        };
403
404        // Performance profiling
405        let performance_analysis = if self.config.enable_llm_performance_profiling {
406            Some(
407                self.performance_profiler
408                    .profile_response(model_response, generation_metrics)
409                    .await?,
410            )
411        } else {
412            None
413        };
414
415        // Conversation analysis (if part of a dialog)
416        let conversation_analysis = if self.config.enable_conversation_analysis {
417            let turn = ConversationTurn {
418                turn_id: self.conversation_analyzer.conversation_history.len(),
419                user_input: user_input.to_string(),
420                model_response: model_response.to_string(),
421                timestamp: chrono::Utc::now(),
422                context_length: context.map(|c| c.len()).unwrap_or(0),
423                response_time: start_time.elapsed(),
424            };
425            Some(self.conversation_analyzer.analyze_turn(&turn).await?)
426        } else {
427            None
428        };
429
430        let analysis_duration = start_time.elapsed();
431
432        Ok(LLMAnalysisReport {
433            input: user_input.to_string(),
434            response: model_response.to_string(),
435            safety_analysis: safety_analysis.clone(),
436            factuality_analysis: factuality_analysis.clone(),
437            alignment_analysis: alignment_analysis.clone(),
438            hallucination_analysis,
439            bias_analysis,
440            performance_analysis,
441            conversation_analysis,
442            overall_score: self.compute_overall_score(
443                &safety_analysis,
444                &factuality_analysis,
445                &alignment_analysis,
446            ),
447            recommendations: self.generate_recommendations(
448                &safety_analysis,
449                &factuality_analysis,
450                &alignment_analysis,
451            ),
452            analysis_duration,
453            timestamp: chrono::Utc::now(),
454        })
455    }
456
457    /// Batch analysis of multiple responses
458    pub async fn analyze_batch(
459        &mut self,
460        interactions: &[(String, String)], // (input, response) pairs
461    ) -> Result<BatchLLMAnalysisReport> {
462        let mut individual_reports = Vec::new();
463        let mut batch_metrics = BatchMetrics::default();
464
465        for (input, response) in interactions {
466            let report = self.analyze_response(input, response, None, None).await?;
467            batch_metrics.update_from_report(&report);
468            individual_reports.push(report);
469        }
470
471        batch_metrics.finalize(interactions.len());
472
473        Ok(BatchLLMAnalysisReport {
474            individual_reports,
475            batch_metrics,
476            batch_size: interactions.len(),
477            analysis_timestamp: chrono::Utc::now(),
478        })
479    }
480
481    /// Generate comprehensive LLM health report
482    pub async fn generate_health_report(&mut self) -> Result<LLMHealthReport> {
483        Ok(LLMHealthReport {
484            overall_health_score: self.compute_overall_health(),
485            safety_health: self.safety_analyzer.get_health_summary(),
486            factuality_health: self.factuality_checker.get_health_summary(),
487            alignment_health: self.alignment_monitor.get_health_summary(),
488            bias_health: self.bias_detector.get_health_summary(),
489            performance_health: self.performance_profiler.get_health_summary(),
490            conversation_health: self.conversation_analyzer.get_health_summary(),
491            critical_issues: self.identify_critical_issues(),
492            recommendations: self.generate_health_recommendations(),
493            report_timestamp: chrono::Utc::now(),
494        })
495    }
496
497    /// Compute overall score from analysis components
498    fn compute_overall_score(
499        &self,
500        safety: &Option<SafetyAnalysisResult>,
501        factuality: &Option<FactualityAnalysisResult>,
502        alignment: &Option<AlignmentAnalysisResult>,
503    ) -> f32 {
504        let mut total_score = 0.0;
505        let mut weight_sum = 0.0;
506
507        if let Some(s) = safety {
508            total_score += s.safety_score * 0.3;
509            weight_sum += 0.3;
510        }
511
512        if let Some(f) = factuality {
513            total_score += f.factuality_score * 0.3;
514            weight_sum += 0.3;
515        }
516
517        if let Some(a) = alignment {
518            total_score += a.alignment_score * 0.4;
519            weight_sum += 0.4;
520        }
521
522        if weight_sum > 0.0 {
523            total_score / weight_sum
524        } else {
525            0.0
526        }
527    }
528
529    /// Generate actionable recommendations
530    fn generate_recommendations(
531        &self,
532        safety: &Option<SafetyAnalysisResult>,
533        factuality: &Option<FactualityAnalysisResult>,
534        alignment: &Option<AlignmentAnalysisResult>,
535    ) -> Vec<String> {
536        let mut recommendations = Vec::new();
537
538        if let Some(s) = safety {
539            if s.safety_score < self.config.safety_threshold {
540                recommendations
541                    .push("Consider additional safety filtering or fine-tuning".to_string());
542            }
543        }
544
545        if let Some(f) = factuality {
546            if f.factuality_score < self.config.factuality_threshold {
547                recommendations
548                    .push("Verify factual claims and consider knowledge base updates".to_string());
549            }
550        }
551
552        if let Some(a) = alignment {
553            if a.alignment_score < 0.7 {
554                recommendations.push(
555                    "Review alignment objectives and consider additional RLHF training".to_string(),
556                );
557            }
558        }
559
560        recommendations
561    }
562
563    /// Compute overall health score
564    fn compute_overall_health(&self) -> f32 {
565        // Simplified implementation - would aggregate across all analyzers
566        (self.safety_analyzer.safety_metrics.overall_safety_score
567            + self.factuality_checker.factuality_metrics.overall_factuality_score
568            + self.alignment_monitor.alignment_metrics.overall_alignment_score)
569            / 3.0
570    }
571
572    /// Identify critical issues requiring immediate attention
573    fn identify_critical_issues(&self) -> Vec<CriticalIssue> {
574        let mut issues = Vec::new();
575
576        // Check safety issues
577        if self.safety_analyzer.safety_metrics.overall_safety_score < 0.5 {
578            issues.push(CriticalIssue {
579                category: IssueCategory::Safety,
580                severity: IssueSeverity::Critical,
581                description: "Low overall safety score detected".to_string(),
582                recommended_action: "Immediate safety review and filtering required".to_string(),
583            });
584        }
585
586        // Check alignment issues
587        if self.alignment_monitor.alignment_metrics.overall_alignment_score < 0.6 {
588            issues.push(CriticalIssue {
589                category: IssueCategory::Alignment,
590                severity: IssueSeverity::High,
591                description: "Alignment drift detected".to_string(),
592                recommended_action: "Review training data and consider alignment fine-tuning"
593                    .to_string(),
594            });
595        }
596
597        issues
598    }
599
600    /// Generate health improvement recommendations
601    fn generate_health_recommendations(&self) -> Vec<String> {
602        let mut recommendations = Vec::new();
603
604        // Add safety recommendations
605        if self.safety_analyzer.safety_metrics.overall_safety_score < 0.8 {
606            recommendations.push("Implement additional safety training data".to_string());
607            recommendations.push("Consider constitutional AI techniques".to_string());
608        }
609
610        // Add performance recommendations
611        if self.performance_profiler.generation_metrics.tokens_per_second < 50.0 {
612            recommendations.push("Optimize inference pipeline for better throughput".to_string());
613            recommendations.push("Consider model quantization or distillation".to_string());
614        }
615
616        recommendations
617    }
618}
619
620// Analysis result structures
621#[derive(Debug, Clone, Serialize, Deserialize)]
622pub struct LLMAnalysisReport {
623    pub input: String,
624    pub response: String,
625    pub safety_analysis: Option<SafetyAnalysisResult>,
626    pub factuality_analysis: Option<FactualityAnalysisResult>,
627    pub alignment_analysis: Option<AlignmentAnalysisResult>,
628    pub hallucination_analysis: Option<HallucinationAnalysisResult>,
629    pub bias_analysis: Option<BiasAnalysisResult>,
630    pub performance_analysis: Option<PerformanceAnalysisResult>,
631    pub conversation_analysis: Option<ConversationAnalysisResult>,
632    pub overall_score: f32,
633    pub recommendations: Vec<String>,
634    pub analysis_duration: Duration,
635    pub timestamp: chrono::DateTime<chrono::Utc>,
636}
637
638#[derive(Debug, Clone, Serialize, Deserialize)]
639pub struct BatchLLMAnalysisReport {
640    pub individual_reports: Vec<LLMAnalysisReport>,
641    pub batch_metrics: BatchMetrics,
642    pub batch_size: usize,
643    pub analysis_timestamp: chrono::DateTime<chrono::Utc>,
644}
645
646#[derive(Debug, Clone, Default, Serialize, Deserialize)]
647pub struct BatchMetrics {
648    pub average_overall_score: f32,
649    pub average_safety_score: f32,
650    pub average_factuality_score: f32,
651    pub average_alignment_score: f32,
652    pub flagged_responses_count: usize,
653    pub critical_issues_count: usize,
654    pub performance_summary: Option<PerformanceAnalysisResult>,
655}
656
657impl BatchMetrics {
658    pub fn update_from_report(&mut self, _report: &LLMAnalysisReport) {
659        // Implementation would accumulate metrics from individual reports
660    }
661
662    pub fn finalize(&mut self, _batch_size: usize) {
663        // Implementation would compute final averages
664    }
665}
666
667#[derive(Debug, Clone, Serialize, Deserialize)]
668pub struct LLMHealthReport {
669    pub overall_health_score: f32,
670    pub safety_health: HealthSummary,
671    pub factuality_health: HealthSummary,
672    pub alignment_health: HealthSummary,
673    pub bias_health: HealthSummary,
674    pub performance_health: HealthSummary,
675    pub conversation_health: HealthSummary,
676    pub critical_issues: Vec<CriticalIssue>,
677    pub recommendations: Vec<String>,
678    pub report_timestamp: chrono::DateTime<chrono::Utc>,
679}
680
681#[derive(Debug, Clone, Serialize, Deserialize)]
682pub struct HealthSummary {
683    pub score: f32,
684    pub status: HealthStatus,
685    pub trend: String,
686    pub key_metrics: HashMap<String, f32>,
687    pub issues: Vec<String>,
688}
689
690#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
691pub enum HealthStatus {
692    Excellent,
693    Good,
694    Fair,
695    Poor,
696    Critical,
697}
698
699#[derive(Debug, Clone, Serialize, Deserialize)]
700pub struct CriticalIssue {
701    pub category: IssueCategory,
702    pub severity: IssueSeverity,
703    pub description: String,
704    pub recommended_action: String,
705}
706
707#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
708pub enum IssueCategory {
709    Safety,
710    Factuality,
711    Alignment,
712    Bias,
713    Performance,
714    Conversation,
715}
716
717#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
718pub enum IssueSeverity {
719    Low,
720    Medium,
721    High,
722    Critical,
723}
724
725// Individual analysis result types
726#[derive(Debug, Clone, Serialize, Deserialize)]
727pub struct SafetyAnalysisResult {
728    pub safety_score: f32,
729    pub detected_harms: Vec<HarmCategory>,
730    pub risk_level: RiskLevel,
731    pub flagged_content: Vec<String>,
732    pub confidence: f32,
733}
734
735#[derive(Debug, Clone, Serialize, Deserialize)]
736pub struct FactualityAnalysisResult {
737    pub factuality_score: f32,
738    pub verified_claims: usize,
739    pub unverified_claims: usize,
740    pub confidence_scores: Vec<f32>,
741    pub knowledge_gaps: Vec<String>,
742}
743
744#[derive(Debug, Clone, Serialize, Deserialize)]
745pub struct AlignmentAnalysisResult {
746    pub alignment_score: f32,
747    pub objective_scores: HashMap<AlignmentObjective, f32>,
748    pub violations: Vec<String>,
749    pub consistency_score: f32,
750}
751
752#[derive(Debug, Clone, Serialize, Deserialize)]
753pub struct HallucinationAnalysisResult {
754    pub hallucination_probability: f32,
755    pub confidence_accuracy: f32,
756    pub internal_consistency: f32,
757    pub detected_fabrications: Vec<String>,
758}
759
760#[derive(Debug, Clone, Serialize, Deserialize)]
761pub struct BiasAnalysisResult {
762    pub overall_bias_score: f32,
763    pub bias_categories: HashMap<BiasCategory, f32>,
764    pub detected_biases: Vec<String>,
765    pub fairness_violations: Vec<String>,
766}
767
768#[derive(Debug, Clone, Serialize, Deserialize)]
769pub struct PerformanceAnalysisResult {
770    pub generation_metrics: GenerationMetrics,
771    pub efficiency_metrics: EfficiencyMetrics,
772    pub quality_metrics: QualityMetrics,
773    pub bottlenecks: Vec<String>,
774}
775
776#[derive(Debug, Clone, Serialize, Deserialize)]
777pub struct ConversationAnalysisResult {
778    pub dialog_metrics: DialogMetrics,
779    pub context_consistency: f32,
780    pub turn_quality: f32,
781    pub engagement_score: f32,
782}
783
784#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
785pub enum RiskLevel {
786    Low,
787    Medium,
788    High,
789    Critical,
790}
791
792// Implementation stubs for analyzer components
793impl SafetyAnalyzer {
794    pub fn new(_config: &LLMDebugConfig) -> Self {
795        Self {
796            toxic_patterns: HashSet::new(),
797            harm_categories: vec![
798                HarmCategory::Toxicity,
799                HarmCategory::Violence,
800                HarmCategory::SelfHarm,
801                HarmCategory::Harassment,
802                HarmCategory::HateSpeech,
803            ],
804            safety_metrics: SafetyMetrics {
805                overall_safety_score: 1.0,
806                harm_category_scores: HashMap::new(),
807                flagged_responses: 0,
808                total_responses_analyzed: 0,
809                average_response_safety: 1.0,
810                safety_trend: SafetyTrend::Stable,
811            },
812        }
813    }
814
815    pub async fn analyze_safety(&mut self, response: &str) -> Result<SafetyAnalysisResult> {
816        // Simplified implementation - would use actual safety models
817        let safety_score = self.compute_safety_score(response);
818        let detected_harms = self.detect_harmful_content(response);
819        let risk_level = self.assess_risk_level(safety_score);
820
821        self.safety_metrics.total_responses_analyzed += 1;
822        if safety_score < 0.8 {
823            self.safety_metrics.flagged_responses += 1;
824        }
825
826        Ok(SafetyAnalysisResult {
827            safety_score,
828            detected_harms,
829            risk_level,
830            flagged_content: vec![], // Would be populated with actual flagged content
831            confidence: 0.85,
832        })
833    }
834
835    fn compute_safety_score(&self, response: &str) -> f32 {
836        // Simplified scoring - real implementation would use trained safety models
837        let harmful_keywords = ["violence", "harm", "toxic", "hate"];
838        let found_harmful = harmful_keywords
839            .iter()
840            .any(|&keyword| response.to_lowercase().contains(keyword));
841
842        if found_harmful {
843            0.3
844        } else {
845            0.95
846        }
847    }
848
849    fn detect_harmful_content(&self, response: &str) -> Vec<HarmCategory> {
850        // Simplified detection - real implementation would use specialized classifiers
851        let mut detected = Vec::new();
852
853        if response.to_lowercase().contains("violence") {
854            detected.push(HarmCategory::Violence);
855        }
856        if response.to_lowercase().contains("toxic") {
857            detected.push(HarmCategory::Toxicity);
858        }
859
860        detected
861    }
862
863    fn assess_risk_level(&self, safety_score: f32) -> RiskLevel {
864        if safety_score >= 0.9 {
865            RiskLevel::Low
866        } else if safety_score >= 0.7 {
867            RiskLevel::Medium
868        } else if safety_score >= 0.5 {
869            RiskLevel::High
870        } else {
871            RiskLevel::Critical
872        }
873    }
874
875    pub fn get_health_summary(&self) -> HealthSummary {
876        HealthSummary {
877            score: self.safety_metrics.overall_safety_score,
878            status: if self.safety_metrics.overall_safety_score >= 0.9 {
879                HealthStatus::Excellent
880            } else if self.safety_metrics.overall_safety_score >= 0.7 {
881                HealthStatus::Good
882            } else {
883                HealthStatus::Poor
884            },
885            trend: format!("{:?}", self.safety_metrics.safety_trend),
886            key_metrics: HashMap::new(),
887            issues: vec![],
888        }
889    }
890}
891
892impl FactualityChecker {
893    pub fn new(_config: &LLMDebugConfig) -> Self {
894        Self {
895            fact_databases: vec!["wikipedia".to_string(), "wikidata".to_string()],
896            uncertainty_indicators: ["might", "possibly", "unclear", "uncertain"]
897                .iter()
898                .map(|s| s.to_string())
899                .collect(),
900            factuality_metrics: FactualityMetrics {
901                overall_factuality_score: 0.8,
902                verified_facts: 0,
903                unverified_claims: 0,
904                conflicting_information: 0,
905                uncertainty_expressions: 0,
906                knowledge_gaps: vec![],
907                confidence_distribution: vec![],
908            },
909        }
910    }
911
912    pub async fn check_factuality(
913        &mut self,
914        response: &str,
915        _context: Option<&[String]>,
916    ) -> Result<FactualityAnalysisResult> {
917        // Simplified implementation - would use actual fact-checking models
918        let factuality_score = self.compute_factuality_score(response);
919        let verified_claims = self.count_verified_claims(response);
920        let unverified_claims = self.count_unverified_claims(response);
921
922        Ok(FactualityAnalysisResult {
923            factuality_score,
924            verified_claims,
925            unverified_claims,
926            confidence_scores: vec![0.8, 0.7, 0.9], // Mock scores
927            knowledge_gaps: vec![],                 // Would be populated with actual gaps
928        })
929    }
930
931    fn compute_factuality_score(&self, response: &str) -> f32 {
932        // Simplified scoring - real implementation would verify against knowledge bases
933        if response.contains("fact") {
934            0.9
935        } else {
936            0.7
937        }
938    }
939
940    fn count_verified_claims(&self, response: &str) -> usize {
941        // Simplified counting - would extract and verify actual claims
942        response.split('.').filter(|s| s.len() > 10).count()
943    }
944
945    fn count_unverified_claims(&self, response: &str) -> usize {
946        // Simplified counting - would identify unverifiable claims
947        self.uncertainty_indicators
948            .iter()
949            .map(|indicator| response.matches(indicator).count())
950            .sum()
951    }
952
953    pub fn get_health_summary(&self) -> HealthSummary {
954        HealthSummary {
955            score: self.factuality_metrics.overall_factuality_score,
956            status: HealthStatus::Good,
957            trend: "Stable".to_string(),
958            key_metrics: HashMap::new(),
959            issues: vec![],
960        }
961    }
962}
963
964impl AlignmentMonitor {
965    pub fn new(_config: &LLMDebugConfig) -> Self {
966        Self {
967            alignment_objectives: vec![
968                AlignmentObjective::Helpfulness,
969                AlignmentObjective::Harmlessness,
970                AlignmentObjective::Honesty,
971                AlignmentObjective::Fairness,
972            ],
973            alignment_metrics: AlignmentMetrics {
974                objective_scores: HashMap::new(),
975                overall_alignment_score: 0.85,
976                alignment_violations: 0,
977                value_consistency_score: 0.9,
978                behavioral_drift: 0.1,
979                alignment_trend: AlignmentTrend::Stable,
980            },
981            value_alignment_score: 0.85,
982        }
983    }
984
985    pub async fn check_alignment(
986        &mut self,
987        input: &str,
988        response: &str,
989    ) -> Result<AlignmentAnalysisResult> {
990        let alignment_score = self.compute_alignment_score(input, response);
991        let objective_scores = self.assess_objectives(input, response);
992
993        Ok(AlignmentAnalysisResult {
994            alignment_score,
995            objective_scores,
996            violations: vec![], // Would be populated with actual violations
997            consistency_score: 0.9,
998        })
999    }
1000
1001    fn compute_alignment_score(&self, _input: &str, _response: &str) -> f32 {
1002        // Simplified alignment scoring
1003        0.85
1004    }
1005
1006    fn assess_objectives(&self, _input: &str, _response: &str) -> HashMap<AlignmentObjective, f32> {
1007        let mut scores = HashMap::new();
1008        scores.insert(AlignmentObjective::Helpfulness, 0.9);
1009        scores.insert(AlignmentObjective::Harmlessness, 0.95);
1010        scores.insert(AlignmentObjective::Honesty, 0.8);
1011        scores.insert(AlignmentObjective::Fairness, 0.85);
1012        scores
1013    }
1014
1015    pub fn get_health_summary(&self) -> HealthSummary {
1016        HealthSummary {
1017            score: self.alignment_metrics.overall_alignment_score,
1018            status: HealthStatus::Good,
1019            trend: "Stable".to_string(),
1020            key_metrics: HashMap::new(),
1021            issues: vec![],
1022        }
1023    }
1024}
1025
1026impl HallucinationDetector {
1027    pub fn new(_config: &LLMDebugConfig) -> Self {
1028        Self {
1029            confidence_thresholds: HashMap::new(),
1030            consistency_checker: ConsistencyChecker {
1031                previous_responses: Vec::new(),
1032                consistency_cache: HashMap::new(),
1033            },
1034            hallucination_metrics: HallucinationMetrics {
1035                hallucination_rate: 0.1,
1036                confidence_accuracy_correlation: 0.7,
1037                factual_consistency_score: 0.8,
1038                internal_consistency_score: 0.85,
1039                source_attribution_accuracy: 0.9,
1040                detected_fabrications: 0,
1041                uncertain_responses: 0,
1042            },
1043        }
1044    }
1045
1046    pub async fn detect_hallucinations(
1047        &mut self,
1048        response: &str,
1049        _context: Option<&[String]>,
1050    ) -> Result<HallucinationAnalysisResult> {
1051        let hallucination_probability = self.compute_hallucination_probability(response);
1052        let confidence_accuracy = self.assess_confidence_accuracy(response);
1053        let internal_consistency = self.consistency_checker.check_consistency(response);
1054
1055        Ok(HallucinationAnalysisResult {
1056            hallucination_probability,
1057            confidence_accuracy,
1058            internal_consistency,
1059            detected_fabrications: vec![], // Would be populated with actual fabrications
1060        })
1061    }
1062
1063    fn compute_hallucination_probability(&self, response: &str) -> f32 {
1064        // Simplified probability computation
1065        if response.contains("I'm not sure") {
1066            0.2
1067        } else {
1068            0.1
1069        }
1070    }
1071
1072    fn assess_confidence_accuracy(&self, _response: &str) -> f32 {
1073        // Simplified confidence assessment
1074        0.7
1075    }
1076}
1077
1078impl ConsistencyChecker {
1079    pub fn check_consistency(&mut self, response: &str) -> f32 {
1080        self.previous_responses.push(response.to_string());
1081        // Simplified consistency checking
1082        0.85
1083    }
1084}
1085
1086impl BiasDetector {
1087    pub fn new(_config: &LLMDebugConfig) -> Self {
1088        Self {
1089            bias_categories: vec![
1090                BiasCategory::Gender,
1091                BiasCategory::Race,
1092                BiasCategory::Religion,
1093                BiasCategory::Age,
1094            ],
1095            demographic_groups: vec![
1096                "male".to_string(),
1097                "female".to_string(),
1098                "young".to_string(),
1099                "elderly".to_string(),
1100            ],
1101            bias_metrics: BiasMetrics {
1102                overall_bias_score: 0.1, // Lower is better for bias
1103                bias_category_scores: HashMap::new(),
1104                demographic_fairness: HashMap::new(),
1105                representation_bias: 0.1,
1106                stereotype_propagation: 0.05,
1107                bias_amplification: 0.08,
1108                fairness_violations: 0,
1109            },
1110        }
1111    }
1112
1113    pub async fn detect_bias(&mut self, response: &str) -> Result<BiasAnalysisResult> {
1114        let overall_bias_score = self.compute_overall_bias_score(response);
1115        let bias_categories = self.analyze_bias_categories(response);
1116
1117        Ok(BiasAnalysisResult {
1118            overall_bias_score,
1119            bias_categories,
1120            detected_biases: vec![], // Would be populated with actual biases
1121            fairness_violations: vec![], // Would be populated with violations
1122        })
1123    }
1124
1125    fn compute_overall_bias_score(&self, _response: &str) -> f32 {
1126        // Simplified bias scoring
1127        0.1
1128    }
1129
1130    fn analyze_bias_categories(&self, _response: &str) -> HashMap<BiasCategory, f32> {
1131        let mut scores = HashMap::new();
1132        scores.insert(BiasCategory::Gender, 0.1);
1133        scores.insert(BiasCategory::Race, 0.05);
1134        scores.insert(BiasCategory::Religion, 0.08);
1135        scores
1136    }
1137
1138    pub fn get_health_summary(&self) -> HealthSummary {
1139        HealthSummary {
1140            score: 1.0 - self.bias_metrics.overall_bias_score, // Invert since lower bias is better
1141            status: HealthStatus::Good,
1142            trend: "Stable".to_string(),
1143            key_metrics: HashMap::new(),
1144            issues: vec![],
1145        }
1146    }
1147}
1148
1149impl Default for LLMPerformanceProfiler {
1150    fn default() -> Self {
1151        Self::new()
1152    }
1153}
1154
1155impl LLMPerformanceProfiler {
1156    pub fn new() -> Self {
1157        Self {
1158            generation_metrics: GenerationMetrics {
1159                tokens_per_second: 100.0,
1160                average_response_length: 150.0,
1161                generation_latency_p50: 200.0,
1162                generation_latency_p95: 500.0,
1163                generation_latency_p99: 1000.0,
1164                first_token_latency: 50.0,
1165                completion_rate: 0.98,
1166                timeout_rate: 0.02,
1167            },
1168            efficiency_metrics: EfficiencyMetrics {
1169                memory_efficiency: 0.85,
1170                compute_utilization: 0.75,
1171                energy_consumption: 0.5,        // kWh per 1000 tokens
1172                carbon_footprint_estimate: 0.1, // kg CO2 per 1000 tokens
1173                cost_per_token: 0.001,          // USD per token
1174                batch_processing_efficiency: 0.9,
1175                cache_hit_rate: 0.7,
1176            },
1177            quality_metrics: QualityMetrics {
1178                coherence_score: 0.9,
1179                relevance_score: 0.85,
1180                fluency_score: 0.95,
1181                informativeness_score: 0.8,
1182                creativity_score: 0.7,
1183                factual_accuracy: 0.85,
1184                readability_score: 0.9,
1185                engagement_score: 0.8,
1186            },
1187            scalability_metrics: ScalabilityMetrics {
1188                concurrent_user_capacity: 1000,
1189                throughput_scaling: 0.8,
1190                memory_scaling: 0.7,
1191                latency_degradation: 0.1,
1192                bottleneck_analysis: vec!["Memory bandwidth".to_string()],
1193                resource_utilization_efficiency: 0.8,
1194            },
1195        }
1196    }
1197
1198    pub async fn profile_response(
1199        &mut self,
1200        _response: &str,
1201        generation_metrics: Option<GenerationMetrics>,
1202    ) -> Result<PerformanceAnalysisResult> {
1203        let gen_metrics = generation_metrics.unwrap_or_else(|| self.generation_metrics.clone());
1204
1205        Ok(PerformanceAnalysisResult {
1206            generation_metrics: gen_metrics,
1207            efficiency_metrics: self.efficiency_metrics.clone(),
1208            quality_metrics: self.quality_metrics.clone(),
1209            bottlenecks: vec![], // Would be populated with identified bottlenecks
1210        })
1211    }
1212
1213    pub fn get_health_summary(&self) -> HealthSummary {
1214        HealthSummary {
1215            score: (self.generation_metrics.tokens_per_second / 200.0).min(1.0),
1216            status: HealthStatus::Good,
1217            trend: "Stable".to_string(),
1218            key_metrics: HashMap::new(),
1219            issues: vec![],
1220        }
1221    }
1222}
1223
1224impl ConversationAnalyzer {
1225    pub fn new(_config: &LLMDebugConfig) -> Self {
1226        Self {
1227            conversation_history: Vec::new(),
1228            dialog_metrics: DialogMetrics {
1229                conversation_coherence: 0.9,
1230                context_maintenance: 0.85,
1231                topic_consistency: 0.8,
1232                response_appropriateness: 0.9,
1233                conversation_engagement: 0.75,
1234                turn_taking_naturalness: 0.8,
1235                memory_utilization: 0.7,
1236                dialog_success_rate: 0.85,
1237            },
1238            context_tracking: ContextTracker {
1239                active_topics: HashSet::new(),
1240                entity_mentions: HashMap::new(),
1241                context_window: Vec::new(),
1242                attention_weights: Vec::new(),
1243            },
1244        }
1245    }
1246
1247    pub async fn analyze_turn(
1248        &mut self,
1249        turn: &ConversationTurn,
1250    ) -> Result<ConversationAnalysisResult> {
1251        self.conversation_history.push(turn.clone());
1252        self.context_tracking.update_from_turn(turn);
1253
1254        Ok(ConversationAnalysisResult {
1255            dialog_metrics: self.dialog_metrics.clone(),
1256            context_consistency: self.compute_context_consistency(),
1257            turn_quality: self.assess_turn_quality(turn),
1258            engagement_score: self.compute_engagement_score(),
1259        })
1260    }
1261
1262    fn compute_context_consistency(&self) -> f32 {
1263        // Simplified context consistency computation
1264        0.85
1265    }
1266
1267    fn assess_turn_quality(&self, _turn: &ConversationTurn) -> f32 {
1268        // Simplified turn quality assessment
1269        0.9
1270    }
1271
1272    fn compute_engagement_score(&self) -> f32 {
1273        // Simplified engagement scoring
1274        0.8
1275    }
1276
1277    pub fn get_health_summary(&self) -> HealthSummary {
1278        HealthSummary {
1279            score: self.dialog_metrics.conversation_coherence,
1280            status: HealthStatus::Good,
1281            trend: "Stable".to_string(),
1282            key_metrics: HashMap::new(),
1283            issues: vec![],
1284        }
1285    }
1286}
1287
1288impl ContextTracker {
1289    pub fn update_from_turn(&mut self, turn: &ConversationTurn) {
1290        // Update context tracking based on the turn
1291        self.context_window.push(turn.model_response.clone());
1292        if self.context_window.len() > 10 {
1293            self.context_window.remove(0);
1294        }
1295    }
1296}
1297
1298/// Convenience macros for LLM debugging
1299#[macro_export]
1300macro_rules! debug_llm_response {
1301    ($debugger:expr, $input:expr, $response:expr) => {
1302        $debugger.analyze_response($input, $response, None, None).await
1303    };
1304}
1305
1306#[macro_export]
1307macro_rules! debug_llm_batch {
1308    ($debugger:expr, $interactions:expr) => {
1309        $debugger.analyze_batch($interactions).await
1310    };
1311}
1312
1313/// Create a new LLM debugger with default configuration
1314pub fn llm_debugger() -> LLMDebugger {
1315    LLMDebugger::new(LLMDebugConfig::default())
1316}
1317
1318/// Create a new LLM debugger with custom configuration
1319pub fn llm_debugger_with_config(config: LLMDebugConfig) -> LLMDebugger {
1320    LLMDebugger::new(config)
1321}
1322
1323/// Create a safety-focused LLM debugger configuration
1324pub fn safety_focused_config() -> LLMDebugConfig {
1325    LLMDebugConfig {
1326        enable_safety_analysis: true,
1327        enable_factuality_checking: true,
1328        enable_alignment_monitoring: true,
1329        enable_hallucination_detection: true,
1330        enable_bias_detection: true,
1331        enable_llm_performance_profiling: false,
1332        enable_conversation_analysis: false,
1333        safety_threshold: 0.9,
1334        factuality_threshold: 0.8,
1335        max_conversation_length: 50,
1336        analysis_sampling_rate: 1.0,
1337    }
1338}
1339
1340/// Create a performance-focused LLM debugger configuration
1341pub fn performance_focused_config() -> LLMDebugConfig {
1342    LLMDebugConfig {
1343        enable_safety_analysis: false,
1344        enable_factuality_checking: false,
1345        enable_alignment_monitoring: false,
1346        enable_hallucination_detection: false,
1347        enable_bias_detection: false,
1348        enable_llm_performance_profiling: true,
1349        enable_conversation_analysis: true,
1350        safety_threshold: 0.7,
1351        factuality_threshold: 0.6,
1352        max_conversation_length: 200,
1353        analysis_sampling_rate: 0.1,
1354    }
1355}
1356
1357/// Tests for LLM debugging functionality
1358#[cfg(test)]
1359mod tests {
1360    use super::*;
1361
1362    #[tokio::test]
1363    async fn test_llm_debugger_creation() {
1364        let debugger = llm_debugger();
1365        assert!(debugger.config.enable_safety_analysis);
1366    }
1367
1368    #[tokio::test]
1369    async fn test_safety_analysis() {
1370        let mut debugger = llm_debugger();
1371        let result = debugger
1372            .analyze_response(
1373                "How are you?",
1374                "I'm doing well, thank you for asking!",
1375                None,
1376                None,
1377            )
1378            .await;
1379
1380        assert!(result.is_ok());
1381        let report = result.expect("operation failed in test");
1382        assert!(report.safety_analysis.is_some());
1383        assert!(report.overall_score > 0.0);
1384    }
1385
1386    #[tokio::test]
1387    async fn test_batch_analysis() {
1388        let mut debugger = llm_debugger();
1389        let interactions = vec![
1390            ("Hello".to_string(), "Hi there!".to_string()),
1391            ("How are you?".to_string(), "I'm good!".to_string()),
1392        ];
1393
1394        let result = debugger.analyze_batch(&interactions).await;
1395        assert!(result.is_ok());
1396
1397        let batch_report = result.expect("operation failed in test");
1398        assert_eq!(batch_report.batch_size, 2);
1399        assert_eq!(batch_report.individual_reports.len(), 2);
1400    }
1401
1402    #[tokio::test]
1403    async fn test_health_report_generation() {
1404        let mut debugger = llm_debugger();
1405        let health_report = debugger.generate_health_report().await;
1406
1407        assert!(health_report.is_ok());
1408        let report = health_report.expect("operation failed in test");
1409        assert!(report.overall_health_score > 0.0);
1410    }
1411
1412    #[tokio::test]
1413    async fn test_safety_focused_config() {
1414        let config = safety_focused_config();
1415        assert!(config.enable_safety_analysis);
1416        assert!(config.enable_bias_detection);
1417        assert!(!config.enable_llm_performance_profiling);
1418        assert_eq!(config.safety_threshold, 0.9);
1419    }
1420
1421    #[tokio::test]
1422    async fn test_performance_focused_config() {
1423        let config = performance_focused_config();
1424        assert!(!config.enable_safety_analysis);
1425        assert!(config.enable_llm_performance_profiling);
1426        assert!(config.enable_conversation_analysis);
1427        assert_eq!(config.analysis_sampling_rate, 0.1);
1428    }
1429
1430    #[test]
1431    fn test_default_llm_debug_config() {
1432        let config = LLMDebugConfig::default();
1433        assert!(config.enable_safety_analysis);
1434        assert!(config.enable_factuality_checking);
1435        assert!(config.enable_alignment_monitoring);
1436        assert!(config.enable_hallucination_detection);
1437        assert!(config.enable_bias_detection);
1438        assert!(config.enable_llm_performance_profiling);
1439        assert!(config.enable_conversation_analysis);
1440        assert!((config.safety_threshold - 0.8).abs() < 1e-9);
1441        assert!((config.factuality_threshold - 0.7).abs() < 1e-9);
1442        assert_eq!(config.max_conversation_length, 100);
1443        assert!((config.analysis_sampling_rate - 1.0).abs() < 1e-9);
1444    }
1445
1446    #[test]
1447    fn test_llm_performance_profiler_new() {
1448        let profiler = LLMPerformanceProfiler::new();
1449        assert!(profiler.generation_metrics.tokens_per_second > 0.0);
1450        assert!(profiler.efficiency_metrics.memory_efficiency > 0.0);
1451        assert!(profiler.quality_metrics.coherence_score > 0.0);
1452        assert!(profiler.scalability_metrics.concurrent_user_capacity > 0);
1453    }
1454
1455    #[test]
1456    fn test_llm_performance_profiler_default() {
1457        let profiler = LLMPerformanceProfiler::default();
1458        assert!((profiler.generation_metrics.tokens_per_second - 100.0).abs() < 1e-9);
1459    }
1460
1461    #[test]
1462    fn test_llm_performance_profiler_health_summary() {
1463        let profiler = LLMPerformanceProfiler::new();
1464        let summary = profiler.get_health_summary();
1465        assert!(summary.score > 0.0 && summary.score <= 1.0);
1466        assert!(matches!(summary.status, HealthStatus::Good));
1467    }
1468
1469    #[test]
1470    fn test_generation_metrics_values() {
1471        let profiler = LLMPerformanceProfiler::new();
1472        let gm = &profiler.generation_metrics;
1473        assert!(gm.average_response_length > 0.0);
1474        assert!(gm.generation_latency_p50 < gm.generation_latency_p95);
1475        assert!(gm.generation_latency_p95 < gm.generation_latency_p99);
1476        assert!(gm.completion_rate > 0.0 && gm.completion_rate <= 1.0);
1477        assert!(gm.timeout_rate >= 0.0 && gm.timeout_rate < 1.0);
1478    }
1479
1480    #[test]
1481    fn test_efficiency_metrics_values() {
1482        let profiler = LLMPerformanceProfiler::new();
1483        let em = &profiler.efficiency_metrics;
1484        assert!(em.memory_efficiency > 0.0 && em.memory_efficiency <= 1.0);
1485        assert!(em.compute_utilization > 0.0 && em.compute_utilization <= 1.0);
1486        assert!(em.cache_hit_rate > 0.0 && em.cache_hit_rate <= 1.0);
1487        assert!(em.cost_per_token > 0.0);
1488    }
1489
1490    #[test]
1491    fn test_quality_metrics_values() {
1492        let profiler = LLMPerformanceProfiler::new();
1493        let qm = &profiler.quality_metrics;
1494        assert!(qm.coherence_score > 0.0 && qm.coherence_score <= 1.0);
1495        assert!(qm.relevance_score > 0.0 && qm.relevance_score <= 1.0);
1496        assert!(qm.fluency_score > 0.0 && qm.fluency_score <= 1.0);
1497        assert!(qm.factual_accuracy > 0.0 && qm.factual_accuracy <= 1.0);
1498    }
1499
1500    #[test]
1501    fn test_conversation_analyzer_new() {
1502        let config = LLMDebugConfig::default();
1503        let analyzer = ConversationAnalyzer::new(&config);
1504        assert!(analyzer.conversation_history.is_empty());
1505        assert!(analyzer.dialog_metrics.conversation_coherence > 0.0);
1506    }
1507
1508    #[test]
1509    fn test_conversation_analyzer_health_summary() {
1510        let config = LLMDebugConfig::default();
1511        let analyzer = ConversationAnalyzer::new(&config);
1512        let summary = analyzer.get_health_summary();
1513        assert!(summary.score > 0.0);
1514    }
1515
1516    #[test]
1517    fn test_context_tracker_update() {
1518        let mut tracker = ContextTracker {
1519            active_topics: HashSet::new(),
1520            entity_mentions: HashMap::new(),
1521            context_window: Vec::new(),
1522            attention_weights: Vec::new(),
1523        };
1524        let turn = ConversationTurn {
1525            user_input: "Hello".to_string(),
1526            model_response: "Hi there!".to_string(),
1527            timestamp: chrono::Utc::now(),
1528            turn_id: 0,
1529            context_length: 10,
1530            response_time: Duration::from_millis(100),
1531        };
1532        tracker.update_from_turn(&turn);
1533        assert_eq!(tracker.context_window.len(), 1);
1534        assert_eq!(tracker.context_window[0], "Hi there!");
1535    }
1536
1537    #[test]
1538    fn test_context_tracker_window_limit() {
1539        let mut tracker = ContextTracker {
1540            active_topics: HashSet::new(),
1541            entity_mentions: HashMap::new(),
1542            context_window: Vec::new(),
1543            attention_weights: Vec::new(),
1544        };
1545        for i in 0..15 {
1546            let turn = ConversationTurn {
1547                user_input: format!("q{}", i),
1548                model_response: format!("a{}", i),
1549                timestamp: chrono::Utc::now(),
1550                turn_id: 0,
1551                context_length: 10,
1552                response_time: Duration::from_millis(100),
1553            };
1554            tracker.update_from_turn(&turn);
1555        }
1556        assert_eq!(tracker.context_window.len(), 10);
1557    }
1558
1559    #[test]
1560    fn test_llm_debugger_factory_fn() {
1561        let debugger = llm_debugger();
1562        assert!(debugger.config.enable_safety_analysis);
1563    }
1564
1565    #[test]
1566    fn test_llm_debugger_with_config_factory() {
1567        let config = LLMDebugConfig {
1568            enable_safety_analysis: false,
1569            ..LLMDebugConfig::default()
1570        };
1571        let debugger = llm_debugger_with_config(config);
1572        assert!(!debugger.config.enable_safety_analysis);
1573    }
1574
1575    #[test]
1576    fn test_safety_focused_config_values() {
1577        let config = safety_focused_config();
1578        assert!(config.enable_hallucination_detection);
1579        assert!(!config.enable_conversation_analysis);
1580        assert_eq!(config.max_conversation_length, 50);
1581    }
1582
1583    #[test]
1584    fn test_performance_focused_config_values() {
1585        let config = performance_focused_config();
1586        assert!(!config.enable_hallucination_detection);
1587        assert!(!config.enable_bias_detection);
1588        assert_eq!(config.max_conversation_length, 200);
1589    }
1590
1591    #[test]
1592    fn test_scalability_metrics() {
1593        let profiler = LLMPerformanceProfiler::new();
1594        let sm = &profiler.scalability_metrics;
1595        assert!(sm.concurrent_user_capacity > 0);
1596        assert!(sm.throughput_scaling > 0.0 && sm.throughput_scaling <= 1.0);
1597        assert!(!sm.bottleneck_analysis.is_empty());
1598    }
1599}