//! # Learning Curves Example //! //! Demonstrates how agent learning curves are computed and displayed. //! //! ## What This Example Shows //! - Recording execution data over time //! - Computing learning curves from historical data //! - Understanding performance trends //! - Visualizing improvement over time //! //! ## Run //! ```bash //! cargo run --example 02-learning-curves -p vapora-knowledge-graph //! ``` use chrono::{Duration, Utc}; fn main() { println!("=== Learning Curves Example ===\n"); // Step 1: Simulate 30 days of execution history let now = Utc::now(); #[derive(Clone)] struct DailyStats { date: String, executions: u32, successful: u32, avg_duration_ms: u32, } let mut daily_data = vec![]; for day in 0..30 { let date_obj = now - Duration::days(day); let date_str = date_obj.format("%Y-%m-%d").to_string(); // Simulate improvement: success rate increases over time let base_success_rate = 0.70 + (day as f64 / 30.0) * 0.22; // From 70% to 92% let executions = 10; let successful = (executions as f64 * base_success_rate) as u32; let avg_duration = 300 - (day as u32 * 3); // Tasks get faster daily_data.push(DailyStats { date: date_str, executions, successful, avg_duration_ms: avg_duration, }); } // Reverse to show chronologically daily_data.reverse(); // Step 2: Display learning curve data println!("=== Agent: developer-bob (30-day history) ===\n"); println!("Date | Success Rate | Duration | Trend"); println!("-----------|------|"); let mut prev_success = 0.0; for data in &daily_data { let success_rate = (data.successful as f64 / data.executions as f64) * 100.0; let trend = if success_rate > prev_success { "↑" } else if success_rate < prev_success { "↓" } else { "→" }; let bar_length = (success_rate / 5.0) as usize; let bar = "█".repeat(bar_length) + &"░".repeat(20 - bar_length); println!( "{} | {} | {:.0}% | {}ms | {}", data.date, bar, success_rate, data.avg_duration_ms, trend ); prev_success = success_rate; } // Step 3: Compute overall learning curve println!("\n=== Learning Curve Analysis ===\n"); let total_executions: u32 = daily_data.iter().map(|d| d.executions).sum(); let total_successful: u32 = daily_data.iter().map(|d| d.successful).sum(); let overall_success = (total_successful as f64 / total_executions as f64) * 100.0; println!("Total executions: {}", total_executions); println!("Total successful: {}", total_successful); println!("Overall success rate: {:.1}%\n", overall_success); // Compute 7-day and 14-day windows let recent_7 = &daily_data[daily_data.len() - 7..]; let recent_14 = &daily_data[daily_data.len() - 14..]; let recent_7_success: f64 = recent_7.iter().map(|d| d.successful as f64).sum::() / recent_7.iter().map(|d| d.executions as f64).sum::(); let recent_14_success: f64 = recent_14.iter().map(|d| d.successful as f64).sum::() / recent_14.iter().map(|d| d.executions as f64).sum::(); println!("Last 7 days success rate: {:.1}%", recent_7_success * 100.0); println!( "Last 14 days success rate: {:.1}%", recent_14_success * 100.0 ); // Step 4: Demonstrate recency bias println!("\n=== Recency Bias ==="); println!("Recent days weighted 3× higher than older days"); println!("Last 7 days: 3.0x weight"); println!("Days 8-30: 1.0x weight\n"); let weighted_recent = recent_7_success * 3.0; let weighted_older: f64 = daily_data[0..23] .iter() .map(|d| (d.successful as f64 / d.executions as f64)) .sum::() / 23.0; let weighted_older = weighted_older * 1.0; let final_score = (weighted_recent + weighted_older) / (3.0 + 1.0); println!("Weighted score: {:.1}%", final_score * 100.0); // Step 5: Recommendations println!("\n=== Agent Performance Trend ==="); let improvement = recent_7_success - (daily_data[0].successful as f64 / daily_data[0].executions as f64); if improvement > 0.0 { println!("✓ IMPROVING (+{:.1}%)", improvement * 100.0); println!(" → Agent is learning from experience"); println!(" → Ready for more complex tasks"); } else if improvement < 0.0 { println!("✗ DECLINING ({:.1}%)", improvement * 100.0); println!(" → Check for blocking issues"); println!(" → Consider additional training"); } else { println!("→ STABLE"); println!(" → Consistent performance"); } }