1use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10use std::collections::BTreeMap;
11use std::path::PathBuf;
12
13#[derive(Clone, Copy, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
17pub enum ProtocolVersion {
18 #[serde(rename = "4")]
20 V4,
21}
22
23#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
26#[serde(tag = "operation", rename_all = "snake_case", deny_unknown_fields)]
27pub enum AdapterRequest {
28 PlanServe {
31 protocol_version: ProtocolVersion,
32 input: PlanServeInput,
33 },
34 RenderServe {
37 protocol_version: ProtocolVersion,
38 input: RenderServeInput,
39 },
40}
41
42impl AdapterRequest {
43 #[must_use]
45 pub const fn protocol_version(&self) -> ProtocolVersion {
46 match self {
47 Self::PlanServe {
48 protocol_version, ..
49 }
50 | Self::RenderServe {
51 protocol_version, ..
52 } => *protocol_version,
53 }
54 }
55}
56
57#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
59#[serde(deny_unknown_fields)]
60pub struct PlanServeInput {
61 pub model: ServeModelInput,
62 pub topology: ServeTopology,
63 pub routing_backend: String,
64 #[serde(default, skip_serializing_if = "Option::is_none")]
65 pub kv_transfer: Option<KvTransferMechanism>,
66 pub parallelism: Parallelism,
67 pub settings: BTreeMap<String, SettingValue>,
68 pub roles: Vec<ServeRoleInput>,
69 #[serde(default)]
70 pub profiling: bool,
71}
72
73#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
76#[serde(deny_unknown_fields)]
77pub struct RenderServeInput {
78 pub model: ServeModelInput,
79 pub topology: ServeTopology,
80 pub routing_backend: String,
81 #[serde(default, skip_serializing_if = "Option::is_none")]
82 pub kv_transfer: Option<KvTransferMechanism>,
83 pub parallelism: Parallelism,
84 pub settings: BTreeMap<String, SettingValue>,
85 pub roles: Vec<ServeRoleResult>,
86 pub links: Vec<ServeRoleLink>,
87 pub allocations: Vec<ServeProcessAllocation>,
88 #[serde(default)]
89 pub render_inputs: Vec<SuppliedRenderInput>,
90 #[serde(default)]
91 pub profiling: bool,
92}
93
94#[derive(Clone, Copy, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
96#[serde(rename_all = "snake_case")]
97pub enum ServeTopology {
98 Single,
100 PrefillDecode,
102}
103
104#[derive(Clone, Copy, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
106#[serde(rename_all = "snake_case")]
107pub enum ServeRoleKind {
108 Serve,
110 Prefill,
112 Decode,
114 Router,
116}
117
118#[derive(Clone, Copy, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
120#[serde(rename_all = "snake_case")]
121pub enum KvTransferMechanism {
122 Mooncake,
124 Nixl,
126}
127
128#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
131#[serde(deny_unknown_fields)]
132pub struct ServeRoleInput {
133 pub id: String,
134 pub kind: ServeRoleKind,
135 pub replica_count: u32,
136 pub parallelism: Parallelism,
137 pub settings: BTreeMap<String, SettingValue>,
138}
139
140#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
143#[serde(deny_unknown_fields)]
144pub struct ServeRoleResult {
145 pub id: String,
146 pub kind: ServeRoleKind,
147 pub replica_count: u32,
148 pub effective_settings: BTreeMap<String, SettingValue>,
149 pub effective_parallelism: Parallelism,
150}
151
152#[derive(Clone, Debug, Default, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
157#[serde(default, deny_unknown_fields)]
158pub struct Parallelism {
159 #[serde(skip_serializing_if = "Option::is_none")]
161 pub outer: Option<ParallelismOuter>,
162 #[serde(skip_serializing_if = "Option::is_none")]
164 pub attention: Option<ParallelismAttention>,
165 #[serde(skip_serializing_if = "Option::is_none")]
167 pub experts: Option<ParallelismExperts>,
168}
169
170impl Parallelism {
171 pub fn merge_from(&mut self, other: &Self) {
174 if let Some(other) = &other.outer {
175 self.outer.get_or_insert_default().merge_from(other);
176 }
177 if let Some(other) = &other.attention {
178 self.attention.get_or_insert_default().merge_from(other);
179 }
180 if let Some(other) = &other.experts {
181 self.experts.get_or_insert_default().merge_from(other);
182 }
183 }
184}
185
186#[derive(Clone, Debug, Default, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
188#[serde(default, deny_unknown_fields)]
189pub struct ParallelismOuter {
190 #[schemars(range(min = 1))]
191 pub tensor_parallel_size: Option<u32>,
192 #[schemars(range(min = 1))]
193 pub pipeline_parallel_size: Option<u32>,
194}
195
196impl ParallelismOuter {
197 fn merge_from(&mut self, other: &Self) {
198 if other.tensor_parallel_size.is_some() {
199 self.tensor_parallel_size = other.tensor_parallel_size;
200 }
201 if other.pipeline_parallel_size.is_some() {
202 self.pipeline_parallel_size = other.pipeline_parallel_size;
203 }
204 }
205}
206
207#[derive(Clone, Debug, Default, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
209#[serde(default, deny_unknown_fields)]
210pub struct ParallelismAttention {
211 #[schemars(range(min = 1))]
212 pub tensor_parallel_size: Option<u32>,
213 #[schemars(range(min = 1))]
214 pub data_parallel_size: Option<u32>,
215 #[schemars(range(min = 1))]
216 pub context_parallel_size: Option<u32>,
217}
218
219impl ParallelismAttention {
220 fn merge_from(&mut self, other: &Self) {
221 if other.tensor_parallel_size.is_some() {
222 self.tensor_parallel_size = other.tensor_parallel_size;
223 }
224 if other.data_parallel_size.is_some() {
225 self.data_parallel_size = other.data_parallel_size;
226 }
227 if other.context_parallel_size.is_some() {
228 self.context_parallel_size = other.context_parallel_size;
229 }
230 }
231}
232
233#[derive(Clone, Debug, Default, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
235#[serde(default, deny_unknown_fields)]
236pub struct ParallelismExperts {
237 #[schemars(range(min = 1))]
238 pub tensor_parallel_size: Option<u32>,
239 #[schemars(range(min = 1))]
240 pub data_parallel_size: Option<u32>,
241 #[schemars(range(min = 1))]
242 pub expert_parallel_size: Option<u32>,
243 #[schemars(range(min = 1))]
244 pub dense_tensor_parallel_size: Option<u32>,
245}
246
247impl ParallelismExperts {
248 fn merge_from(&mut self, other: &Self) {
249 if other.tensor_parallel_size.is_some() {
250 self.tensor_parallel_size = other.tensor_parallel_size;
251 }
252 if other.data_parallel_size.is_some() {
253 self.data_parallel_size = other.data_parallel_size;
254 }
255 if other.expert_parallel_size.is_some() {
256 self.expert_parallel_size = other.expert_parallel_size;
257 }
258 if other.dense_tensor_parallel_size.is_some() {
259 self.dense_tensor_parallel_size = other.dense_tensor_parallel_size;
260 }
261 }
262}
263
264#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
266#[serde(deny_unknown_fields)]
267pub struct ServeModelInput {
268 pub locator: String,
269 pub served_name: String,
270}
271
272#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
274#[serde(deny_unknown_fields)]
275pub struct EndpointAssignment {
276 pub host: String,
277 pub port: u16,
278}
279
280#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
282#[serde(deny_unknown_fields)]
283pub struct ClientEndpointInput {
284 pub protocol: EndpointProtocol,
285 pub host: String,
286 pub port: u16,
287 pub api_path: String,
288}
289
290#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
292#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
293pub enum EvalDefinitionInput {
294 #[serde(rename = "openai_smoke")]
296 OpenAiSmoke {
297 prompt: String,
298 max_tokens: u32,
299 timeout_seconds: u64,
300 },
301 LmEval {
303 task: String,
304 dataset: Option<String>,
305 split: Option<String>,
306 limit: Option<u32>,
307 few_shot: Option<u32>,
308 seed: Option<u64>,
309 max_tokens: Option<u32>,
310 concurrency: Option<u32>,
311 metric: String,
312 threshold: f64,
313 timeout_seconds: u64,
314 },
315}
316
317#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
319#[serde(deny_unknown_fields)]
320pub struct BenchDefinitionInput {
321 pub input_tokens: u32,
322 pub output_tokens: u32,
323 pub seed: u64,
324 pub temperature: f64,
325 pub timeout_seconds: u64,
326 #[serde(default)]
327 pub reset_prefix_cache: bool,
328}
329
330#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
333#[serde(untagged)]
334pub enum SettingValue {
335 Bool(bool),
337 Integer(i64),
339 Float(f64),
341 String(String),
343 Array(Vec<SettingValue>),
345 Object(BTreeMap<String, SettingValue>),
347}
348
349#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
351#[serde(tag = "status", rename_all = "snake_case", deny_unknown_fields)]
352pub enum AdapterResponse {
353 Ok {
355 protocol_version: ProtocolVersion,
356 result: Box<AdapterResult>,
357 },
358 Error {
360 protocol_version: ProtocolVersion,
361 error: AdapterError,
362 },
363}
364
365impl AdapterResponse {
366 #[must_use]
368 pub const fn protocol_version(&self) -> ProtocolVersion {
369 match self {
370 Self::Ok {
371 protocol_version, ..
372 }
373 | Self::Error {
374 protocol_version, ..
375 } => *protocol_version,
376 }
377 }
378}
379
380#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
383#[serde(tag = "operation", rename_all = "snake_case", deny_unknown_fields)]
384pub enum AdapterResult {
385 PlanServe { output: Box<PlanServeResult> },
387 RenderServe { output: Box<RenderServeResult> },
389}
390
391#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
395#[serde(deny_unknown_fields)]
396pub struct PlanServeResult {
397 pub integration: IntegrationIdentity,
398 pub effective_settings: BTreeMap<String, SettingValue>,
399 pub effective_parallelism: Parallelism,
400 pub roles: Vec<ServeRoleResult>,
401 pub replicas: Vec<ServeReplicaRequirement>,
402 pub links: Vec<ServeRoleLink>,
403 pub public_endpoint: PublicEndpointRequirement,
404 pub endpoint: EndpointRequirement,
405 #[serde(default)]
406 pub render_inputs: Vec<RenderInputDeclaration>,
407}
408
409#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
412#[serde(deny_unknown_fields)]
413pub struct RenderInputDeclaration {
414 pub source_path: String,
415}
416
417#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
420#[serde(deny_unknown_fields)]
421pub struct SuppliedRenderInput {
422 pub source_path: String,
423 pub text: String,
424 pub sha256: String,
425}
426
427#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
430#[serde(deny_unknown_fields)]
431pub struct ServeReplicaRequirement {
432 pub id: String,
433 pub role_id: String,
434 pub replica_index: u32,
435 pub accelerator_count: u32,
436 pub ports: Vec<String>,
437 pub primary_ports: Vec<String>,
438 pub primary_readiness: ReadinessProbe,
439 pub worker_readiness: ReadinessProbe,
440 #[serde(default, skip_serializing_if = "Option::is_none")]
441 pub capture_target: Option<CaptureTargetRequirement>,
442}
443
444#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
448#[serde(deny_unknown_fields)]
449pub struct ServeProcessAllocation {
450 pub process_id: String,
451 pub role_id: String,
452 pub replica_id: String,
453 pub replica_index: u32,
454 pub rank: u32,
455 pub machine_id: String,
456 pub model_locator: String,
457 pub runtime_cache_root: String,
458 pub devices: Vec<u32>,
459 pub endpoint: EndpointAssignment,
460 pub ports: BTreeMap<String, EndpointAssignment>,
461}
462
463#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
466#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
467pub enum ServeRoleLink {
468 RequestRouting {
470 source: String,
471 targets: Vec<String>,
472 },
473 KvTransfer {
475 source: String,
476 target: String,
477 mechanism: KvTransferMechanism,
478 },
479 Bootstrap {
481 source: String,
482 target: String,
483 port: String,
484 },
485 SideChannel {
487 source: String,
488 target: String,
489 port: String,
490 },
491}
492
493#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
495#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
496pub enum PublicEndpointRequirement {
497 Replica { replica_id: String },
499 BuiltinProxy {
502 process_id: String,
503 role_id: String,
504 prefill_role: String,
505 decode_role: String,
506 readiness: ReadinessProbe,
507 },
508}
509
510#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
513#[serde(deny_unknown_fields)]
514pub struct CaptureTargetRequirement {
515 pub control: CaptureControlRequirement,
516}
517
518#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
520#[serde(deny_unknown_fields)]
521pub struct CaptureControlRequirement {
522 pub start_path: String,
523 pub stop_path: String,
524}
525
526#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
529#[serde(deny_unknown_fields)]
530pub struct RenderServeResult {
531 pub integration: IntegrationIdentity,
532 pub processes: Vec<RenderedServeProcess>,
533}
534
535#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
537#[serde(deny_unknown_fields)]
538pub struct RenderedServeProcess {
539 pub id: String,
540 pub launch_files: Vec<LaunchFileDeclaration>,
541 pub process: ProcessSpec,
542}
543
544#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
546#[serde(deny_unknown_fields)]
547pub struct LaunchFileDeclaration {
548 pub relative_path: String,
549 pub text: String,
550 pub sha256: String,
551}
552
553#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
555#[serde(deny_unknown_fields)]
556pub struct HttpActionSpec {
557 pub method: HttpMethod,
558 pub path: String,
559}
560
561#[derive(Clone, Copy, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
563#[serde(rename_all = "snake_case")]
564pub enum HttpMethod {
565 Post,
567}
568
569#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
572#[serde(deny_unknown_fields)]
573pub struct IntegrationIdentity {
574 pub adapter_id: String,
575 pub adapter_version: String,
576 pub framework: String,
577}
578
579#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
581#[serde(deny_unknown_fields)]
582pub struct ProcessSpec {
583 pub argv: Vec<String>,
584 pub env: BTreeMap<String, String>,
585}
586
587#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
589#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
590pub enum ReadinessProbe {
591 Http { path: String },
593 HttpTargetRegistry(Box<HttpTargetRegistryReadiness>),
596 ProcessAlive,
598}
599
600#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
602#[serde(deny_unknown_fields)]
603pub struct HttpTargetRegistryReadiness {
604 pub target_scheme: TargetEndpointScheme,
605 pub readiness_path: String,
606 pub registry_path: String,
607 pub targets_field: String,
608 pub target_url_field: String,
609 pub target_role_field: String,
610 pub target_healthy_field: String,
611 pub target_bootstrap_port_field: String,
612 pub prefill_role_value: String,
613 pub decode_role_value: String,
614 pub prefill_bootstrap_port: String,
615}
616
617#[derive(Clone, Copy, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
619#[serde(rename_all = "snake_case")]
620pub enum TargetEndpointScheme {
621 Http,
623 Grpc,
625}
626
627#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
630#[serde(deny_unknown_fields)]
631pub struct EndpointRequirement {
632 pub protocol: EndpointProtocol,
633 pub api_path: String,
634 #[serde(default, skip_serializing_if = "Option::is_none")]
635 pub prefix_cache_reset: Option<HttpActionSpec>,
636}
637
638#[derive(Clone, Copy, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
640#[serde(rename_all = "snake_case")]
641pub enum EndpointProtocol {
642 Http,
644}
645
646#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
648#[serde(deny_unknown_fields)]
649pub struct AdapterError {
650 pub code: AdapterErrorCode,
651 pub message: String,
652}
653
654#[derive(Clone, Copy, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
656#[serde(rename_all = "snake_case")]
657pub enum AdapterErrorCode {
658 InvalidRequest,
660 UnsupportedProtocolVersion,
662 InvalidSettings,
664 Internal,
666 UnsupportedOperation,
668}
669
670#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
673#[serde(deny_unknown_fields)]
674pub struct EvalClientRequest {
675 pub protocol_version: ProtocolVersion,
676 pub endpoint: ClientEndpointInput,
677 pub model: ServeModelInput,
678 pub definition: EvalDefinitionInput,
679 pub artifact_dir: PathBuf,
680}
681
682#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
686#[serde(deny_unknown_fields)]
687pub struct BenchClientRequest {
688 pub protocol_version: ProtocolVersion,
689 pub endpoint: ClientEndpointInput,
690 pub model: ServeModelInput,
691 pub definition: BenchDefinitionInput,
692 pub case: BenchCaseInput,
693 pub artifact_dir: PathBuf,
694}
695
696#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
698#[serde(deny_unknown_fields)]
699pub struct BenchCaseInput {
700 pub load_shape: BenchLoadInput,
701 pub request_count: u32,
702}
703
704#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
706#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
707pub enum BenchLoadInput {
708 ConcurrencyLimited { concurrency: u32 },
710 RequestRateLimited {
712 request_rate: f64,
713 burstiness: Option<f64>,
714 },
715 UnboundedRequestRate,
717}
718
719#[derive(Clone, Copy, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
721#[serde(rename_all = "snake_case")]
722pub enum ClientStatus {
723 Succeeded,
725 Failed,
727}
728
729#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
731#[serde(deny_unknown_fields)]
732pub struct EvalClientResult {
733 pub schema_version: u32,
736 pub status: ClientStatus,
737 pub metrics: BTreeMap<String, f64>,
738 pub native_command: Vec<String>,
739 pub raw_artifacts: Vec<RawArtifact>,
740 pub error: Option<String>,
741}
742
743#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
745#[serde(deny_unknown_fields)]
746pub struct BenchClientResult {
747 pub schema_version: u32,
750 pub status: ClientStatus,
751 pub completed_requests: u64,
752 pub failed_requests: u64,
753 pub normalization_schema: String,
754 pub metrics: BTreeMap<String, f64>,
755 pub native_command: Vec<String>,
756 pub native_exit_code: Option<i32>,
757 pub raw_artifacts: Vec<RawArtifact>,
758 pub error: Option<String>,
759}
760
761#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
763#[serde(deny_unknown_fields)]
764pub struct RawArtifact {
765 pub name: String,
766 pub kind: String,
767 pub path: PathBuf,
768}
769
770#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
774#[serde(deny_unknown_fields)]
775pub struct AdapterProtocol {
776 pub request: AdapterRequest,
777 pub response: AdapterResponse,
778 #[serde(default, skip_serializing_if = "Option::is_none")]
779 pub eval_client_request: Option<EvalClientRequest>,
780 #[serde(default, skip_serializing_if = "Option::is_none")]
781 pub eval_client_result: Option<EvalClientResult>,
782 #[serde(default, skip_serializing_if = "Option::is_none")]
783 pub bench_client_request: Option<BenchClientRequest>,
784 #[serde(default, skip_serializing_if = "Option::is_none")]
785 pub bench_client_result: Option<BenchClientResult>,
786}