use std::collections::BTreeMap;
use std::path::PathBuf;
use serde::{Deserialize, Serialize};
pub const ENGINE_CONFIG_SCHEMA_VERSION: u32 = 1;
pub const ENGINE_SPEC_SCHEMA_VERSION: u32 = 15;
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct EngineConfig {
pub schema_version: u32,
pub model_name: String,
pub system_name: String,
#[serde(default)]
pub systems_path: Option<PathBuf>,
pub backend: BackendKind,
pub backend_version: Option<String>,
#[serde(default)]
pub forward_model: Option<String>,
pub kv_block_size: Option<u32>,
#[serde(flatten)]
pub parallel: ParallelMapping,
#[serde(flatten)]
pub quantization: QuantizationConfig,
#[serde(flatten)]
pub speculative: Option<SpeculativeConfig>,
#[serde(default)]
pub enable_shared_layer: Option<bool>,
#[serde(default)]
pub strict_provenance: bool,
#[serde(default)]
pub database_mode: crate::common::enums::DatabaseMode,
#[serde(default)]
pub tolerate_dirless_version: bool,
#[serde(default)]
pub transfer_policy: Option<Vec<String>>,
#[serde(default)]
pub extra: BTreeMap<String, String>,
}
pub type PerfDbSources = BTreeMap<String, Vec<PerfSource>>;
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct PerfSource(pub PathBuf, pub Option<Vec<String>>);
impl PerfSource {
pub fn path(&self) -> &std::path::Path {
&self.0
}
pub fn kernel_sources(&self) -> Option<&[String]> {
self.1.as_deref()
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct ParallelMapping {
pub tp_size: u32,
pub pp_size: u32,
#[serde(default)]
pub attention_dp_size: Option<u32>,
#[serde(default)]
pub moe_tp_size: Option<u32>,
#[serde(default)]
pub moe_ep_size: Option<u32>,
#[serde(default)]
pub cp_size: Option<u32>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct QuantizationConfig {
pub weight_dtype: Option<DataType>,
#[serde(default)]
pub moe_dtype: Option<DataType>,
pub activation_dtype: Option<DataType>,
pub kv_cache_dtype: Option<DataType>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct SpeculativeConfig {
#[serde(default)]
pub nextn: Option<u32>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum BackendKind {
Trtllm,
Sglang,
Vllm,
}
impl BackendKind {
pub(crate) fn as_str(&self) -> &'static str {
match self {
Self::Trtllm => "trtllm",
Self::Sglang => "sglang",
Self::Vllm => "vllm",
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum DataType {
#[serde(rename = "bfloat16")]
Bfloat16,
#[serde(rename = "float16")]
Float16,
#[serde(rename = "fp8")]
Fp8,
#[serde(rename = "fp8_static")]
Fp8Static,
#[serde(rename = "fp8_block")]
Fp8Block,
#[serde(rename = "nvfp4")]
Nvfp4,
#[serde(rename = "int8")]
Int8,
#[serde(rename = "int4")]
Int4,
#[serde(rename = "w4afp8")]
W4afp8,
#[serde(rename = "w4a16_mxfp4")]
W4a16Mxfp4,
#[serde(rename = "w4a8_mxfp4_mxfp8")]
W4a8Mxfp4Mxfp8,
#[serde(rename = "w4a8_mxfp4_mxfp8_trtllm")]
W4a8Mxfp4Mxfp8Trtllm,
#[serde(rename = "w4a16_mxfp4_cutlass")]
W4a16Mxfp4Cutlass,
#[serde(rename = "w4a16_nvfp4")]
W4a16Nvfp4,
}
#[cfg(test)]
mod engine_config_wire_tests {
use super::*;
#[test]
fn flat_python_payload_deserializes_into_regrouped_config() {
let json = r#"{
"schema_version": 1,
"model_name": "Qwen/Qwen3-32B",
"model_arch": "Qwen3ForCausalLM",
"system_name": "h200_sxm",
"backend": "trtllm",
"backend_version": "1.0.0",
"tp_size": 2,
"pp_size": 1,
"moe_tp_size": null,
"moe_ep_size": null,
"attention_dp_size": null,
"weight_dtype": "bfloat16",
"moe_dtype": null,
"activation_dtype": "bfloat16",
"kv_cache_dtype": "bfloat16",
"kv_block_size": null,
"nextn": null,
"extra": {}
}"#;
let config: EngineConfig = serde_json::from_str(json).expect("flat payload must parse");
assert_eq!(config.parallel.tp_size, 2);
assert_eq!(config.parallel.pp_size, 1);
assert_eq!(config.parallel.attention_dp_size, None);
assert_eq!(config.parallel.moe_tp_size, None);
assert_eq!(config.parallel.moe_ep_size, None);
assert_eq!(config.quantization.weight_dtype, Some(DataType::Bfloat16));
assert_eq!(config.quantization.moe_dtype, None);
let nextn = config.speculative.as_ref().and_then(|s| s.nextn);
assert_eq!(nextn, None);
assert!(!config.extra.contains_key("model_arch"));
assert_eq!(config.model_name, "Qwen/Qwen3-32B");
assert_eq!(config.systems_path, None);
}
}