1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::collections::HashMap;
4
5#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
9#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
10#[serde(rename_all = "lowercase")]
11pub enum AudioFormat {
12 Wav,
13 Mp3,
14 Linear16,
15 Flac,
16 Mulaw,
17 Alaw,
18 Aac,
19 Opus,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
24#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
25#[serde(tag = "type", rename_all = "kebab-case")]
26pub enum Part {
27 Text(TextPart),
28 Image(ImagePart),
29 Audio(AudioPart),
30 Source(SourcePart),
31 ToolCall(ToolCallPart),
32 ToolResult(ToolResultPart),
33 Reasoning(ReasoningPart),
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
38#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
39#[serde(tag = "type", rename_all = "kebab-case")]
40pub enum PartDelta {
41 Text(TextPartDelta),
42 ToolCall(ToolCallPartDelta),
43 Image(ImagePartDelta),
44 Audio(AudioPartDelta),
45 Reasoning(ReasoningPartDelta),
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
50#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
51#[serde(tag = "role", rename_all = "lowercase")]
52pub enum Message {
53 User(UserMessage),
54 Assistant(AssistantMessage),
55 Tool(ToolMessage),
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
60#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
61#[serde(rename_all = "lowercase")]
62pub enum Modality {
63 Text,
64 Image,
65 Audio,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
76#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
77#[serde(tag = "type", rename_all = "lowercase")]
78pub enum ToolChoiceOption {
79 Auto,
82 None,
84 Required,
86 Tool(ToolChoiceTool),
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
92#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
93#[serde(tag = "type", rename_all = "lowercase")]
94pub enum ResponseFormatOption {
95 Text,
97 Json(ResponseFormatJson),
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
102#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
103#[serde(rename_all = "kebab-case")]
104pub enum LanguageModelCapability {
105 TextInput,
106 TextOutput,
107 ImageInput,
108 ImageOutput,
109 AudioInput,
110 AudioOutput,
111 FunctionCalling,
112 StructuredOutput,
113 Citation,
114 Reasoning,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
119#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
120pub struct TextPart {
121 pub text: String,
122 #[serde(skip_serializing_if = "Option::is_none")]
123 pub citations: Option<Vec<Citation>>,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
128#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
129pub struct ImagePart {
130 pub mime_type: String,
132 pub data: String,
134 #[serde(skip_serializing_if = "Option::is_none")]
136 pub width: Option<u32>,
137 #[serde(skip_serializing_if = "Option::is_none")]
139 pub height: Option<u32>,
140 #[serde(skip_serializing_if = "Option::is_none")]
142 pub id: Option<String>,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
147#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
148pub struct AudioPart {
149 pub data: String,
151 pub format: AudioFormat,
153 #[serde(skip_serializing_if = "Option::is_none")]
155 pub sample_rate: Option<u32>,
156 #[serde(skip_serializing_if = "Option::is_none")]
158 pub channels: Option<u32>,
159 #[serde(skip_serializing_if = "Option::is_none")]
161 pub transcript: Option<String>,
162 #[serde(skip_serializing_if = "Option::is_none")]
164 pub id: Option<String>,
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
170#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
171pub struct SourcePart {
172 pub source: String,
174 pub title: String,
176 pub content: Vec<Part>,
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
183#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
184pub struct ToolCallPart {
185 pub tool_call_id: String,
188 pub tool_name: String,
190 pub args: Value,
192 #[serde(skip_serializing_if = "Option::is_none")]
196 pub id: Option<String>,
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
201#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
202pub struct ToolResultPart {
203 pub tool_call_id: String,
205 pub tool_name: String,
207 pub content: Vec<Part>,
209 #[serde(skip_serializing_if = "Option::is_none")]
211 pub is_error: Option<bool>,
212}
213
214#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
216#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
217pub struct ReasoningPart {
218 pub text: String,
220 #[serde(skip_serializing_if = "Option::is_none")]
222 pub signature: Option<String>,
223 #[serde(skip_serializing_if = "Option::is_none")]
225 pub id: Option<String>,
226}
227
228#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
229#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
230pub struct Citation {
231 pub source: String,
235 #[serde(skip_serializing_if = "Option::is_none")]
239 pub title: Option<String>,
240 #[serde(skip_serializing_if = "Option::is_none")]
244 pub cited_text: Option<String>,
245 pub start_index: usize,
249 pub end_index: usize,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
257#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
258pub struct UserMessage {
259 pub content: Vec<Part>,
260}
261
262#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
264#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
265pub struct AssistantMessage {
266 pub content: Vec<Part>,
267}
268
269#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
272#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
273pub struct TextPartDelta {
274 pub text: String,
275 #[serde(skip_serializing_if = "Option::is_none")]
276 pub citation: Option<CitationDelta>,
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
281#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
282pub struct CitationDelta {
283 #[serde(rename = "type")]
285 pub r#type: String,
286 #[serde(skip_serializing_if = "Option::is_none")]
288 pub source: Option<String>,
289 #[serde(skip_serializing_if = "Option::is_none")]
291 pub title: Option<String>,
292 #[serde(skip_serializing_if = "Option::is_none")]
294 pub cited_text: Option<String>,
295 #[serde(skip_serializing_if = "Option::is_none")]
297 pub start_index: Option<usize>,
298 #[serde(skip_serializing_if = "Option::is_none")]
300 pub end_index: Option<usize>,
301}
302
303#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
305#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
306pub struct ToolCallPartDelta {
307 #[serde(skip_serializing_if = "Option::is_none")]
310 pub tool_call_id: Option<String>,
311 #[serde(skip_serializing_if = "Option::is_none")]
313 pub tool_name: Option<String>,
314 #[serde(skip_serializing_if = "Option::is_none")]
316 pub args: Option<String>,
317 #[serde(skip_serializing_if = "Option::is_none")]
321 pub id: Option<String>,
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
326#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
327pub struct ImagePartDelta {
328 #[serde(skip_serializing_if = "Option::is_none")]
330 pub mime_type: Option<String>,
331 #[serde(skip_serializing_if = "Option::is_none")]
333 pub data: Option<String>,
334 #[serde(skip_serializing_if = "Option::is_none")]
336 pub width: Option<u32>,
337 #[serde(skip_serializing_if = "Option::is_none")]
339 pub height: Option<u32>,
340 #[serde(skip_serializing_if = "Option::is_none")]
342 pub id: Option<String>,
343}
344
345#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
347#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
348pub struct AudioPartDelta {
349 #[serde(skip_serializing_if = "Option::is_none")]
351 pub data: Option<String>,
352 #[serde(skip_serializing_if = "Option::is_none")]
353 pub format: Option<AudioFormat>,
354 #[serde(skip_serializing_if = "Option::is_none")]
356 pub sample_rate: Option<u32>,
357 #[serde(skip_serializing_if = "Option::is_none")]
359 pub channels: Option<u32>,
360 #[serde(skip_serializing_if = "Option::is_none")]
362 pub transcript: Option<String>,
363 #[serde(skip_serializing_if = "Option::is_none")]
365 pub id: Option<String>,
366}
367
368#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
370#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
371pub struct ReasoningPartDelta {
372 #[serde(skip_serializing_if = "Option::is_none")]
374 pub text: Option<String>,
375 #[serde(skip_serializing_if = "Option::is_none")]
377 pub signature: Option<String>,
378 #[serde(skip_serializing_if = "Option::is_none")]
380 pub id: Option<String>,
381}
382
383#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
386#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
387pub struct ContentDelta {
388 pub index: usize,
389 pub part: PartDelta,
390}
391
392pub type JSONSchema = Value;
394
395#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
397#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
398pub struct Tool {
399 pub name: String,
401 pub description: String,
403 pub parameters: JSONSchema,
406}
407
408#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
411#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
412pub struct ToolMessage {
413 pub content: Vec<Part>,
414}
415
416#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
418#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
419pub struct ModelTokensDetails {
420 #[serde(skip_serializing_if = "Option::is_none")]
421 pub text_tokens: Option<u32>,
422 #[serde(skip_serializing_if = "Option::is_none")]
423 pub cached_text_tokens: Option<u32>,
424 #[serde(skip_serializing_if = "Option::is_none")]
425 pub audio_tokens: Option<u32>,
426 #[serde(skip_serializing_if = "Option::is_none")]
427 pub cached_audio_tokens: Option<u32>,
428 #[serde(skip_serializing_if = "Option::is_none")]
429 pub image_tokens: Option<u32>,
430 #[serde(skip_serializing_if = "Option::is_none")]
431 pub cached_image_tokens: Option<u32>,
432}
433
434#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
436#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
437pub struct ModelUsage {
438 pub input_tokens: u32,
439 pub output_tokens: u32,
440 #[serde(skip_serializing_if = "Option::is_none")]
441 pub input_tokens_details: Option<ModelTokensDetails>,
442 #[serde(skip_serializing_if = "Option::is_none")]
443 pub output_tokens_details: Option<ModelTokensDetails>,
444}
445
446#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
448#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
449pub struct ModelResponse {
450 pub content: Vec<Part>,
451 #[serde(skip_serializing_if = "Option::is_none")]
452 pub usage: Option<ModelUsage>,
453 #[serde(skip_serializing_if = "Option::is_none")]
455 pub cost: Option<f64>,
456}
457
458#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
461#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
462pub struct PartialModelResponse {
463 pub delta: Option<ContentDelta>,
464 pub usage: Option<ModelUsage>,
465 pub cost: Option<f64>,
466}
467
468#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
470#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
471pub struct ToolChoiceTool {
472 pub tool_name: String,
473}
474
475#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
478#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
479pub struct ResponseFormatJson {
480 pub name: String,
482 #[serde(skip_serializing_if = "Option::is_none")]
484 pub description: Option<String>,
485 #[serde(skip_serializing_if = "Option::is_none")]
486 pub schema: Option<JSONSchema>,
487}
488
489#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
491#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
492pub struct AudioOptions {
493 #[serde(skip_serializing_if = "Option::is_none")]
495 pub format: Option<AudioFormat>,
496 #[serde(skip_serializing_if = "Option::is_none")]
498 pub voice: Option<String>,
499 #[serde(skip_serializing_if = "Option::is_none")]
501 pub language: Option<String>,
502}
503
504#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
506#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
507pub struct ReasoningOptions {
508 pub enabled: bool,
510 #[serde(skip_serializing_if = "Option::is_none")]
512 pub budget_tokens: Option<u32>,
513}
514
515#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
517#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
518pub struct LanguageModelInput {
519 #[serde(skip_serializing_if = "Option::is_none")]
522 pub system_prompt: Option<String>,
523 pub messages: Vec<Message>,
525 #[serde(skip_serializing_if = "Option::is_none")]
527 pub tools: Option<Vec<Tool>>,
528 #[serde(skip_serializing_if = "Option::is_none")]
529 pub tool_choice: Option<ToolChoiceOption>,
530 #[serde(skip_serializing_if = "Option::is_none")]
531 pub response_format: Option<ResponseFormatOption>,
532 #[serde(skip_serializing_if = "Option::is_none")]
535 pub max_tokens: Option<u32>,
536 #[serde(skip_serializing_if = "Option::is_none")]
538 pub temperature: Option<f64>,
539 #[serde(skip_serializing_if = "Option::is_none")]
543 pub top_p: Option<f64>,
544 #[serde(skip_serializing_if = "Option::is_none")]
548 pub top_k: Option<i32>,
549 #[serde(skip_serializing_if = "Option::is_none")]
552 pub presence_penalty: Option<f64>,
553 #[serde(skip_serializing_if = "Option::is_none")]
557 pub frequency_penalty: Option<f64>,
558 #[serde(skip_serializing_if = "Option::is_none")]
561 pub seed: Option<i64>,
562 #[serde(skip_serializing_if = "Option::is_none")]
564 pub modalities: Option<Vec<Modality>>,
565 #[serde(skip_serializing_if = "Option::is_none")]
568 pub metadata: Option<HashMap<String, String>>,
569 #[serde(skip_serializing_if = "Option::is_none")]
571 pub audio: Option<AudioOptions>,
572 pub reasoning: Option<ReasoningOptions>,
574 #[serde(skip_serializing_if = "Option::is_none")]
576 pub extra: Option<LanguageModelInputExtra>,
577}
578
579pub type LanguageModelInputExtra = Value;
580
581#[derive(Debug, Clone, Serialize, Deserialize)]
583#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
584pub struct LanguageModelPricing {
585 #[serde(skip_serializing_if = "Option::is_none")]
587 pub input_cost_per_text_token: Option<f64>,
588 #[serde(skip_serializing_if = "Option::is_none")]
590 pub input_cost_per_cached_text_token: Option<f64>,
591 #[serde(skip_serializing_if = "Option::is_none")]
593 pub output_cost_per_text_token: Option<f64>,
594 #[serde(skip_serializing_if = "Option::is_none")]
596 pub input_cost_per_audio_token: Option<f64>,
597 #[serde(skip_serializing_if = "Option::is_none")]
599 pub input_cost_per_cached_audio_token: Option<f64>,
600 #[serde(skip_serializing_if = "Option::is_none")]
602 pub output_cost_per_audio_token: Option<f64>,
603 #[serde(skip_serializing_if = "Option::is_none")]
605 pub input_cost_per_image_token: Option<f64>,
606 #[serde(skip_serializing_if = "Option::is_none")]
608 pub input_cost_per_cached_image_token: Option<f64>,
609 #[serde(skip_serializing_if = "Option::is_none")]
611 pub output_cost_per_image_token: Option<f64>,
612}