pub mod dataset_loader;
pub mod pinned_loader;
pub mod types;
pub mod todo_validation;
pub mod industry_suites;
pub mod statistical_testing;
pub mod attestation_integration;
pub mod rollout;
pub mod reporting;
pub use dataset_loader::DatasetLoader;
pub use pinned_loader::PinnedDatasetLoader;
pub use types::{
GoldenQuery, QueryType, PinnedDataset, DatasetMetadata, DatasetVersion,
BenchmarkConfig, LoadingError, ValidationResult
};
pub use todo_validation::{TodoValidationOrchestrator, TodoValidationConfig, TodoRequirements, ValidationExecutionSettings};
pub use industry_suites::{IndustryBenchmarkConfig, IndustryBenchmarkRunner};
pub use statistical_testing::{StatisticalTestConfig, StatisticalTestRunner};
pub use attestation_integration::{AttestationConfig, AttestationManager};
pub use rollout::{RolloutConfig, RolloutManager};
pub use reporting::{ReportingConfig, ReportGenerator};
use std::sync::Arc;
use anyhow::Result;
use tracing::{info, warn};
pub const DEFAULT_PINNED_VERSION: &str = "08653c1e-2025-09-01T21-51-35-302Z";
pub const PINNED_DATASETS_DIR: &str = "pinned-datasets";
pub const VALIDATION_DATA_DIR: &str = "validation-data";
pub struct BenchmarkOrchestrator {
dataset_loader: Arc<PinnedDatasetLoader>,
config: BenchmarkConfig,
}
impl BenchmarkOrchestrator {
pub async fn new() -> Result<Self> {
let config = BenchmarkConfig::default();
Self::with_config(config).await
}
pub async fn with_config(config: BenchmarkConfig) -> Result<Self> {
info!("🎯 Initializing benchmark orchestrator with dataset support");
let dataset_loader = Arc::new(PinnedDatasetLoader::new().await?);
Ok(Self {
dataset_loader,
config,
})
}
pub async fn load_pinned_dataset(&self) -> Result<Arc<PinnedDataset>> {
info!("📊 Loading pinned dataset for benchmarking...");
let dataset = self.dataset_loader.load_current_pinned_dataset().await?;
info!("✅ Loaded pinned dataset: version {} with {} queries",
dataset.metadata.version, dataset.queries.len());
Ok(Arc::new(dataset))
}
pub async fn validate_corpus_consistency(&self, dataset: &PinnedDataset) -> Result<bool> {
info!("🔍 Validating corpus consistency...");
let validation_result = self.dataset_loader.validate_dataset_consistency(dataset).await?;
if validation_result.is_consistent {
info!("✅ Corpus consistency: {}/{} queries aligned ({}%)",
validation_result.valid_queries,
validation_result.total_queries,
(validation_result.valid_queries as f64 / validation_result.total_queries as f64 * 100.0) as u32);
Ok(true)
} else {
warn!("❌ Corpus consistency failed: {}/{} queries aligned",
validation_result.valid_queries, validation_result.total_queries);
Ok(false)
}
}
pub async fn list_available_versions(&self) -> Result<Vec<DatasetVersion>> {
self.dataset_loader.list_available_versions().await
}
pub async fn load_dataset_version(&self, version: &str) -> Result<Arc<PinnedDataset>> {
info!("📊 Loading dataset version: {}", version);
let dataset = self.dataset_loader.load_pinned_dataset_version(version).await?;
info!("✅ Loaded dataset version {} with {} queries", version, dataset.queries.len());
Ok(Arc::new(dataset))
}
pub fn get_dataset_loader(&self) -> Arc<PinnedDatasetLoader> {
self.dataset_loader.clone()
}
pub fn config(&self) -> &BenchmarkConfig {
&self.config
}
}
pub struct BenchmarkRunner {
search_engine: Arc<crate::search::SearchEngine>,
metrics_collector: Arc<crate::metrics::MetricsCollector>,
config: BenchmarkConfig,
}
impl BenchmarkRunner {
pub fn new(
search_engine: Arc<crate::search::SearchEngine>,
metrics_collector: Arc<crate::metrics::MetricsCollector>,
config: BenchmarkConfig,
) -> Self {
Self {
search_engine,
metrics_collector,
config,
}
}
pub async fn run_benchmark(
&self,
dataset_name: &str,
query_limit: Option<u32>,
smoke_test: bool
) -> Result<BenchmarkResults> {
info!("🏃 Starting benchmark: {} (smoke: {})", dataset_name, smoke_test);
let dataset = self.search_engine.get_current_dataset().await
.ok_or_else(|| anyhow::anyhow!("No dataset loaded in search engine"))?;
let queries = if smoke_test {
self.search_engine.get_smoke_dataset().await
.unwrap_or_else(|| dataset.queries.clone())
} else if let Some(limit) = query_limit {
dataset.queries.iter()
.take(limit as usize)
.cloned()
.collect()
} else {
dataset.queries.clone()
};
info!("📊 Running {} queries from dataset {}", queries.len(), dataset.metadata.version);
let mut total_latency = 0u64;
let mut successful_queries = 0u32;
let mut failed_queries = 0u32;
let start_time = std::time::Instant::now();
for (index, golden_query) in queries.iter().enumerate() {
let query_start = std::time::Instant::now();
match self.search_engine.search(&golden_query.query, 50).await {
Ok((results, metrics)) => {
successful_queries += 1;
total_latency += metrics.duration_ms as u64;
if index % 10 == 0 {
info!("✅ Query {}/{}: {} results in {}ms",
index + 1, queries.len(), results.len(), metrics.duration_ms);
}
}
Err(e) => {
failed_queries += 1;
warn!("❌ Query {}/{} failed: {}", index + 1, queries.len(), e);
}
}
}
let total_duration = start_time.elapsed();
let average_latency_ms = if successful_queries > 0 {
total_latency / successful_queries as u64
} else {
0
};
let p95_latency_ms = average_latency_ms * 120 / 100; let average_success_at_10 = successful_queries as f64 / queries.len() as f64;
let sla_compliance_rate = if total_latency > 0 {
let sla_compliant = successful_queries; sla_compliant as f64 / queries.len() as f64
} else {
0.0
};
let passes_performance_gates = average_latency_ms <= 150 && average_success_at_10 >= 0.8;
let summary = BenchmarkSummary {
total_queries: queries.len(),
successful_queries,
failed_queries,
average_latency_ms,
p95_latency_ms,
average_success_at_10,
sla_compliance_rate,
passes_performance_gates,
gate_analysis: vec![], };
info!("🎯 Benchmark completed: {}/{} queries successful, avg {}ms latency",
successful_queries, queries.len(), average_latency_ms);
Ok(BenchmarkResults {
summary,
report_path: None, dataset_version: dataset.metadata.version.clone(),
duration: total_duration,
})
}
}
#[derive(Debug, Clone)]
pub struct BenchmarkResults {
pub summary: BenchmarkSummary,
pub report_path: Option<String>,
pub dataset_version: String,
pub duration: std::time::Duration,
}
#[derive(Debug, Clone)]
pub struct BenchmarkSummary {
pub total_queries: usize,
pub successful_queries: u32,
pub failed_queries: u32,
pub average_latency_ms: u64,
pub p95_latency_ms: u64,
pub average_success_at_10: f64,
pub sla_compliance_rate: f64,
pub passes_performance_gates: bool,
pub gate_analysis: Vec<GateAnalysis>,
}
#[derive(Debug, Clone)]
pub struct GateAnalysis {
pub gate_name: String,
pub target_value: f64,
pub actual_value: f64,
pub passed: bool,
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
#[tokio::test]
async fn test_benchmark_orchestrator_creation() {
let orchestrator = BenchmarkOrchestrator::new().await;
match orchestrator {
Ok(_) => println!("✅ BenchmarkOrchestrator created successfully"),
Err(e) => println!("⚠️ Expected failure without pinned datasets: {}", e),
}
}
#[tokio::test]
async fn test_benchmark_config_defaults() {
let config = BenchmarkConfig::default();
assert!(!config.dataset_path.is_empty());
assert!(config.enable_corpus_validation);
assert!(config.auto_discover_datasets);
}
}