diff --git a/crates/ruvector-tiny-dancer-core/examples/admin-server.rs b/crates/ruvector-tiny-dancer-core/examples/admin-server.rs index 0bc09510..2f53d1a8 100644 --- a/crates/ruvector-tiny-dancer-core/examples/admin-server.rs +++ b/crates/ruvector-tiny-dancer-core/examples/admin-server.rs @@ -1,79 +1,28 @@ -//! Admin server example for Tiny Dancer +//! Admin and health check example for Tiny Dancer //! -//! This example demonstrates how to run the admin API server for monitoring, -//! health checks, and administration of the Tiny Dancer routing system. +//! This example demonstrates how to implement health checks and +//! administrative functionality for the Tiny Dancer routing system. //! //! ## Usage //! //! ```bash -//! cargo run --example admin-server --features admin-api +//! cargo run --example admin-server //! ``` //! -//! ## Endpoints +//! This example shows: +//! - Health check implementations +//! - Configuration inspection +//! - Circuit breaker status monitoring +//! - Hot model reloading //! -//! ### Health Checks -//! - `GET /health` - Basic liveness probe -//! - `GET /health/ready` - Readiness check (K8s compatible) -//! -//! ### Metrics -//! - `GET /metrics` - Prometheus format metrics -//! -//! ### Admin -//! - `POST /admin/reload` - Hot reload model -//! - `GET /admin/config` - Get current configuration -//! - `PUT /admin/config` - Update configuration -//! - `GET /admin/circuit-breaker` - Get circuit breaker status -//! - `POST /admin/circuit-breaker/reset` - Reset circuit breaker -//! -//! ### Info -//! - `GET /info` - System information -//! -//! ## Testing Endpoints -//! -//! ```bash -//! # Health check -//! curl http://localhost:8080/health -//! -//! # Readiness check -//! curl http://localhost:8080/health/ready -//! -//! # Metrics (Prometheus format) -//! curl http://localhost:8080/metrics -//! -//! # System info -//! curl http://localhost:8080/info -//! -//! # Reload model (requires auth if token is set) -//! curl -X POST http://localhost:8080/admin/reload \ -//! -H "Authorization: Bearer your-token-here" -//! -//! # Get configuration -//! curl http://localhost:8080/admin/config \ -//! -H "Authorization: Bearer your-token-here" -//! -//! # Circuit breaker status -//! curl http://localhost:8080/admin/circuit-breaker \ -//! -H "Authorization: Bearer your-token-here" -//! ``` +//! For a full HTTP admin server implementation, see the `api` module +//! documentation which requires additional dependencies (axum, tokio). -use ruvector_tiny_dancer_core::api::{AdminServer, AdminServerConfig}; -use ruvector_tiny_dancer_core::router::Router; -use ruvector_tiny_dancer_core::types::RouterConfig; -use std::sync::Arc; -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; +use ruvector_tiny_dancer_core::{Candidate, Router, RouterConfig, RoutingRequest}; +use std::collections::HashMap; -#[tokio::main] -async fn main() -> Result<(), Box> { - // Initialize tracing - tracing_subscriber::registry() - .with( - tracing_subscriber::EnvFilter::try_from_default_env() - .unwrap_or_else(|_| "info,ruvector_tiny_dancer_core=debug".into()), - ) - .with(tracing_subscriber::fmt::layer()) - .init(); - - tracing::info!("Starting Tiny Dancer Admin Server Example"); +fn main() -> Result<(), Box> { + println!("=== Tiny Dancer Admin Example ===\n"); // Create router with default configuration let router_config = RouterConfig { @@ -86,55 +35,97 @@ async fn main() -> Result<(), Box> { database_path: None, }; - tracing::info!("Creating router with config: {:?}", router_config); - let router = Router::new(router_config)?; - let router = Arc::new(router); + println!("Creating router with config:"); + println!(" Model path: {}", router_config.model_path); + println!(" Confidence threshold: {}", router_config.confidence_threshold); + println!(" Max uncertainty: {}", router_config.max_uncertainty); + println!(" Circuit breaker: {}", router_config.enable_circuit_breaker); - // Configure admin server - let admin_config = AdminServerConfig { - bind_address: "127.0.0.1".to_string(), - port: 8080, - // Uncomment to enable authentication: - // auth_token: Some("your-secret-token-here".to_string()), - auth_token: None, - enable_cors: true, + let router = Router::new(router_config.clone())?; + + // Health check implementation + println!("\n--- Health Check ---"); + let health = check_health(&router); + println!("Status: {}", if health { "healthy" } else { "unhealthy" }); + + // Readiness check + println!("\n--- Readiness Check ---"); + let ready = check_readiness(&router); + println!("Ready: {}", ready); + + // Configuration info + println!("\n--- Configuration ---"); + let config = router.config(); + println!("Current configuration: {:?}", config); + + // Circuit breaker status + println!("\n--- Circuit Breaker Status ---"); + match router.circuit_breaker_status() { + Some(true) => println!("State: Closed (accepting requests)"), + Some(false) => println!("State: Open (rejecting requests)"), + None => println!("State: Disabled"), + } + + // Test routing to verify system works + println!("\n--- Test Routing ---"); + let candidates = vec![ + Candidate { + id: "test-1".to_string(), + embedding: vec![0.5; 384], + metadata: HashMap::new(), + created_at: chrono::Utc::now().timestamp(), + access_count: 10, + success_rate: 0.95, + }, + ]; + + let request = RoutingRequest { + query_embedding: vec![0.5; 384], + candidates, + metadata: None, }; - tracing::info!( - "Starting admin server on {}:{}", - admin_config.bind_address, - admin_config.port - ); - tracing::info!( - "Authentication: {}", - if admin_config.auth_token.is_some() { - "enabled" - } else { - "disabled" + match router.route(request) { + Ok(response) => { + println!( + "Test routing successful: {} candidates in {}μs", + response.candidates_processed, response.inference_time_us + ); } - ); + Err(e) => { + println!("Test routing failed: {}", e); + } + } - // Create and start admin server - let server = AdminServer::new(router, admin_config); + // Model reload demonstration + println!("\n--- Model Reload ---"); + println!("Attempting model reload..."); + match router.reload_model() { + Ok(_) => println!("Model reload: Success"), + Err(e) => println!("Model reload: {} (expected if model file doesn't exist)", e), + } - println!("\n╔════════════════════════════════════════════════════════════════╗"); - println!("║ Tiny Dancer Admin Server Running ║"); - println!("╠════════════════════════════════════════════════════════════════╣"); - println!("║ Health Check: http://localhost:8080/health ║"); - println!("║ Readiness: http://localhost:8080/health/ready ║"); - println!("║ Metrics: http://localhost:8080/metrics ║"); - println!("║ System Info: http://localhost:8080/info ║"); - println!("║ ║"); - println!("║ Admin API: http://localhost:8080/admin/* ║"); - println!("║ - POST /admin/reload ║"); - println!("║ - GET /admin/config ║"); - println!("║ - PUT /admin/config ║"); - println!("║ - GET /admin/circuit-breaker ║"); - println!("║ - POST /admin/circuit-breaker/reset ║"); - println!("╚════════════════════════════════════════════════════════════════╝\n"); - - // Start server (blocking) - server.serve().await?; + println!("\n=== Admin Example Complete ==="); + println!("\nFor a full HTTP admin server, you would need:"); + println!("1. Add axum and tokio dependencies"); + println!("2. Enable the admin-api feature"); + println!("3. Use the AdminServer from the api module"); Ok(()) } + +/// Basic health check - returns true if the router is operational +fn check_health(router: &Router) -> bool { + // A simple health check just verifies the router exists + // In production, you might also check model availability + router.config().model_path.len() > 0 +} + +/// Readiness check - returns true if ready to accept traffic +fn check_readiness(router: &Router) -> bool { + // Check circuit breaker status + match router.circuit_breaker_status() { + Some(is_closed) => is_closed, // Ready only if circuit breaker is closed + None => true, // Ready if circuit breaker is disabled + } +} diff --git a/crates/ruvector-tiny-dancer-core/examples/full_observability.rs b/crates/ruvector-tiny-dancer-core/examples/full_observability.rs index 8452f245..a56cfe79 100644 --- a/crates/ruvector-tiny-dancer-core/examples/full_observability.rs +++ b/crates/ruvector-tiny-dancer-core/examples/full_observability.rs @@ -1,40 +1,20 @@ -//! Comprehensive observability example combining metrics and tracing +//! Comprehensive observability example demonstrating routing performance //! //! This example demonstrates: -//! - Prometheus metrics collection -//! - OpenTelemetry distributed tracing -//! - Structured logging //! - Circuit breaker monitoring //! - Performance tracking -//! -//! Prerequisites: -//! - Jaeger (optional): docker run -d -p6831:6831/udp -p16686:16686 jaegertracing/all-in-one:latest -//! - Prometheus (optional): Configure to scrape your metrics endpoint +//! - Response statistics +//! - Different load scenarios //! //! Run with: cargo run --example full_observability -use ruvector_tiny_dancer_core::{ - Candidate, Router, RouterConfig, RoutingRequest, TracingConfig, TracingSystem, -}; +use ruvector_tiny_dancer_core::{Candidate, Router, RouterConfig, RoutingRequest, RoutingResponse}; use std::collections::HashMap; use std::time::Duration; fn main() -> Result<(), Box> { println!("=== Tiny Dancer Full Observability Example ===\n"); - // Initialize tracing (optional, for demonstration) - let tracing_config = TracingConfig { - service_name: "tiny-dancer-full-observability".to_string(), - service_version: "1.0.0".to_string(), - jaeger_agent_endpoint: None, // Set to Some("localhost:6831") for Jaeger - sampling_ratio: 1.0, - enable_stdout: false, - }; - - let tracing_system = TracingSystem::new(tracing_config); - // Ignore error if Jaeger is not available - let _ = tracing_system.init(); - // Create router with full configuration let config = RouterConfig { model_path: "./models/fastgrnn.safetensors".to_string(), @@ -48,6 +28,13 @@ fn main() -> Result<(), Box> { let router = Router::new(config)?; + // Track metrics manually + let mut total_requests = 0u64; + let mut successful_requests = 0u64; + let mut total_latency_us = 0u64; + let mut lightweight_routes = 0usize; + let mut powerful_routes = 0usize; + println!("\n=== Scenario 1: Normal Operations ===\n"); // Process normal requests @@ -62,8 +49,14 @@ fn main() -> Result<(), Box> { )])), }; + total_requests += 1; match router.route(request) { Ok(response) => { + successful_requests += 1; + total_latency_us += response.inference_time_us; + let (lw, pw) = count_routes(&response); + lightweight_routes += lw; + powerful_routes += pw; print_response_summary(i + 1, &response); } Err(e) => { @@ -88,8 +81,14 @@ fn main() -> Result<(), Box> { )])), }; + total_requests += 1; match router.route(request) { Ok(response) => { + successful_requests += 1; + total_latency_us += response.inference_time_us; + let (lw, pw) = count_routes(&response); + lightweight_routes += lw; + powerful_routes += pw; print_response_summary(i + 1, &response); } Err(e) => { @@ -98,41 +97,24 @@ fn main() -> Result<(), Box> { } } - println!("\n=== Metrics Export ===\n"); - - // Export Prometheus metrics - let metrics = router.export_metrics()?; - - println!("Sample metrics (showing key metrics only):\n"); - for line in metrics.lines() { - if line.starts_with("tiny_dancer_routing_requests_total") - || line.starts_with("tiny_dancer_routing_decisions_total") - || line.starts_with("tiny_dancer_circuit_breaker_state") - || line.starts_with("# HELP") - || line.starts_with("# TYPE") - { - println!("{}", line); - } - } - // Display statistics println!("\n=== Performance Statistics ===\n"); - display_statistics(); - - // Shutdown tracing - tracing_system.shutdown(); + display_statistics( + total_requests, + successful_requests, + total_latency_us, + lightweight_routes, + powerful_routes, + &router, + ); println!("\n=== Full Observability Example Complete ==="); - println!("\nObservability Stack:"); - println!("✓ Prometheus metrics collected"); - println!("✓ Distributed traces created"); - println!("✓ Structured logging enabled"); - println!("✓ Circuit breaker monitored"); - println!("\nNext steps:"); - println!("1. Deploy Prometheus to scrape metrics"); - println!("2. Connect Jaeger for trace visualization"); - println!("3. Set up Grafana dashboards"); - println!("4. Configure alerting rules"); + println!("\nMetrics Summary:"); + println!("- Total requests processed"); + println!("- Success/failure rates tracked"); + println!("- Latency statistics computed"); + println!("- Routing decisions categorized"); + println!("- Circuit breaker state monitored"); Ok(()) } @@ -153,13 +135,14 @@ fn create_candidates(offset: i32, count: usize) -> Vec { .collect() } -fn print_response_summary(request_num: i32, response: &ruvector_tiny_dancer_core::RoutingResponse) { - let lightweight_count = response - .decisions - .iter() - .filter(|d| d.use_lightweight) - .count(); - let powerful_count = response.decisions.len() - lightweight_count; +fn count_routes(response: &RoutingResponse) -> (usize, usize) { + let lightweight = response.decisions.iter().filter(|d| d.use_lightweight).count(); + let powerful = response.decisions.len() - lightweight; + (lightweight, powerful) +} + +fn print_response_summary(request_num: i32, response: &RoutingResponse) { + let (lightweight_count, powerful_count) = count_routes(response); println!( "Request {}: {}μs total, {}μs features, {} candidates", @@ -181,16 +164,37 @@ fn print_response_summary(request_num: i32, response: &ruvector_tiny_dancer_core } } -fn display_statistics() { - println!("Circuit Breaker: Closed"); - println!("Total Requests: 8"); - println!("Success Rate: 100%"); - println!("Avg Latency: <1ms"); - println!("\nMetric Types Collected:"); - println!("- tiny_dancer_routing_requests_total (counter)"); - println!("- tiny_dancer_routing_latency_seconds (histogram)"); - println!("- tiny_dancer_circuit_breaker_state (gauge)"); - println!("- tiny_dancer_routing_decisions_total (counter)"); - println!("- tiny_dancer_confidence_scores (histogram)"); - println!("- tiny_dancer_uncertainty_estimates (histogram)"); +fn display_statistics( + total_requests: u64, + successful_requests: u64, + total_latency_us: u64, + lightweight_routes: usize, + powerful_routes: usize, + router: &Router, +) { + let cb_state = match router.circuit_breaker_status() { + Some(true) => "Closed", + Some(false) => "Open", + None => "Disabled", + }; + + let success_rate = if total_requests > 0 { + (successful_requests as f64 / total_requests as f64) * 100.0 + } else { + 0.0 + }; + + let avg_latency = if successful_requests > 0 { + total_latency_us / successful_requests + } else { + 0 + }; + + println!("Circuit Breaker: {}", cb_state); + println!("Total Requests: {}", total_requests); + println!("Successful Requests: {}", successful_requests); + println!("Success Rate: {:.1}%", success_rate); + println!("Avg Latency: {}μs", avg_latency); + println!("Lightweight Routes: {}", lightweight_routes); + println!("Powerful Routes: {}", powerful_routes); } diff --git a/crates/ruvector-tiny-dancer-core/examples/metrics_example.rs b/crates/ruvector-tiny-dancer-core/examples/metrics_example.rs index 188cbe0a..4bc6fe2b 100644 --- a/crates/ruvector-tiny-dancer-core/examples/metrics_example.rs +++ b/crates/ruvector-tiny-dancer-core/examples/metrics_example.rs @@ -1,8 +1,7 @@ -//! Example demonstrating Prometheus metrics collection with Tiny Dancer +//! Example demonstrating metrics collection with Tiny Dancer //! //! This example shows how to: -//! - Collect routing metrics -//! - Export metrics in Prometheus format +//! - Collect routing metrics manually //! - Monitor circuit breaker state //! - Track routing decisions and latencies //! @@ -26,6 +25,13 @@ fn main() -> Result<(), Box> { let router = Router::new(config)?; + // Track metrics manually + let mut total_requests = 0u64; + let mut total_candidates = 0u64; + let mut total_latency_us = 0u64; + let mut lightweight_count = 0u64; + let mut powerful_count = 0u64; + // Process multiple routing requests println!("Processing routing requests...\n"); @@ -65,13 +71,31 @@ fn main() -> Result<(), Box> { match router.route(request) { Ok(response) => { + total_requests += 1; + total_candidates += response.candidates_processed as u64; + total_latency_us += response.inference_time_us; + + // Count routing decisions + for decision in &response.decisions { + if decision.use_lightweight { + lightweight_count += 1; + } else { + powerful_count += 1; + } + } + println!( "Request {}: Processed {} candidates in {}μs", i + 1, response.candidates_processed, response.inference_time_us ); - println!(" Top decision: {:?}", response.decisions.first()); + if let Some(top) = response.decisions.first() { + println!( + " Top decision: {} (confidence: {:.3}, lightweight: {})", + top.candidate_id, top.confidence, top.use_lightweight + ); + } } Err(e) => { eprintln!("Error processing request {}: {}", i + 1, e); @@ -79,36 +103,39 @@ fn main() -> Result<(), Box> { } } - // Export metrics - println!("\n=== Prometheus Metrics ===\n"); - let metrics = router.export_metrics()?; - println!("{}", metrics); + // Display collected metrics + println!("\n=== Collected Metrics ===\n"); - // Parse and display key metrics - println!("\n=== Key Metrics Summary ===\n"); + let cb_state = match router.circuit_breaker_status() { + Some(true) => "closed", + Some(false) => "open", + None => "disabled", + }; - for line in metrics.lines() { - if line.starts_with("tiny_dancer_routing_requests_total") { - println!("{}", line); - } else if line.starts_with("tiny_dancer_routing_decisions_total") { - println!("{}", line); - } else if line.starts_with("tiny_dancer_circuit_breaker_state") { - println!("{}", line); - } else if line.starts_with("tiny_dancer_candidates_processed_total") { - println!("{}", line); - } - } + let avg_latency = if total_requests > 0 { + total_latency_us / total_requests + } else { + 0 + }; + + println!("tiny_dancer_routing_requests_total {}", total_requests); + println!("tiny_dancer_candidates_processed_total {}", total_candidates); + println!( + "tiny_dancer_routing_decisions_total{{model_type=\"lightweight\"}} {}", + lightweight_count + ); + println!( + "tiny_dancer_routing_decisions_total{{model_type=\"powerful\"}} {}", + powerful_count + ); + println!("tiny_dancer_avg_latency_us {}", avg_latency); + println!("tiny_dancer_circuit_breaker_state {}", cb_state); println!("\n=== Metrics Collection Complete ==="); - println!("\nTo visualize these metrics:"); - println!("1. Set up a Prometheus server"); - println!("2. Configure scraping from your application"); - println!("3. Use Grafana to create dashboards"); - println!("\nExample Prometheus configuration:"); - println!(" scrape_configs:"); - println!(" - job_name: 'tiny-dancer'"); - println!(" static_configs:"); - println!(" - targets: ['localhost:9090']"); + println!("\nThese metrics can be exported to monitoring systems:"); + println!("- Prometheus for time-series collection"); + println!("- Grafana for visualization"); + println!("- Custom dashboards for real-time monitoring"); Ok(()) } diff --git a/crates/ruvector-tiny-dancer-core/examples/tracing_example.rs b/crates/ruvector-tiny-dancer-core/examples/tracing_example.rs index c22cd02a..c73f3287 100644 --- a/crates/ruvector-tiny-dancer-core/examples/tracing_example.rs +++ b/crates/ruvector-tiny-dancer-core/examples/tracing_example.rs @@ -1,45 +1,20 @@ -//! Example demonstrating distributed tracing with OpenTelemetry and Jaeger +//! Example demonstrating basic tracing with the Tiny Dancer routing system //! //! This example shows how to: -//! - Initialize OpenTelemetry tracing -//! - Create spans for routing operations -//! - Propagate trace context -//! - Export traces to Jaeger -//! -//! Prerequisites: -//! - Run Jaeger: docker run -d -p6831:6831/udp -p16686:16686 jaegertracing/all-in-one:latest +//! - Create and configure a router +//! - Process routing requests +//! - Monitor timing and performance //! //! Run with: cargo run --example tracing_example -use ruvector_tiny_dancer_core::{ - Candidate, Router, RouterConfig, RoutingRequest, TraceContext, TracingConfig, TracingSystem, -}; +use ruvector_tiny_dancer_core::{Candidate, Router, RouterConfig, RoutingRequest}; use std::collections::HashMap; +use std::time::Instant; fn main() -> Result<(), Box> { - println!("=== Tiny Dancer Distributed Tracing Example ===\n"); + println!("=== Tiny Dancer Routing Example with Timing ===\n"); - // Initialize tracing with stdout exporter (for demonstration) - // In production, use Jaeger endpoint - let tracing_config = TracingConfig { - service_name: "tiny-dancer-example".to_string(), - service_version: "1.0.0".to_string(), - jaeger_agent_endpoint: None, // Set to Some("localhost:6831") for Jaeger - sampling_ratio: 1.0, - enable_stdout: true, // Set to false when using Jaeger - }; - - let tracing_system = TracingSystem::new(tracing_config); - tracing_system.init()?; - - println!("Tracing initialized (stdout mode for demonstration)\n"); - println!("To use Jaeger:"); - println!("1. Start Jaeger: docker run -d -p6831:6831/udp -p16686:16686 jaegertracing/all-in-one:latest"); - println!("2. Set jaeger_agent_endpoint to Some(\"localhost:6831\")"); - println!("3. Set enable_stdout to false"); - println!("4. Visit http://localhost:16686 to view traces\n"); - - // Create router + // Create router with configuration let config = RouterConfig { model_path: "./models/fastgrnn.safetensors".to_string(), confidence_threshold: 0.85, @@ -51,19 +26,13 @@ fn main() -> Result<(), Box> { let router = Router::new(config)?; - // Process requests with tracing - println!("Processing requests with distributed tracing...\n"); + // Process requests with timing + println!("Processing requests with timing information...\n"); for i in 0..3 { + let request_start = Instant::now(); println!("Request {} - Processing", i + 1); - // Get trace context for propagation (requires OpenTelemetry to be initialized) - if let Some(trace_ctx) = TraceContext::from_current() { - println!(" Trace ID: {}", trace_ctx.trace_id); - println!(" Span ID: {}", trace_ctx.span_id); - println!(" W3C Traceparent: {}", trace_ctx.to_w3c_traceparent()); - } - // Create candidates let candidates = vec![ Candidate { @@ -90,14 +59,16 @@ fn main() -> Result<(), Box> { metadata: None, }; - // Route with automatic span creation + // Route request match router.route(request) { Ok(response) => { + let total_time = request_start.elapsed(); println!( - "\nRequest {}: Processed {} candidates in {}μs", + "\nRequest {}: Processed {} candidates in {}μs (total: {:?})", i + 1, response.candidates_processed, - response.inference_time_us + response.inference_time_us, + total_time ); for decision in response.decisions.iter().take(2) { @@ -115,17 +86,11 @@ fn main() -> Result<(), Box> { println!(); } - // Shutdown tracing to flush remaining spans - println!("\n=== Flushing traces ==="); - tracing_system.shutdown(); - - println!("\n=== Tracing Example Complete ==="); - println!("\nSpans created during execution:"); - println!("- routing_request (Router::route)"); - println!("- circuit_breaker_check"); - println!("- feature_engineering"); - println!("- model_inference (per candidate)"); - println!("- uncertainty_estimation (per candidate)"); + println!("\n=== Routing Example Complete ==="); + println!("\nTiming breakdown available in each response:"); + println!("- inference_time_us: Total inference time"); + println!("- feature_time_us: Feature engineering time"); + println!("- candidates_processed: Number of candidates evaluated"); Ok(()) } diff --git a/crates/ruvector-tiny-dancer-core/src/error.rs b/crates/ruvector-tiny-dancer-core/src/error.rs index 287835ea..bccef48d 100644 --- a/crates/ruvector-tiny-dancer-core/src/error.rs +++ b/crates/ruvector-tiny-dancer-core/src/error.rs @@ -54,3 +54,9 @@ impl From for TinyDancerError { TinyDancerError::SerializationError(err.to_string()) } } + +impl From for TinyDancerError { + fn from(err: std::io::Error) -> Self { + TinyDancerError::StorageError(err.to_string()) + } +} diff --git a/crates/ruvector-tiny-dancer-core/src/lib.rs b/crates/ruvector-tiny-dancer-core/src/lib.rs index 66838af0..74105445 100644 --- a/crates/ruvector-tiny-dancer-core/src/lib.rs +++ b/crates/ruvector-tiny-dancer-core/src/lib.rs @@ -9,6 +9,7 @@ //! - Uncertainty quantification with conformal prediction //! - Circuit breaker patterns for graceful degradation //! - SQLite/AgentDB integration +//! - Training infrastructure with knowledge distillation #![deny(unsafe_op_in_unsafe_fn)] #![warn(missing_docs, rustdoc::broken_intra_doc_links)] @@ -20,14 +21,16 @@ pub mod model; pub mod optimization; pub mod router; pub mod storage; +pub mod training; pub mod types; pub mod uncertainty; // Re-exports for convenience pub use error::{Result, TinyDancerError}; -pub use model::FastGRNN; +pub use model::{FastGRNN, FastGRNNConfig}; pub use router::Router; -pub use types::{Candidate, RoutingDecision, RoutingRequest, RoutingResponse}; +pub use training::{generate_teacher_predictions, Trainer, TrainingConfig, TrainingDataset, TrainingMetrics}; +pub use types::{Candidate, RouterConfig, RoutingDecision, RoutingRequest, RoutingResponse, RoutingMetrics}; /// Version of the Tiny Dancer library pub const VERSION: &str = env!("CARGO_PKG_VERSION");