use metrale_config::{IndexerCacheDtype, MoeExpertLayout, WeightQuantization};
use metrale_gpu_runtime::prefill_tail_mode::PrefillTailMode;
use metrale_model_layers::layers::{DenseQuantization, DsaQuantization, ExpertQuantization};
pub(crate) const AUTO_KV_HIGH_PRECISION_LAYERS: usize = 2;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum KvHighPrecisionLayers {
All,
Auto,
Count(usize),
}
impl std::str::FromStr for KvHighPrecisionLayers {
type Err = String;
fn from_str(raw: &str) -> Result<Self, String> {
match raw.trim().to_lowercase().as_str() {
"max" | "all" => Ok(Self::All),
"auto" => Ok(Self::Auto),
s => s.parse::<usize>().map(Self::Count).map_err(|_| {
"expected a whole number of layers, or one of: auto, max, all".to_string()
}),
}
}
}
impl KvHighPrecisionLayers {
pub(crate) fn resolve(self, num_attn_layers: usize) -> usize {
match self {
Self::All => num_attn_layers,
Self::Auto => AUTO_KV_HIGH_PRECISION_LAYERS,
Self::Count(n) => n,
}
}
}
pub(crate) const TRISTATES: &[&str] = &["auto", "on", "off"];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Tristate {
Auto,
On,
Off,
}
impl std::str::FromStr for Tristate {
type Err = String;
fn from_str(raw: &str) -> Result<Self, String> {
match raw {
"auto" => Ok(Self::Auto),
"on" => Ok(Self::On),
"off" => Ok(Self::Off),
other => Err(format!("expected one of auto, on, off; got {other:?}")),
}
}
}
impl Tristate {
pub(crate) fn validated(raw: &str) -> Self {
raw.parse().expect("validated by validate_serve_args")
}
pub(crate) fn pinned(self) -> Option<bool> {
match self {
Self::Auto => None,
Self::On => Some(true),
Self::Off => Some(false),
}
}
}
pub(crate) fn canonical_kv_cache_dtype(raw: &str) -> Result<String, String> {
let canonical = match raw {
"fp8_e4m3" => "fp8",
other => other,
};
Ok(canonical.to_string())
}
pub(crate) const LM_HEAD_DTYPES: &[&str] = &["default", "bf16", "nvfp4", "fp8"];
pub(crate) const MTP_QUANTS: &[&str] = &["bf16", "fp8", "nvfp4"];
pub(crate) const SCHEDULERS: &[&str] = &["fifo", "slai"];
pub(crate) const SCHEDULER_CONFIGS: &[&str] = &["sync", "async"];
pub(crate) const TELEMETRY_LEVELS: &[&str] = &metrale_telemetry::Level::NAMES;
pub(crate) const SSM_H_DTYPES: &[&str] = &["f32", "f16", "f16-pool"];
pub(crate) const MTP_GATES: &[&str] = &["auto", "force"];
pub(crate) const TOOL_CALL_PARSERS: &[&str] = &[
"hermes",
"qwen3_coder",
"qwen3_xml",
"gemma4",
"mistral",
"minimax_xml",
"bare_json",
"poolside_v1",
"glm47",
];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ExpertQuantizationArg(pub ExpertQuantization);
impl clap::ValueEnum for ExpertQuantizationArg {
fn value_variants<'a>() -> &'a [Self] {
const VARIANTS: [ExpertQuantizationArg; 3] = [
ExpertQuantizationArg(ExpertQuantization::ALL[0]),
ExpertQuantizationArg(ExpertQuantization::ALL[1]),
ExpertQuantizationArg(ExpertQuantization::ALL[2]),
];
&VARIANTS
}
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
let help = match self.0 {
ExpertQuantization::Fp8 => {
"the checkpoint's FP8 experts (most stable, still fast). BFCL echolp N=1004 \
84.96/86.03 overall/normalized; agentic-webserver pass (535-546 s); C16 \
315.5 tok/s, 0.227 J/tok"
}
ExpertQuantization::Nvfp4GateUp => {
"lowers the routed experts' gate and up projections to NVFP4 in decode; down, \
the shared expert and prefill stay FP8 (the stable speed lever). BFCL \
84.86/85.33; agentic-webserver pass 3/3 (504-533 s); C16 359.6 tok/s, \
0.211 J/tok"
}
ExpertQuantization::Nvfp4 => {
"lowers every routed-expert projection to NVFP4 in decode; the shared expert and \
prefill stay FP8 (dangerous but fast). BFCL 85.46/86.57; agentic-webserver \
FAILS its 700 s ceiling (168 turns, 774 s); C16 383.1 tok/s, 0.201 J/tok"
}
};
Some(clap::builder::PossibleValue::new(self.0.name()).help(help))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DenseQuantizationArg(pub DenseQuantization);
impl clap::ValueEnum for DenseQuantizationArg {
fn value_variants<'a>() -> &'a [Self] {
const VARIANTS: [DenseQuantizationArg; 3] = [
DenseQuantizationArg(DenseQuantization::ALL[0]),
DenseQuantizationArg(DenseQuantization::ALL[1]),
DenseQuantizationArg(DenseQuantization::ALL[2]),
];
&VARIANTS
}
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
let help = match self.0 {
DenseQuantization::Declared => "16-bit dense projections at the checkpoint's width",
DenseQuantization::Fp8 => {
"16-bit dense projections quantized at load to FP8 per-channel and decoded \
W8A8 with per-token FP8 activations: below the checkpoint's declared \
precision (glm5_next only; unmeasured)"
}
DenseQuantization::W4a16 => {
"FURTHER BELOW the checkpoint's declared precision than fp8: the KDA q/k/v, \
f_a, b, g_a and o projections and the shared expert quantized at load to \
NVFP4 (4-bit weights) and decoded W4A16 with 16-bit activations; the rest of \
fp8's set stays fp8 (glm5_next only; unmeasured)"
}
};
Some(clap::builder::PossibleValue::new(self.0.name()).help(help))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DsaQuantizationArg(pub DsaQuantization);
impl clap::ValueEnum for DsaQuantizationArg {
fn value_variants<'a>() -> &'a [Self] {
const VARIANTS: [DsaQuantizationArg; 3] = [
DsaQuantizationArg(DsaQuantization::ALL[0]),
DsaQuantizationArg(DsaQuantization::ALL[1]),
DsaQuantizationArg(DsaQuantization::ALL[2]),
];
&VARIANTS
}
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
let help = match self.0 {
DsaQuantization::Declared => {
"the DSA q_a, absorbed q and absorbed o projections at the checkpoint's BF16"
}
DsaQuantization::W8a8 => {
"those three quantized at load to FP8 per-channel and decoded W8A8 with \
per-token FP8 activations, as the reference engine runs them: below the \
checkpoint's declared precision (glm5_next only)"
}
DsaQuantization::W4a16 => {
"FURTHER BELOW declared than w8a8: those three quantized at load to NVFP4 \
(4-bit weights) and decoded W4A16 with 16-bit activations (glm5_next only)"
}
};
Some(clap::builder::PossibleValue::new(self.0.name()).help(help))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PrefillTailModeArg(pub PrefillTailMode);
impl clap::ValueEnum for PrefillTailModeArg {
fn value_variants<'a>() -> &'a [Self] {
const VARIANTS: [PrefillTailModeArg; 2] = [
PrefillTailModeArg(PrefillTailMode::ALL[0]),
PrefillTailModeArg(PrefillTailMode::ALL[1]),
];
&VARIANTS
}
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
Some(clap::builder::PossibleValue::new(self.0.name()).help(self.0.describe()))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IndexerCacheDtypeArg(pub IndexerCacheDtype);
impl clap::ValueEnum for IndexerCacheDtypeArg {
fn value_variants<'a>() -> &'a [Self] {
const VARIANTS: [IndexerCacheDtypeArg; 2] = [
IndexerCacheDtypeArg(IndexerCacheDtype::ALL[0]),
IndexerCacheDtypeArg(IndexerCacheDtype::ALL[1]),
];
&VARIANTS
}
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
let help = match self.0 {
IndexerCacheDtype::Bf16 => "a bf16 key row and gate row per token",
IndexerCacheDtype::Fp8 => {
"one FP8 E4M3 compressed key per complete pool plus a bf16 ring for the pool \
being filled; more context per KV byte (glm5_next only)"
}
};
Some(clap::builder::PossibleValue::new(self.0.name()).help(help))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MoeExpertLayoutArg(pub MoeExpertLayout);
impl clap::ValueEnum for MoeExpertLayoutArg {
fn value_variants<'a>() -> &'a [Self] {
const VARIANTS: [MoeExpertLayoutArg; 2] = [
MoeExpertLayoutArg(MoeExpertLayout::ALL[0]),
MoeExpertLayoutArg(MoeExpertLayout::ALL[1]),
];
&VARIANTS
}
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
let help = match self.0 {
MoeExpertLayout::Ep => "each routed expert owned whole by one --ep-size rank",
MoeExpertLayout::Tp => {
"every routed expert's intermediate width split over the --tp-size ranks, all \
slots local on every rank; needs --ep-size 1 (glm5_next only; unmeasured)"
}
};
Some(clap::builder::PossibleValue::new(self.0.name()).help(help))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct WeightQuantizationArg(pub WeightQuantization);
impl clap::ValueEnum for WeightQuantizationArg {
fn value_variants<'a>() -> &'a [Self] {
const VARIANTS: [WeightQuantizationArg; 2] = [
WeightQuantizationArg(WeightQuantization::ALL[0]),
WeightQuantizationArg(WeightQuantization::ALL[1]),
];
&VARIANTS
}
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
let help = match self.0 {
WeightQuantization::Declared => WEIGHT_QUANT_DECLARED_HELP,
WeightQuantization::Nvfp4 => WEIGHT_QUANT_NVFP4_HELP,
};
Some(clap::builder::PossibleValue::new(self.0.name()).help(help))
}
}
const WEIGHT_QUANT_DECLARED_HELP: &str = "each layer at the precision its checkpoint's \
quantization_config declares, weights and activations (W4A4 where it declares FP4 \
activations, W4A16 where weight-only). Until the W8A8 decode kernels land, FP8-declared \
layers run 16-bit activations (above declared), and the dense loader still requantizes \
per-channel FP8 attention/GDN/MLP to NVFP4";
const WEIGHT_QUANT_NVFP4_HELP: &str = "the engine before the tiers: FP8-declared layers \
requantized to NVFP4 at load (below declared), 16-bit decode activations unless \
--w4a4-downcast, FP4 MMQ prefill on every NVFP4 FFN; the certified recipes' tier";
pub(crate) fn options_for_flag(flag: &str) -> Option<Vec<String>> {
let owned = |list: &[&str]| list.iter().map(|s| s.to_string()).collect();
match flag {
"lm-head-dtype" => Some(owned(LM_HEAD_DTYPES)),
"mtp-quantization" => Some(owned(MTP_QUANTS)),
"scheduler" => Some(owned(SCHEDULERS)),
"scheduler-config" => Some(owned(SCHEDULER_CONFIGS)),
"ssm-h-dtype" => Some(owned(SSM_H_DTYPES)),
"telemetry" => Some(owned(TELEMETRY_LEVELS)),
"mtp-gate" => Some(owned(MTP_GATES)),
"tool-call-parser" => Some(owned(TOOL_CALL_PARSERS)),
"ssm-batched-recurrent" | "content-loop-watchdog" | "tool-grammar" => {
Some(owned(TRISTATES))
}
"weight-quantization" => Some(
WeightQuantization::ALL
.iter()
.map(|q| q.name().to_string())
.collect(),
),
"dense-quantization" => Some(
DenseQuantization::ALL
.iter()
.map(|q| q.name().to_string())
.collect(),
),
"moe-expert-layout" => Some(
MoeExpertLayout::ALL
.iter()
.map(|l| l.name().to_string())
.collect(),
),
"indexer-cache-dtype" => Some(
IndexerCacheDtype::ALL
.iter()
.map(|d| d.name().to_string())
.collect(),
),
"expert-quantization" => Some(
ExpertQuantization::ALL
.iter()
.map(|q| q.name().to_string())
.collect(),
),
"kv-cache-dtype" => Some(
metrale_cache::kv_cache::KvCacheDtype::ALL
.iter()
.map(|d| d.name().to_string())
.collect(),
),
_ => None,
}
}
#[cfg(test)]
#[path = "flag_values_tests.rs"]
mod tests;
#[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)]
pub enum ForwardArg {
#[value(help = "the hand-written layer loops")]
Legacy,
#[value(help = "the program compiled from the model's circuit plan")]
Circuit,
#[value(
help = "the circuit plan with reference rules only (no bit-identical fusions), for A/B"
)]
CircuitReference,
}
impl ForwardArg {
pub fn name(self) -> &'static str {
match self {
ForwardArg::Legacy => "legacy",
ForwardArg::Circuit => "circuit",
ForwardArg::CircuitReference => "circuit-reference",
}
}
}