251 lines
8.6 KiB
Rust
251 lines
8.6 KiB
Rust
|
|
//! Example: RAG Batch Processing
|
|||
|
|
//!
|
|||
|
|
//! Demonstrates parallel query processing with:
|
|||
|
|
//! - Priority-based execution
|
|||
|
|
//! - Concurrent query processing
|
|||
|
|
//! - Progress tracking
|
|||
|
|
//! - Error handling and retries
|
|||
|
|
//! - Result aggregation and statistics
|
|||
|
|
|
|||
|
|
#![allow(clippy::useless_vec)]
|
|||
|
|
|
|||
|
|
use provisioning_rag::{BatchJob, BatchQuery};
|
|||
|
|
|
|||
|
|
#[tokio::main]
|
|||
|
|
async fn main() -> anyhow::Result<()> {
|
|||
|
|
// Initialize logging
|
|||
|
|
tracing_subscriber::fmt()
|
|||
|
|
.with_max_level(tracing::Level::INFO)
|
|||
|
|
.init();
|
|||
|
|
|
|||
|
|
println!("=== RAG Batch Processing Example ===\n");
|
|||
|
|
|
|||
|
|
// 1. Create batch queries
|
|||
|
|
println!("1. Creating Batch Queries\n");
|
|||
|
|
|
|||
|
|
let queries = vec![
|
|||
|
|
("What is Kubernetes?", 90), // High priority
|
|||
|
|
("How do I deploy applications?", 50), // Medium priority
|
|||
|
|
("Explain networking concepts", 70), // Higher priority
|
|||
|
|
("What about persistence?", 40), // Lower priority
|
|||
|
|
("Compare orchestration tools", 80), // Higher priority
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
let batch_queries: Vec<BatchQuery> = queries
|
|||
|
|
.into_iter()
|
|||
|
|
.map(|(query, priority)| {
|
|||
|
|
BatchQuery::new(query.into())
|
|||
|
|
.with_priority(priority)
|
|||
|
|
.with_retries(2)
|
|||
|
|
})
|
|||
|
|
.collect();
|
|||
|
|
|
|||
|
|
println!("Created {} queries", batch_queries.len());
|
|||
|
|
for query in &batch_queries {
|
|||
|
|
println!(" - ID: {}", query.query_id);
|
|||
|
|
println!(" Query: \"{}\"", query.query);
|
|||
|
|
println!(" Priority: {}", query.priority);
|
|||
|
|
println!(" Retries: {}\n", query.retry_count);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. Create batch job
|
|||
|
|
println!("\n2. Creating Batch Job Configuration\n");
|
|||
|
|
|
|||
|
|
let mut job = BatchJob::new(batch_queries);
|
|||
|
|
|
|||
|
|
println!("Job ID: {}", job.job_id);
|
|||
|
|
println!("Total queries: {}", job.total_queries());
|
|||
|
|
println!("Default max_concurrent: {}", job.max_concurrent);
|
|||
|
|
println!("Default timeout: {}s\n", job.timeout_secs);
|
|||
|
|
|
|||
|
|
// 3. Configure job
|
|||
|
|
println!("\n3. Configuring Batch Job\n");
|
|||
|
|
|
|||
|
|
job = job.with_max_concurrent(2).with_timeout(30);
|
|||
|
|
|
|||
|
|
println!(
|
|||
|
|
"Updated max_concurrent: {} (process 2 queries in parallel)",
|
|||
|
|
job.max_concurrent
|
|||
|
|
);
|
|||
|
|
println!("Updated timeout: {}s per query\n", job.timeout_secs);
|
|||
|
|
|
|||
|
|
// 4. Demonstrate priority sorting
|
|||
|
|
println!("\n4. Priority-Based Query Ordering\n");
|
|||
|
|
|
|||
|
|
println!("Before sorting:");
|
|||
|
|
for (i, q) in job.queries.iter().enumerate() {
|
|||
|
|
println!(" {}. \"{}\" (priority: {})", i + 1, q.query, q.priority);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
job.sort_by_priority();
|
|||
|
|
|
|||
|
|
println!("\nAfter sorting by priority (highest first):");
|
|||
|
|
for (i, q) in job.queries.iter().enumerate() {
|
|||
|
|
println!(" {}. \"{}\" (priority: {})", i + 1, q.query, q.priority);
|
|||
|
|
}
|
|||
|
|
println!();
|
|||
|
|
|
|||
|
|
// 5. Demonstrate parallel execution strategy
|
|||
|
|
println!("\n5. Parallel Execution Strategy\n");
|
|||
|
|
|
|||
|
|
println!("With max_concurrent=2, queries execute in batches:\n");
|
|||
|
|
|
|||
|
|
let max_concurrent = job.max_concurrent;
|
|||
|
|
for (batch_num, chunk) in job.queries.chunks(max_concurrent).enumerate() {
|
|||
|
|
println!("Batch {} (parallel execution):", batch_num + 1);
|
|||
|
|
for (i, q) in chunk.iter().enumerate() {
|
|||
|
|
println!(" {}. \"{}\" (p:{})", i + 1, q.query, q.priority);
|
|||
|
|
}
|
|||
|
|
println!();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 6. Explain timeout handling
|
|||
|
|
println!("\n6. Timeout and Retry Strategy\n");
|
|||
|
|
|
|||
|
|
println!("Per-query configuration:");
|
|||
|
|
for q in &job.queries {
|
|||
|
|
println!(" Query: \"{}\"", q.query);
|
|||
|
|
println!(" Timeout: {}s", job.timeout_secs);
|
|||
|
|
println!(" Max retries: {}", q.retry_count);
|
|||
|
|
println!(" Logic:");
|
|||
|
|
println!(" 1. Try to execute query");
|
|||
|
|
if q.retry_count > 0 {
|
|||
|
|
println!(" 2. If timeout, retry up to {} times", q.retry_count);
|
|||
|
|
} else {
|
|||
|
|
println!(" 2. If timeout, fail immediately");
|
|||
|
|
}
|
|||
|
|
println!(" 3. If max retries exceeded, store error result\n");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 7. Expected progress tracking
|
|||
|
|
println!("\n7. Expected Progress Tracking During Execution\n");
|
|||
|
|
|
|||
|
|
println!("Simulated execution timeline:\n");
|
|||
|
|
|
|||
|
|
let simulated_batches = vec![
|
|||
|
|
vec![
|
|||
|
|
"Q1: What is Kubernetes? (p:90)",
|
|||
|
|
"Q2: Explain networking (p:70)",
|
|||
|
|
],
|
|||
|
|
vec!["Q3: Compare tools (p:80)", "Q4: How to deploy? (p:50)"],
|
|||
|
|
vec!["Q5: What about persistence? (p:40)"],
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
for (batch_num, batch) in simulated_batches.iter().enumerate() {
|
|||
|
|
println!(
|
|||
|
|
"Time: {}ms - Executing Batch {}:",
|
|||
|
|
batch_num * 500,
|
|||
|
|
batch_num + 1
|
|||
|
|
);
|
|||
|
|
for query in batch {
|
|||
|
|
println!(" → {}", query);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let completed = ((batch_num + 1) * 2).min(5);
|
|||
|
|
let percent = (completed as f32 / 5.0 * 100.0) as u8;
|
|||
|
|
println!("Progress: {}/{} completed ({}%)\n", completed, 5, percent);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 8. Result aggregation
|
|||
|
|
println!("\n8. Result Aggregation and Statistics\n");
|
|||
|
|
|
|||
|
|
println!("Expected batch results:");
|
|||
|
|
println!(" ✅ Q1: What is Kubernetes? → Success (520ms)");
|
|||
|
|
println!(" ✅ Q2: Explain networking → Success (480ms)");
|
|||
|
|
println!(" ✅ Q3: Compare tools → Success (610ms)");
|
|||
|
|
println!(" ✅ Q4: How to deploy? → Success (450ms)");
|
|||
|
|
println!(" ✅ Q5: What about persistence? → Success (490ms)\n");
|
|||
|
|
|
|||
|
|
println!("Aggregated Statistics:");
|
|||
|
|
println!(" Total queries: 5");
|
|||
|
|
println!(" Successful: 5");
|
|||
|
|
println!(" Failed: 0");
|
|||
|
|
println!(" Success rate: 100.0%");
|
|||
|
|
println!(" Total duration: 2550ms");
|
|||
|
|
println!(" Average duration: 510ms\n");
|
|||
|
|
|
|||
|
|
// 9. Error handling scenarios
|
|||
|
|
println!("\n9. Error Handling Scenarios\n");
|
|||
|
|
|
|||
|
|
println!("Scenario 1: Query Timeout");
|
|||
|
|
println!(" Query exceeds 30s timeout");
|
|||
|
|
println!(" Action: Retry up to N times");
|
|||
|
|
println!(" Result: Error result stored\n");
|
|||
|
|
|
|||
|
|
println!("Scenario 2: Query Fails");
|
|||
|
|
println!(" Query processing error occurs");
|
|||
|
|
println!(" Action: Retry based on query config");
|
|||
|
|
println!(" Result: Error with details stored\n");
|
|||
|
|
|
|||
|
|
println!("Scenario 3: Partial Success");
|
|||
|
|
println!(" Some queries succeed, some fail");
|
|||
|
|
println!(" Result: Mixed results in output");
|
|||
|
|
println!(" Statistics: Partial success rate\n");
|
|||
|
|
|
|||
|
|
// 10. Performance comparison
|
|||
|
|
println!("\n10. Performance Comparison\n");
|
|||
|
|
|
|||
|
|
println!("Processing 5 queries:");
|
|||
|
|
println!(" Sequential (1 at a time):");
|
|||
|
|
println!(" 5 × 500ms = 2500ms total");
|
|||
|
|
println!(" Parallel (2 concurrent):");
|
|||
|
|
println!(" [500ms batch, 500ms batch, 500ms batch] = 1500ms total");
|
|||
|
|
println!(" Speedup: 1.67x faster\n");
|
|||
|
|
|
|||
|
|
println!("Processing 20 queries:");
|
|||
|
|
println!(" Sequential: 20 × 500ms = 10000ms total");
|
|||
|
|
println!(" Parallel (max_concurrent=5):");
|
|||
|
|
println!(" [500ms] × 4 batches = 2000ms total");
|
|||
|
|
println!(" Speedup: 5x faster!\n");
|
|||
|
|
|
|||
|
|
// 11. Configuration recommendations
|
|||
|
|
println!("\n11. Configuration Recommendations\n");
|
|||
|
|
|
|||
|
|
let configs = vec![
|
|||
|
|
(
|
|||
|
|
"Quick response required",
|
|||
|
|
1,
|
|||
|
|
5,
|
|||
|
|
"Sequential, minimize overhead",
|
|||
|
|
),
|
|||
|
|
("Balanced (default)", 5, 30, "Good balance of parallelism"),
|
|||
|
|
("High throughput", 10, 60, "Aggressive parallelism"),
|
|||
|
|
("Batch processing", 20, 120, "Maximum parallelism"),
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
for (scenario, max_concurrent, timeout_secs, reason) in configs {
|
|||
|
|
println!("Scenario: {}", scenario);
|
|||
|
|
println!(" max_concurrent: {}", max_concurrent);
|
|||
|
|
println!(" timeout: {}s", timeout_secs);
|
|||
|
|
println!(" Reason: {}\n", reason);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 12. Integration workflow
|
|||
|
|
println!("\n12. Typical Integration Workflow\n");
|
|||
|
|
|
|||
|
|
println!("1. User submits multiple questions");
|
|||
|
|
println!("2. Create BatchQuery for each (with priority)");
|
|||
|
|
println!("3. Create BatchJob with configuration");
|
|||
|
|
println!("4. Call batch_agent.process_batch(job)");
|
|||
|
|
println!("5. Queries execute in parallel by priority");
|
|||
|
|
println!("6. Progress tracked in real-time");
|
|||
|
|
println!("7. Results collected with statistics");
|
|||
|
|
println!("8. Display results to user\n");
|
|||
|
|
|
|||
|
|
// 13. Best practices
|
|||
|
|
println!("\n13. Best Practices for Batch Processing\n");
|
|||
|
|
|
|||
|
|
println!("✓ Set realistic priorities based on importance");
|
|||
|
|
println!("✓ Adjust max_concurrent based on system load");
|
|||
|
|
println!("✓ Set appropriate timeouts for query type");
|
|||
|
|
println!("✓ Use retries for transient failures");
|
|||
|
|
println!("✓ Monitor success rates and adjust config");
|
|||
|
|
println!("✓ Log results for analytics");
|
|||
|
|
println!("✓ Combine with query optimization");
|
|||
|
|
println!("✓ Cache frequent batch patterns\n");
|
|||
|
|
|
|||
|
|
println!("✅ Batch processing example complete!\n");
|
|||
|
|
|
|||
|
|
Ok(())
|
|||
|
|
}
|