Skip to main content

superfluid_executor/
capabilities.rs

1//! The executor's capability descriptor.
2
3use superfluid_abi::{encoding, MAX_TOP_LOGPROBS};
4use serde_json::{json, Map, Value};
5
6use crate::primitives::{RuntimeDescriptor, SamplingDefaults};
7
8fn cap(reason: Option<String>) -> Value {
9    reason.map(Value::String).unwrap_or(Value::Bool(true))
10}
11
12fn no(reason: impl Into<String>) -> Value {
13    Value::String(reason.into())
14}
15
16fn sampling_defaults(sd: &SamplingDefaults) -> Option<Value> {
17    let mut m = Map::new();
18    let mut put = |k: &str, v: Option<Value>| {
19        if let Some(v) = v {
20            m.insert(k.to_string(), v);
21        }
22    };
23    put("temperature", sd.temperature.map(|x| json!(x)));
24    put("top_p", sd.top_p.map(|x| json!(x)));
25    put("top_k", sd.top_k.map(|x| json!(x)));
26    put("min_p", sd.min_p.map(|x| json!(x)));
27    put("repetition_penalty", sd.repetition_penalty.map(|x| json!(x)));
28    if let Some(d) = sd.do_sample {
29        m.insert("do_sample".to_string(), Value::Bool(d));
30    }
31    (!m.is_empty()).then_some(Value::Object(m))
32}
33
34/// `verify_rows`: the runtime answers `step_rows`, so it can verify a
35/// prompt-lookup draft (models that cannot roll back are refused once loaded).
36pub fn static_descriptor(id: &str, export_encodings: &[u8], verify_rows: bool) -> serde_json::Value {
37    let lossy = export_encodings.iter().any(|e| *e != encoding::LOSSLESS);
38    let media = || no(format!("the {id} runtime has no media path"));
39    let lora = || no(format!("the {id} runtime loads no LoRA"));
40    json!({
41        "descriptor_version": 1,
42        "runtime": {"id": id},
43        "load": {
44            "paged_kv": false,
45            "prefix_cache": true,
46            "kv_bits": no(format!("the {id} runtime keeps its KV type per context and exposes no such knob")),
47        },
48        "workload": {
49            "causal_generation": true,
50            "embedding": no(format!("the {id} runtime serves generation; it has no embedding path")),
51            "speech_to_text": no("not a speech model"),
52        },
53        "modalities": {
54            "image_encode": media(),
55            "gemma_audio_encode": media(),
56            "whisper_transcribe": no("not a Whisper model"),
57            "whisper_translate": no("not a Whisper model"),
58        },
59        "serving": {
60            "sequences": true,
61            "host_logits": true,
62            "multi_row_verification": if verify_rows {
63                Value::Bool(true)
64            } else {
65                no(format!("the {id} runtime registers no speculation strategy"))
66            },
67            "speculation_strategies": if verify_rows { json!([crate::speculate::STRATEGY_ID]) } else { json!([]) },
68            "prefix_seed": true,
69            "park_lossless": export_encodings.contains(&encoding::LOSSLESS),
70            "park_lossy": cap((!lossy).then(|| format!("the {id} runtime exports no lossy encoding"))),
71            "round_granular": true,
72        },
73        "state": {"legacy_save_load": no("the native engine's state-file API")},
74        "adaptation": {"lora_load": lora(), "lora_active_on_inference": lora()},
75        "ops": {
76            "snapshot_restore": true,
77            "seq_fork": true,
78            "space_promote": no("no demoted tier: parks are lossless exports"),
79            "cache_evict_entries": true,
80        },
81        "sampling": {"logit_bias": true, "penalties": true, "top_logprobs_max": MAX_TOP_LOGPROBS},
82        "determinism": {
83            "seed_reproducible": true,
84            "batch_invariant": no("a batched round or another prefill chunking moves logits by rounding"),
85        },
86    })
87}
88
89pub fn model_facts(architecture: &str, sd: &SamplingDefaults) -> Value {
90    let mut v = json!({"architecture": architecture});
91    if let Some(s) = sampling_defaults(sd) {
92        v["sampling_defaults"] = s;
93    }
94    v
95}
96
97pub(crate) fn descriptor(d: &RuntimeDescriptor, grammar: bool) -> String {
98    let id = d.runtime_id.as_str();
99    let mut v = static_descriptor(id, &d.export_encodings, d.verify_rows);
100    if d.verify_rows && !d.truncate_partial {
101        v["serving"]["multi_row_verification"] = json!(format!(
102            "prompt-lookup cuts a rejected draft off, and this model's {} state cuts only at its head",
103            if d.recurrent { "recurrent" } else { "sliding-window" }
104        ));
105        v["serving"]["speculation_strategies"] = json!([]);
106    }
107    v["architecture"] = json!(d.architecture);
108    v["backend"] = json!(d.backend);
109    v["runtime"]["version"] = json!(d.runtime_version);
110    v["load"]["max_batch_size"] = json!(d.max_batch);
111    v["serving"]["tick_yield"] =
112        cap((d.prefill_step_tokens == 0).then(|| format!("the {id} runtime prefills a tick as one step")));
113    v["state"]["rollback"] = cap((!d.truncate_partial).then(|| "recurrent state cuts only at its head".to_string()));
114    v["state"]["shared_prefix_seed"] = cap((!d.truncate_partial).then(|| {
115        "a cached state seeds only a prompt that holds all of it: recurrent state cuts only at its head".to_string()
116    }));
117    v["state"]["recurrent_snapshot"] = cap((!d.recurrent).then(|| "no recurrent state in this architecture".to_string()));
118    v["sampling"]["grammar"] =
119        cap((!grammar).then(|| format!("the {id} runtime lists no vocabulary to compile grammars against")));
120    v["sampling"]["engine_argmax"] = json!(d.engine_sampling);
121    v["sampling"]["engine_draws"] = json!(d.engine_draws);
122    v["limits"] = json!({
123        "max_seq_len": d.max_seq_len,
124        "max_seqs": d.max_seqs,
125        "page_size_tokens": d.page_size_tokens,
126        "cells_total": d.cells_total,
127        "cache_resident_cells": d.cache_resident_cells,
128        "cache_exported_cells": d.cache_exported_cells,
129    });
130    if let Some(sd) = sampling_defaults(&d.sampling_defaults) {
131        v["sampling_defaults"] = sd;
132    }
133    v.to_string()
134}
135
136#[cfg(test)]
137mod tests {
138    use super::*;
139
140    fn desc() -> RuntimeDescriptor {
141        crate::fake::FakePrimitives::default().describe()
142    }
143
144    use crate::primitives::RuntimePrimitives;
145
146    #[test]
147    fn a_runtime_reports_what_it_lacks_in_its_own_words() {
148        let v: Value = serde_json::from_str(&descriptor(&desc(), false)).unwrap();
149        assert_eq!(v["descriptor_version"], 1);
150        assert_eq!(v["runtime"], json!({"id": "fake", "version": "1"}));
151        assert_eq!(v["serving"]["park_lossy"], "the fake runtime exports no lossy encoding");
152        assert_eq!(v["serving"]["park_lossless"], true);
153        assert_eq!(v["modalities"]["image_encode"], "the fake runtime has no media path");
154        assert_eq!(v["sampling"]["grammar"], "the fake runtime lists no vocabulary to compile grammars against");
155        assert_eq!(v["state"]["rollback"], true, "the fake cuts anywhere by default");
156        assert_eq!(v["state"]["shared_prefix_seed"], true);
157        assert!(v.get("sampling_defaults").is_none(), "a checkpoint that claims none carries none");
158    }
159
160    #[test]
161    fn a_models_facts_are_the_records_artifact_fields() {
162        let sd = SamplingDefaults { top_p: Some(0.95), ..Default::default() };
163        assert_eq!(model_facts("qwen3", &sd), json!({"architecture": "qwen3", "sampling_defaults": {"top_p": 0.95}}));
164        assert_eq!(model_facts("llama", &SamplingDefaults::default()), json!({"architecture": "llama"}));
165    }
166
167    #[test]
168    fn the_checkpoints_sampling_defaults_ride_along_and_only_what_it_claims() {
169        let mut d = desc();
170        d.sampling_defaults = SamplingDefaults { temperature: Some(0.6), top_k: Some(20), ..Default::default() };
171        d.truncate_partial = false;
172        let v: Value = serde_json::from_str(&descriptor(&d, true)).unwrap();
173        assert_eq!(v["sampling_defaults"], json!({"temperature": 0.6, "top_k": 20}));
174        assert_eq!(v["sampling"]["grammar"], true);
175        assert_eq!(v["state"]["rollback"], "recurrent state cuts only at its head");
176        assert!(v["state"]["shared_prefix_seed"].is_string(), "a burst on one prefix needs a kept copy");
177    }
178
179    #[test]
180    fn the_static_part_is_what_every_load_reports() {
181        let s = static_descriptor("fake", &[encoding::LOSSLESS], false);
182        let full: Value = serde_json::from_str(&descriptor(&desc(), false)).unwrap();
183        for (section, keys) in s.as_object().unwrap() {
184            let Some(keys) = keys.as_object() else { continue };
185            for (k, v) in keys {
186                if section == "runtime" {
187                    continue;
188                }
189                assert_eq!(&full[section][k], v, "{section}.{k}");
190            }
191        }
192    }
193}