Skip to main content

ferrum_interfaces/vnext/execution/
provider.rs

1use super::{
2    AttributeId, BTreeMap, BTreeSet, CapabilityId, ContractVersion, Deserialize, Deserializer,
3    ExecutionWeightPlan, MemoryPlan, ModelFamilyId, NodeId, NodeWorkContract, OperationId,
4    OperationRegistryAuthority, PlanExactAlias, PlanHash, PlanId, PlanNode,
5    PlanProviderRejectReason, PlanSchemaVersion, PlanStateEffect, ProviderId, ProviderResourcePlan,
6    ProviderSelection, ProviderWorkspaceRequirement, QuantizationFormatId, ResolvedValueBinding,
7    ResourceId, RetainedCompletionValue, SemanticValue, Serialize, WeightFormatId,
8};
9use crate::vnext::ProviderExecutionSemantics;
10
11/// Per-node trusted physical resolution. It supplies physical bindings and a
12/// provider estimator result, but cannot provide memory totals, compatibility
13/// reports, plan identities, or hashes.
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct PlanNodeResolution {
16    pub(super) operation_registry_authority: OperationRegistryAuthority,
17    pub(super) node_id: NodeId,
18    pub(super) values: Vec<ResolvedValueBinding>,
19    pub(super) required_capabilities: BTreeSet<CapabilityId>,
20    pub(super) preferred_provider: Option<ProviderId>,
21    pub(super) provider_resource_candidates: Vec<ProviderResourcePlan>,
22    pub(super) provider_resolution_rejections: BTreeMap<ProviderId, PlanProviderRejectReason>,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
26#[serde(deny_unknown_fields)]
27pub struct ExecutionPlanPayload {
28    pub(super) schema: PlanSchemaVersion,
29    pub(super) plan_id: PlanId,
30    pub(super) family_id: ModelFamilyId,
31    pub(super) device_id: super::DeviceId,
32    pub(super) device_runtime_implementation_fingerprint: String,
33    pub(super) prepared_family_fingerprint: String,
34    pub(super) program_fingerprint: String,
35    pub(super) capability_catalog_fingerprint: String,
36    pub(super) policy_version: ContractVersion,
37    pub(super) policy_fingerprint: String,
38    pub(super) maximum_scheduled_tokens: u64,
39    pub(super) execution_weights: ExecutionWeightPlan,
40    pub(super) weight_format: WeightFormatId,
41    pub(super) quantization_formats: BTreeSet<QuantizationFormatId>,
42    pub(super) retained_completion_values: Vec<RetainedCompletionValue>,
43    pub(super) terminal_output_resources: Vec<ResourceId>,
44    pub(super) nodes: Vec<PlanNode>,
45    pub(super) memory: MemoryPlan,
46}
47
48impl ExecutionPlanPayload {
49    pub const fn schema(&self) -> PlanSchemaVersion {
50        self.schema
51    }
52
53    pub fn plan_id(&self) -> &PlanId {
54        &self.plan_id
55    }
56
57    pub fn family_id(&self) -> &ModelFamilyId {
58        &self.family_id
59    }
60
61    pub fn device_id(&self) -> &super::DeviceId {
62        &self.device_id
63    }
64
65    pub fn device_runtime_implementation_fingerprint(&self) -> &str {
66        &self.device_runtime_implementation_fingerprint
67    }
68
69    pub fn prepared_family_fingerprint(&self) -> &str {
70        &self.prepared_family_fingerprint
71    }
72
73    pub fn program_fingerprint(&self) -> &str {
74        &self.program_fingerprint
75    }
76
77    pub fn capability_catalog_fingerprint(&self) -> &str {
78        &self.capability_catalog_fingerprint
79    }
80
81    pub const fn policy_version(&self) -> ContractVersion {
82        self.policy_version
83    }
84
85    pub fn policy_fingerprint(&self) -> &str {
86        &self.policy_fingerprint
87    }
88
89    pub const fn maximum_scheduled_tokens(&self) -> u64 {
90        self.maximum_scheduled_tokens
91    }
92
93    pub fn execution_weights(&self) -> &ExecutionWeightPlan {
94        &self.execution_weights
95    }
96
97    pub fn weight_format(&self) -> &WeightFormatId {
98        &self.weight_format
99    }
100
101    pub fn quantization_formats(&self) -> &BTreeSet<QuantizationFormatId> {
102        &self.quantization_formats
103    }
104
105    pub fn retained_completion_values(&self) -> &[RetainedCompletionValue] {
106        &self.retained_completion_values
107    }
108
109    pub fn terminal_output_resources(&self) -> &[ResourceId] {
110        &self.terminal_output_resources
111    }
112
113    pub fn nodes(&self) -> &[PlanNode] {
114        &self.nodes
115    }
116
117    pub fn memory(&self) -> &MemoryPlan {
118        &self.memory
119    }
120}
121
122#[derive(Serialize)]
123pub(super) struct PlanHashMaterial<'a> {
124    pub(super) schema: PlanSchemaVersion,
125    pub(super) family_id: &'a ModelFamilyId,
126    pub(super) device_id: &'a super::DeviceId,
127    pub(super) device_runtime_implementation_fingerprint: &'a str,
128    pub(super) prepared_family_fingerprint: &'a str,
129    pub(super) program_fingerprint: &'a str,
130    pub(super) capability_catalog_fingerprint: &'a str,
131    pub(super) policy_version: ContractVersion,
132    pub(super) policy_fingerprint: &'a str,
133    pub(super) maximum_scheduled_tokens: u64,
134    pub(super) execution_weights: &'a ExecutionWeightPlan,
135    pub(super) weight_format: &'a WeightFormatId,
136    pub(super) quantization_formats: &'a BTreeSet<QuantizationFormatId>,
137    pub(super) retained_completion_values: &'a [RetainedCompletionValue],
138    pub(super) terminal_output_resources: &'a [ResourceId],
139    pub(super) nodes: &'a [PlanNode],
140    pub(super) memory: &'a MemoryPlan,
141}
142
143impl<'a> From<&'a ExecutionPlanPayload> for PlanHashMaterial<'a> {
144    fn from(payload: &'a ExecutionPlanPayload) -> Self {
145        Self {
146            schema: payload.schema,
147            family_id: &payload.family_id,
148            device_id: &payload.device_id,
149            device_runtime_implementation_fingerprint: &payload
150                .device_runtime_implementation_fingerprint,
151            prepared_family_fingerprint: &payload.prepared_family_fingerprint,
152            program_fingerprint: &payload.program_fingerprint,
153            capability_catalog_fingerprint: &payload.capability_catalog_fingerprint,
154            policy_version: payload.policy_version,
155            policy_fingerprint: &payload.policy_fingerprint,
156            maximum_scheduled_tokens: payload.maximum_scheduled_tokens,
157            execution_weights: &payload.execution_weights,
158            weight_format: &payload.weight_format,
159            quantization_formats: &payload.quantization_formats,
160            retained_completion_values: &payload.retained_completion_values,
161            terminal_output_resources: &payload.terminal_output_resources,
162            nodes: &payload.nodes,
163            memory: &payload.memory,
164        }
165    }
166}
167
168/// A wire payload is deliberately not an executable plan. It must be rebuilt
169/// against a typed model family, catalog, and runtime policy before use.
170#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
171#[serde(deny_unknown_fields)]
172pub struct UnvalidatedProviderResourcePlan {
173    pub(super) provider_id: ProviderId,
174    pub(super) estimator_id: String,
175    pub(super) estimator_version: ContractVersion,
176    pub(super) estimator_implementation_fingerprint: String,
177    pub(super) estimator_input_fingerprint: String,
178    pub(super) estimate_fingerprint: String,
179    pub(super) value_alignment_bytes: u64,
180    pub(super) scratch: Option<ProviderWorkspaceRequirement>,
181    pub(super) binding: Option<ProviderWorkspaceRequirement>,
182    pub(super) persistent: Option<ProviderWorkspaceRequirement>,
183}
184
185#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
186#[serde(deny_unknown_fields)]
187pub struct UnvalidatedPlanNode {
188    pub(super) id: NodeId,
189    pub(super) dependencies: Vec<NodeId>,
190    pub(super) operation_id: OperationId,
191    pub(super) operation_version: ContractVersion,
192    pub(super) operation_fingerprint: String,
193    pub(super) provider_implementation_fingerprint: String,
194    pub(super) provider_execution_semantics: ProviderExecutionSemantics,
195    pub(super) required_capabilities: BTreeSet<CapabilityId>,
196    pub(super) attributes: BTreeMap<AttributeId, SemanticValue>,
197    pub(super) work: NodeWorkContract,
198    pub(super) selection: ProviderSelection,
199    pub(super) provider_resources: UnvalidatedProviderResourcePlan,
200    pub(super) values: Vec<ResolvedValueBinding>,
201    pub(super) exact_aliases: Vec<PlanExactAlias>,
202    pub(super) state_effects: Vec<PlanStateEffect>,
203    pub(super) scratch_resource: Option<ResourceId>,
204    pub(super) binding_resource: Option<ResourceId>,
205    pub(super) persistent_resource: Option<ResourceId>,
206    pub(super) resources: Vec<ResourceId>,
207}
208
209#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
210#[serde(deny_unknown_fields)]
211pub(super) struct UnvalidatedExecutionPlanPayload {
212    pub(super) schema: PlanSchemaVersion,
213    pub(super) plan_id: PlanId,
214    pub(super) family_id: ModelFamilyId,
215    pub(super) device_id: super::DeviceId,
216    pub(super) device_runtime_implementation_fingerprint: String,
217    pub(super) prepared_family_fingerprint: String,
218    pub(super) program_fingerprint: String,
219    pub(super) capability_catalog_fingerprint: String,
220    pub(super) policy_version: ContractVersion,
221    pub(super) policy_fingerprint: String,
222    pub(super) maximum_scheduled_tokens: u64,
223    pub(super) execution_weights: ExecutionWeightPlan,
224    pub(super) weight_format: WeightFormatId,
225    pub(super) quantization_formats: BTreeSet<QuantizationFormatId>,
226    pub(super) retained_completion_values: Vec<RetainedCompletionValue>,
227    pub(super) terminal_output_resources: Vec<ResourceId>,
228    pub(super) nodes: Vec<UnvalidatedPlanNode>,
229    pub(super) memory: MemoryPlan,
230}
231
232#[derive(Debug, Clone, PartialEq, Eq)]
233pub struct UnvalidatedExecutionPlan {
234    pub(super) payload: UnvalidatedExecutionPlanPayload,
235    pub(super) plan_hash: PlanHash,
236}
237
238#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
239pub(crate) struct UnvalidatedExecutionPlanWire {
240    pub(super) payload: UnvalidatedExecutionPlanPayload,
241    pub(super) plan_hash: PlanHash,
242}
243
244#[derive(Deserialize, Serialize)]
245#[serde(deny_unknown_fields)]
246pub(super) struct UnvalidatedExecutionPlanWireFields {
247    pub(super) payload: UnvalidatedExecutionPlanPayload,
248    pub(super) plan_hash: PlanHash,
249}
250
251impl<'de> Deserialize<'de> for UnvalidatedExecutionPlanWire {
252    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
253    where
254        D: Deserializer<'de>,
255    {
256        let raw = serde_json::Value::deserialize(deserializer)?;
257        let fields = UnvalidatedExecutionPlanWireFields::deserialize(&raw)
258            .map_err(serde::de::Error::custom)?;
259        let canonical = serde_json::to_value(&fields).map_err(serde::de::Error::custom)?;
260        if canonical != raw {
261            return Err(serde::de::Error::custom(
262                "execution plan wire contains unknown or non-canonical nested fields",
263            ));
264        }
265        Ok(Self {
266            payload: fields.payload,
267            plan_hash: fields.plan_hash,
268        })
269    }
270}
271
272impl From<UnvalidatedExecutionPlanWire> for UnvalidatedExecutionPlan {
273    fn from(wire: UnvalidatedExecutionPlanWire) -> Self {
274        Self {
275            payload: wire.payload,
276            plan_hash: wire.plan_hash,
277        }
278    }
279}