Files
rustytorch/crates/production/rtx-serving-api/src/advanced_server.rs
T
osobhandClaude Opus 4.6 02d382d5f6 style: apply rustfmt across all crates and demos
Consistent formatting pass: line wrapping, import sorting, trailing
whitespace removal, let-chain indentation, merged derive attributes,
and unsafe block reformatting.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
2026-04-12 07:01:58 -07:00

702 lines
22 KiB
Rust

//! Advanced LLM serving server with comprehensive features
//!
//! Integrates all advanced LLM capabilities into a unified server:
//! - Rate limiting and token management
//! - Structured generation and validation
//! - Grammar-constrained sampling
//! - Cost attribution and billing
//! - Request prioritization and queuing
//! - Advanced sampling strategies
//! - Streaming responses (SSE/WebSocket)
//! - Multi-model serving and routing
use axum::{
Router,
extract::{Path, State},
response::{Json, Sse},
routing::{get, post},
};
use serde::{Deserialize, Serialize};
use std::{sync::Arc, time::Duration};
use tokio::net::TcpListener;
use tower_http::{cors::CorsLayer, timeout::TimeoutLayer, trace::TraceLayer};
use crate::{
ApiError,
ApiResult,
// grammar_sampling::{ContextFreeGrammar, GrammarGuidedSampler}, // Temporarily disabled
billing::BillingManager,
multi_model::MultiModelManager,
queue_management::QueueManager,
rate_limiting::RateLimitManager,
streaming::StreamManager,
structured_generation::StructuredGenerationManager,
};
/// Advanced server configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdvancedServerConfig {
/// Basic server settings
pub host: String,
pub port: u16,
pub timeout_seconds: u64,
/// Rate limiting configuration
pub enable_rate_limiting: bool,
pub rate_limit_config: RateLimitConfig,
/// Structured generation settings
pub enable_structured_generation: bool,
pub max_schema_size: usize,
/// Grammar sampling settings
pub enable_grammar_sampling: bool,
pub max_grammar_complexity: usize,
/// Billing configuration
pub enable_billing: bool,
pub billing_currency: String,
/// Queue management settings
pub enable_queue_management: bool,
pub max_queue_size: usize,
pub max_concurrent_requests: usize,
/// Streaming configuration
pub enable_streaming: bool,
pub max_stream_connections: usize,
pub stream_buffer_size: usize,
/// Multi-model settings
pub enable_multi_model: bool,
pub max_loaded_models: usize,
pub model_cache_size_gb: f32,
/// Security settings
pub enable_auth: bool,
pub api_key_required: bool,
pub cors_origins: Vec<String>,
}
/// Rate limiting configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RateLimitConfig {
pub requests_per_minute: u64,
pub tokens_per_minute: u64,
pub burst_allowance: f64,
pub enable_user_tiers: bool,
}
impl Default for AdvancedServerConfig {
fn default() -> Self {
Self {
host: "127.0.0.1".to_string(),
port: 8080,
timeout_seconds: 300,
enable_rate_limiting: true,
rate_limit_config: RateLimitConfig {
requests_per_minute: 60,
tokens_per_minute: 10000,
burst_allowance: 2.0,
enable_user_tiers: true,
},
enable_structured_generation: true,
max_schema_size: 1024 * 1024, // 1MB
enable_grammar_sampling: true,
max_grammar_complexity: 1000,
enable_billing: true,
billing_currency: "USD".to_string(),
enable_queue_management: true,
max_queue_size: 1000,
max_concurrent_requests: 100,
enable_streaming: true,
max_stream_connections: 10000,
stream_buffer_size: 4096,
enable_multi_model: true,
max_loaded_models: 10,
model_cache_size_gb: 100.0,
enable_auth: false,
api_key_required: false,
cors_origins: vec!["*".to_string()],
}
}
}
/// Advanced serving server state
#[derive(Clone)]
pub struct AdvancedServerState {
pub config: AdvancedServerConfig,
pub rate_limiter: Option<Arc<RateLimitManager>>,
pub structured_gen: Option<Arc<StructuredGenerationManager>>,
pub billing_manager: Option<Arc<BillingManager>>,
pub queue_manager: Option<Arc<QueueManager>>,
pub stream_manager: Option<Arc<StreamManager>>,
pub model_manager: Option<Arc<MultiModelManager>>,
}
impl AdvancedServerState {
/// Create new advanced server state
#[must_use]
pub fn new(config: AdvancedServerConfig) -> Self {
let rate_limiter = if config.enable_rate_limiting {
Some(Arc::new(RateLimitManager::new()))
} else {
None
};
let structured_gen = if config.enable_structured_generation {
Some(Arc::new(StructuredGenerationManager::new()))
} else {
None
};
let billing_manager = if config.enable_billing {
Some(Arc::new(BillingManager::new()))
} else {
None
};
let queue_manager = if config.enable_queue_management {
Some(Arc::new(QueueManager::new(
config.max_concurrent_requests,
config.max_queue_size,
)))
} else {
None
};
let stream_manager = if config.enable_streaming {
let stream_config = crate::streaming::StreamConfig {
buffer_size: config.stream_buffer_size,
max_concurrent_streams: config.max_stream_connections,
..Default::default()
};
Some(Arc::new(StreamManager::new(stream_config)))
} else {
None
};
let model_manager = if config.enable_multi_model {
Some(Arc::new(MultiModelManager::new()))
} else {
None
};
Self {
config,
rate_limiter,
structured_gen,
billing_manager,
queue_manager,
stream_manager,
model_manager,
}
}
}
/// Advanced serving server
pub struct AdvancedServingServer {
state: AdvancedServerState,
}
impl AdvancedServingServer {
/// Create new advanced serving server
#[must_use]
pub fn new(config: AdvancedServerConfig) -> Self {
Self {
state: AdvancedServerState::new(config),
}
}
/// Build the complete router with all advanced features
pub fn app(&self) -> Router {
let mut router = Router::new()
// Basic health and model endpoints
.route("/health", get(health_check))
.route("/health/ready", get(health_check))
.route("/health/live", get(health_check))
.route("/v1/models", get(list_models))
// Standard inference endpoints
.route("/v1/completions", post(completions))
.route("/v1/chat/completions", post(chat_completions))
// Cached inference endpoints (existing)
.route("/v1/cached/completions", post(cached_completions))
.route("/v1/cached/chat/completions", post(cached_chat_completions))
.route("/v1/cache/stats", get(cache_stats))
.route("/v1/cache/clear", post(clear_cache));
// Add rate limiting endpoints if enabled
if self.state.config.enable_rate_limiting {
router = router
.route("/v1/rate-limits/status/:user_id", get(rate_limit_status))
.route("/v1/rate-limits/reset/:user_id", post(reset_rate_limits));
}
// Add structured generation endpoints if enabled
if self.state.config.enable_structured_generation {
router = router
.route("/v1/structured/generate", post(structured_generate))
.route("/v1/structured/schemas", get(list_schemas))
.route("/v1/structured/schemas", post(create_schema))
.route("/v1/structured/validate", post(validate_output));
}
// Add grammar sampling endpoints if enabled
if self.state.config.enable_grammar_sampling {
router = router
.route("/v1/grammar/generate", post(grammar_generate))
.route("/v1/grammar/validate", post(validate_grammar))
.route("/v1/grammar/parse", post(parse_bnf_grammar));
}
// Add billing endpoints if enabled
if self.state.config.enable_billing {
router = router
.route("/v1/billing/costs/:user_id", get(get_user_costs))
.route("/v1/billing/budgets", get(list_budgets))
.route("/v1/billing/budgets", post(create_budget))
.route("/v1/billing/forecasts/:entity_id", get(get_forecast));
}
// Add queue management endpoints if enabled
if self.state.config.enable_queue_management {
router = router
.route("/v1/queue/stats", get(queue_stats))
.route("/v1/queue/status/:request_id", get(request_status))
.route("/v1/queue/cancel/:request_id", post(cancel_request))
.route("/v1/queue/priority", post(priority_completions));
}
// Add streaming endpoints if enabled
if self.state.config.enable_streaming {
router = router
.route("/v1/stream/sse/:user_id", get(sse_stream))
.route("/v1/stream/ws/:user_id", get(websocket_upgrade))
.route("/v1/stream/chunked/:user_id", get(chunked_stream))
.route("/v1/stream/stats", get(stream_stats));
}
// Add multi-model endpoints if enabled
if self.state.config.enable_multi_model {
router = router
.route("/v1/models/load", post(load_model))
.route("/v1/models/unload/:instance_id", post(unload_model))
.route("/v1/models/stats", get(model_stats))
.route("/v1/models/ab-test", post(create_ab_test))
.route("/v1/models/canary", post(create_canary))
.route("/v1/models/ensemble", post(create_ensemble));
}
// Add state and middleware
router
.with_state(self.state.clone())
.layer(CorsLayer::permissive())
.layer(TraceLayer::new_for_http())
.layer(TimeoutLayer::new(Duration::from_secs(
self.state.config.timeout_seconds,
)))
}
/// Start the advanced server
pub async fn serve(&self) -> ApiResult<()> {
let app = self.app();
let addr = format!("{}:{}", self.state.config.host, self.state.config.port);
let listener = TcpListener::bind(&addr)
.await
.map_err(|e| ApiError::internal(format!("Failed to bind to {addr}: {e}")))?;
tracing::info!("Advanced LLM serving server listening on {}", addr);
tracing::info!(
"Features enabled: rate_limiting={}, structured_gen={}, grammar_sampling={}, billing={}, queue_mgmt={}, streaming={}, multi_model={}",
self.state.config.enable_rate_limiting,
self.state.config.enable_structured_generation,
self.state.config.enable_grammar_sampling,
self.state.config.enable_billing,
self.state.config.enable_queue_management,
self.state.config.enable_streaming,
self.state.config.enable_multi_model
);
// Start background tasks
self.start_background_tasks().await;
axum::serve(listener, app)
.await
.map_err(|e| ApiError::internal(format!("Server error: {e}")))?;
Ok(())
}
/// Start background tasks for cleanup and monitoring
async fn start_background_tasks(&self) {
if let Some(queue_manager) = &self.state.queue_manager {
let queue_manager = queue_manager.clone();
tokio::spawn(async move {
let mut interval = tokio::time::interval(Duration::from_secs(60));
loop {
interval.tick().await;
queue_manager.cleanup_expired_requests().await;
}
});
}
if let Some(rate_limiter) = &self.state.rate_limiter {
let rate_limiter = rate_limiter.clone();
tokio::spawn(async move {
let mut interval = tokio::time::interval(Duration::from_secs(300));
loop {
interval.tick().await;
rate_limiter.cleanup_expired_entries().await;
}
});
}
if let Some(stream_manager) = &self.state.stream_manager {
stream_manager.start_cleanup_task();
}
}
}
// Handler implementations (simplified for brevity - would implement full logic)
async fn health_check() -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"status": "healthy"})))
}
async fn list_models(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"models": []})))
}
async fn completions(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(
serde_json::json!({"response": "Generated completion"}),
))
}
async fn chat_completions(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(
serde_json::json!({"response": "Generated chat completion"}),
))
}
async fn cached_completions(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"response": "Cached completion"})))
}
async fn cached_chat_completions(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(
serde_json::json!({"response": "Cached chat completion"}),
))
}
async fn cache_stats(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"cache_stats": {}})))
}
async fn clear_cache(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"status": "cache cleared"})))
}
// Rate limiting handlers
async fn rate_limit_status(
Path(user_id): Path<String>,
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
if let Some(rate_limiter) = &state.rate_limiter {
if let Some(usage) = rate_limiter.get_user_usage(&user_id) {
Ok(Json(serde_json::json!(usage)))
} else {
Ok(Json(serde_json::json!({"error": "User not found"})))
}
} else {
Err(ApiError::not_found("Rate limiting not enabled"))
}
}
async fn reset_rate_limits(
Path(user_id): Path<String>,
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"status": "rate limits reset"})))
}
// Structured generation handlers
async fn structured_generate(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(
serde_json::json!({"structured_response": "Generated"}),
))
}
async fn list_schemas(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"schemas": []})))
}
async fn create_schema(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"schema_id": "new_schema"})))
}
async fn validate_output(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"valid": true})))
}
// Grammar sampling handlers
async fn grammar_generate(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"grammar_response": "Generated"})))
}
async fn validate_grammar(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"valid": true})))
}
async fn parse_bnf_grammar(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"parsed": true})))
}
// Billing handlers
async fn get_user_costs(
Path(user_id): Path<String>,
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"costs": []})))
}
async fn list_budgets(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"budgets": []})))
}
async fn create_budget(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"budget_id": "new_budget"})))
}
async fn get_forecast(
Path(entity_id): Path<String>,
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"forecast": {}})))
}
// Queue management handlers
async fn queue_stats(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
if let Some(queue_manager) = &state.queue_manager {
let stats = queue_manager.get_queue_stats();
Ok(Json(serde_json::json!(stats)))
} else {
Err(ApiError::not_found("Queue management not enabled"))
}
}
async fn request_status(
Path(request_id): Path<String>,
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"status": "processing"})))
}
async fn cancel_request(
Path(request_id): Path<String>,
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"status": "cancelled"})))
}
async fn priority_completions(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"response": "Priority completion"})))
}
// Streaming handlers
async fn sse_stream(
Path(user_id): Path<String>,
State(state): State<AdvancedServerState>,
) -> ApiResult<
Sse<
impl futures_util::Stream<Item = Result<axum::response::sse::Event, axum::Error>> + 'static,
>,
> {
// Clone the Arc to get 'static lifetime for the stream
let stream_manager = state
.stream_manager
.clone()
.ok_or_else(|| ApiError::not_found("Streaming not enabled"))?;
let stream = stream_manager
.create_sse_stream(user_id, "default".to_string())
.await
.map_err(|e| ApiError::internal(format!("Failed to create SSE stream: {e}")))?;
Ok(Sse::new(stream).keep_alive(
axum::response::sse::KeepAlive::new()
.interval(Duration::from_secs(30))
.text("keep-alive"),
))
}
async fn websocket_upgrade(
Path(user_id): Path<String>,
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(
serde_json::json!({"message": "WebSocket upgrade would be handled here"}),
))
}
async fn chunked_stream(
Path(user_id): Path<String>,
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(
serde_json::json!({"message": "Chunked stream would be handled here"}),
))
}
async fn stream_stats(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
if let Some(stream_manager) = &state.stream_manager {
let stats = stream_manager.get_stream_stats();
Ok(Json(serde_json::json!(stats)))
} else {
Err(ApiError::not_found("Streaming not enabled"))
}
}
// Multi-model handlers
async fn load_model(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(
serde_json::json!({"instance_id": "new_model_instance"}),
))
}
async fn unload_model(
Path(instance_id): Path<String>,
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"status": "model unloaded"})))
}
async fn model_stats(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
if let Some(model_manager) = &state.model_manager {
let stats = model_manager.get_model_stats();
Ok(Json(serde_json::json!(stats)))
} else {
Err(ApiError::not_found("Multi-model serving not enabled"))
}
}
async fn create_ab_test(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"test_id": "new_ab_test"})))
}
async fn create_canary(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"deployment_id": "new_canary"})))
}
async fn create_ensemble(
State(state): State<AdvancedServerState>,
) -> ApiResult<Json<serde_json::Value>> {
Ok(Json(serde_json::json!({"ensemble_id": "new_ensemble"})))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_advanced_server_config_default() {
let config = AdvancedServerConfig::default();
assert_eq!(config.host, "127.0.0.1");
assert_eq!(config.port, 8080);
assert!(config.enable_rate_limiting);
assert!(config.enable_streaming);
assert!(config.enable_multi_model);
}
#[test]
fn test_advanced_server_state_creation() {
let config = AdvancedServerConfig::default();
let state = AdvancedServerState::new(config.clone());
assert!(state.rate_limiter.is_some());
assert!(state.structured_gen.is_some());
assert!(state.billing_manager.is_some());
assert!(state.queue_manager.is_some());
assert!(state.stream_manager.is_some());
assert!(state.model_manager.is_some());
}
#[test]
fn test_advanced_server_creation() {
let config = AdvancedServerConfig::default();
let server = AdvancedServingServer::new(config);
// Should be able to build the app router
let _app = server.app();
}
#[test]
fn test_rate_limit_config() {
let config = RateLimitConfig {
requests_per_minute: 100,
tokens_per_minute: 50000,
burst_allowance: 1.5,
enable_user_tiers: true,
};
assert_eq!(config.requests_per_minute, 100);
assert_eq!(config.tokens_per_minute, 50000);
assert!(config.enable_user_tiers);
}
}