#[cfg(feature = "inference")]
fn dominant_quantization(model: &realizar::gguf::OwnedQuantizedModel) -> Option<&'static str> {
use std::collections::HashMap;
let mut counts: HashMap<u32, usize> = HashMap::new();
for layer in model.layers() {
let mut tally = |qtype: u32| *counts.entry(qtype).or_insert(0) += 1;
tally(layer.attn_output_weight.qtype);
tally(layer.ffn_up_weight.qtype);
tally(layer.ffn_down_weight.qtype);
if let Some(gate) = layer.ffn_gate_weight.as_ref() {
tally(gate.qtype);
}
}
counts
.into_iter()
.filter_map(|(qtype, n)| realizar::api::gguf_qtype_name(qtype).map(|name| (name, n)))
.max_by_key(|&(_, n)| n)
.map(|(name, _)| name)
}
#[cfg(feature = "inference")]
fn measured_model_source(
model: &realizar::gguf::OwnedQuantizedModel,
config: &ServerConfig,
) -> realizar::api::ModelSourceInfo {
let base = config
.model_path
.as_deref()
.map(realizar::api::ModelSourceInfo::from_path)
.unwrap_or_default();
let mut source = base
.with_architecture(model.config().architecture.as_str())
.with_model_max_context_length(model.config().context_length)
.with_context_length(config.context_length);
if let Some(quantization) = dominant_quantization(model) {
source = source.with_quantization(quantization);
}
source
}
#[cfg(feature = "inference")]
fn run_cpu_server(
quantized_model: realizar::gguf::OwnedQuantizedModel,
vocab: Vec<String>,
mapped_model: Option<std::sync::Arc<realizar::gguf::MappedGGUFModel>>,
config: &ServerConfig,
) -> Result<()> {
use realizar::api::{create_router_with_config, AppState};
let model_source = measured_model_source(&quantized_model, config);
let mut state = AppState::with_quantized_model_and_vocab(quantized_model, vocab)
.map_err(|e| CliError::InferenceFailed(format!("Failed to create app state: {e}")))?
.with_model_source(model_source);
if let Some(mapped) = mapped_model {
state = state.with_mapped_gguf_model(mapped);
}
let state = state.with_verbose(config.verbose);
let app = create_router_with_config(state, config.router_config());
let runtime = tokio::runtime::Runtime::new()
.map_err(|e| CliError::InferenceFailed(format!("Failed to create runtime: {e}")))?;
let bind_addr = config.bind_addr();
let endpoints = realizar::api::advertised_routes(&config.router_config());
runtime.block_on(async move {
let listener = tokio::net::TcpListener::bind(&bind_addr)
.await
.map_err(|e| CliError::InferenceFailed(format!("Failed to bind: {e}")))?;
println!();
println!(
"{}",
format!("Inference server listening on http://{}", bind_addr)
.green()
.bold()
);
println!();
println!("{}", "Endpoints:".cyan());
for endpoint in &endpoints {
println!(" {endpoint}");
}
println!();
println!(
"{}",
"Performance targets: 100+ tok/s CPU, 500+ tok/s GPU".yellow()
);
println!("{}", "Press Ctrl+C to stop".dimmed());
axum::serve(listener, app)
.with_graceful_shutdown(shutdown_signal())
.await
.map_err(|e| CliError::InferenceFailed(format!("Server error: {e}")))?;
println!();
println!("{}", "Server stopped".yellow());
Ok(())
})
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(all(feature = "inference", feature = "cuda"))]
fn start_gguf_server_gpu_batched(
quantized_model: realizar::gguf::OwnedQuantizedModel,
vocab: Vec<String>,
mapped_model: std::sync::Arc<realizar::gguf::MappedGGUFModel>,
config: &ServerConfig,
) -> Result<()> {
use realizar::api::{create_router_with_config, spawn_batch_processor, AppState, BatchConfig};
use realizar::gguf::OwnedQuantizedModelCachedSync;
println!(
"{}",
"Enabling GPU batched inference (2X+ Ollama)...".cyan()
);
let runtime = tokio::runtime::Runtime::new()
.map_err(|e| CliError::InferenceFailed(format!("Failed to create runtime: {e}")))?;
let cached_model = OwnedQuantizedModelCachedSync::new(quantized_model);
println!(" Warming up GPU cache...");
match cached_model.warmup_gpu_cache() {
Ok((memory_bytes, num_layers)) => {
println!(
" GPU cache ready: {:.2} GB ({} layers)",
memory_bytes as f64 / 1e9,
num_layers
);
}
Err(e) => {
eprintln!(" Warning: GPU cache warmup failed: {e}");
}
}
let state = AppState::with_cached_model_and_vocab(cached_model, vocab)
.map_err(|e| CliError::InferenceFailed(format!("Failed to create app state: {e}")))?
.with_mapped_gguf_model(mapped_model)
.with_verbose(config.verbose);
let cached_model_arc = state
.cached_model()
.expect("cached_model should exist")
.clone();
let batch_config = BatchConfig::default();
println!(" Batch window: {}ms", batch_config.window_ms);
println!(" Optimal batch: {}", batch_config.optimal_batch);
println!(" GPU threshold: {}", batch_config.gpu_threshold);
let bind_addr = config.bind_addr();
let router_config = config.router_config();
runtime.block_on(async move {
let batch_tx = spawn_batch_processor(cached_model_arc, batch_config.clone());
println!(" Batch processor: RUNNING");
let state = state.with_batch_config(batch_tx, batch_config);
let app = create_router_with_config(state, router_config);
let listener = tokio::net::TcpListener::bind(&bind_addr)
.await
.map_err(|e| CliError::InferenceFailed(format!("Failed to bind: {e}")))?;
println!();
println!(
"{}",
format!("GPU Batched Server listening on http://{}", bind_addr)
.green()
.bold()
);
println!();
println!("{}", "2X Ollama Endpoints:".cyan());
println!(" GET /health - Health check");
println!(" GET /v1/gpu/status - GPU cache status");
println!(" POST /v1/completions - OpenAI-compatible (batched)");
println!(" POST /v1/batch/completions - Explicit batch inference");
println!();
println!(
"{}",
"Performance: 800+ tok/s (2.8x Ollama) with batched requests".yellow()
);
println!("{}", "Press Ctrl+C to stop".dimmed());
axum::serve(listener, app)
.with_graceful_shutdown(shutdown_signal())
.await
.map_err(|e| CliError::InferenceFailed(format!("Server error: {e}")))?;
println!();
println!("{}", "Server stopped".yellow());
Ok(())
})
}
#[cfg(feature = "inference")]
pub(crate) async fn shutdown_signal() {
tokio::signal::ctrl_c()
.await
.expect("Failed to install Ctrl+C handler");
}