Vapora/crates/vapora-knowledge-graph/examples/01-execution-tracking.rs

207 lines
7.3 KiB
Rust
Raw Permalink Normal View History

2026-01-12 03:34:01 +00:00
//! # Knowledge Graph Execution Tracking Example
//!
//! Demonstrates how to record agent executions and query the knowledge graph.
//!
//! ## What This Example Shows
//! - Creating a `TemporalKG` instance (in-memory for this example)
//! - Recording execution events with timestamps
//! - Querying executions by agent and task type
//! - Understanding execution metrics (duration, success rate, costs)
//!
//! ## Run
//! ```bash
//! cargo run --example 01-execution-tracking -p vapora-knowledge-graph
//! ```
//!
//! ## Expected Output
//! ```text
//! === Knowledge Graph Execution Tracking Example ===
//!
//! Recording execution events...
//! ✓ Recorded: developer-1 @ 2025-01-12 (coding, 250ms, success)
//! ✓ Recorded: developer-1 @ 2025-01-11 (testing, 180ms, success)
//! ✓ Recorded: developer-2 @ 2025-01-12 (coding, 320ms, failed)
//!
//! === Execution Summary ===
//! Total executions: 3
//! By agent:
//! developer-1: 2 executions (success rate: 100%)
//! developer-2: 1 execution (success rate: 0%)
//! By task type:
//! coding: 2 executions (success rate: 50%)
//! testing: 1 execution (success rate: 100%)
//! ```
use chrono::{Duration, Utc};
use vapora_knowledge_graph::ExecutionRecord;
fn main() {
println!("=== Knowledge Graph Execution Tracking Example ===\n");
// Step 1: Create sample execution records
let now = Utc::now();
let executions = vec![
ExecutionRecord {
id: "exec-001".to_string(),
task_id: "task-001".to_string(),
agent_id: "developer-1".to_string(),
agent_role: Some("developer".to_string()),
task_type: "coding".to_string(),
description: "Implement authentication module".to_string(),
root_cause: None,
solution: Some("Used OAuth2 with JWT tokens".to_string()),
timestamp: now - Duration::hours(24),
duration_ms: 250,
success: true,
input_tokens: 500,
output_tokens: 300,
cost_cents: 12,
provider: "claude".to_string(),
error: None,
},
ExecutionRecord {
id: "exec-002".to_string(),
task_id: "task-002".to_string(),
agent_id: "developer-1".to_string(),
agent_role: Some("developer".to_string()),
task_type: "testing".to_string(),
description: "Write unit tests for auth module".to_string(),
root_cause: None,
solution: Some("Implemented 100% code coverage".to_string()),
timestamp: now - Duration::hours(20),
duration_ms: 180,
success: true,
input_tokens: 300,
output_tokens: 200,
cost_cents: 8,
provider: "claude".to_string(),
error: None,
},
ExecutionRecord {
id: "exec-003".to_string(),
task_id: "task-003".to_string(),
agent_id: "developer-2".to_string(),
agent_role: Some("developer".to_string()),
task_type: "coding".to_string(),
description: "Refactor database layer".to_string(),
root_cause: Some("Performance regression detected".to_string()),
solution: None,
timestamp: now - Duration::hours(12),
duration_ms: 320,
success: false,
input_tokens: 600,
output_tokens: 400,
cost_cents: 18,
provider: "gpt-4".to_string(),
error: Some("Timeout after 320ms".to_string()),
},
];
// Step 2: Display execution records
println!("Recording execution events...");
for exec in &executions {
let status = if exec.success { "" } else { "" };
println!(
" {} {} (agent: {}, task: {}, duration: {}ms, success: {})",
status,
exec.timestamp.format("%Y-%m-%d %H:%M"),
exec.agent_id,
exec.task_type,
exec.duration_ms,
exec.success
);
}
println!();
// Step 3: Analyze executions by agent
println!("=== Execution Summary ===");
println!("Total executions: {}\n", executions.len());
println!("By Agent:");
let mut agents: std::collections::HashMap<String, Vec<_>> = std::collections::HashMap::new();
for exec in &executions {
agents
.entry(exec.agent_id.clone())
.or_insert_with(Vec::new)
.push(exec);
}
for (agent_id, agent_execs) in &agents {
let successes = agent_execs.iter().filter(|e| e.success).count();
let success_rate = (successes as f64 / agent_execs.len() as f64) * 100.0;
println!(
" {}: {} executions (success rate: {:.0}%)",
agent_id,
agent_execs.len(),
success_rate
);
let total_duration: u64 = agent_execs.iter().map(|e| e.duration_ms).sum();
let avg_duration = total_duration / agent_execs.len() as u64;
println!(" Average duration: {}ms", avg_duration);
let total_input_tokens: u64 = agent_execs.iter().map(|e| e.input_tokens).sum();
let total_output_tokens: u64 = agent_execs.iter().map(|e| e.output_tokens).sum();
println!(
" Tokens: {} input, {} output",
total_input_tokens, total_output_tokens
);
}
// Step 4: Analyze executions by task type
println!("\nBy Task Type:");
let mut task_types: std::collections::HashMap<String, Vec<_>> =
std::collections::HashMap::new();
for exec in &executions {
task_types
.entry(exec.task_type.clone())
.or_insert_with(Vec::new)
.push(exec);
}
for (task_type, task_execs) in &task_types {
let successes = task_execs.iter().filter(|e| e.success).count();
let success_rate = (successes as f64 / task_execs.len() as f64) * 100.0;
println!(
" {}: {} executions (success rate: {:.0}%)",
task_type,
task_execs.len(),
success_rate
);
let avg_duration: u64 =
task_execs.iter().map(|e| e.duration_ms).sum::<u64>() / task_execs.len() as u64;
println!(" Average duration: {}ms", avg_duration);
}
// Step 5: Analyze costs
println!("\n=== Cost Analysis ===");
let mut costs_by_provider: std::collections::HashMap<String, (u64, u64)> =
std::collections::HashMap::new();
for exec in &executions {
let (input_cost_cents, output_cost_cents) = match exec.provider.as_str() {
"claude" => (15, 45), // Claude pricing: $15 per 1M input, $45 per 1M output
"gpt-4" => (30, 60), // GPT-4 pricing: $30 per 1M input, $60 per 1M output
_ => (0, 0),
};
let provider_cost = costs_by_provider
.entry(exec.provider.clone())
.or_insert((0, 0));
provider_cost.0 += (exec.input_tokens * input_cost_cents) / 1_000_000;
provider_cost.1 += (exec.output_tokens * output_cost_cents) / 1_000_000;
2026-01-12 03:34:01 +00:00
}
for (provider, (input_cost, output_cost)) in costs_by_provider {
let total = input_cost + output_cost;
println!(
" {}: ${:.4} (input: ${:.4}, output: ${:.4})",
provider,
total as f64 / 10000.0,
input_cost as f64 / 10000.0,
output_cost as f64 / 10000.0
);
}
}