llm_sdk/
types.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::collections::HashMap;
4
5/// Loosely describe audio format. Some values (e.g., 'wav') denote containers;
6/// others (e.g., 'linear16') specify encoding only; cannot describe containers
7/// that can contain different audio encodings.
8#[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/// A part of the message.
23#[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/// Delta parts used in partial updates.
37#[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/// A message in an LLM conversation history.
49#[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/// Defines the modality of content (e.g., text or audio) in LLM responses.
59#[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/// Determines how the model should choose which tool to use.
69/// - "auto" The model will automatically choose the tool to use or not use any
70///   tools.
71/// - "none" The model will not use any tools.
72/// - "required" The model will be forced to use a tool.
73/// - { type: "tool", toolName: "toolName" } The model will use the specified
74///   tool.
75#[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    /// The model will automatically choose the tool to use or not use any
80    /// tools.
81    Auto,
82    /// The model will not use any tools.
83    None,
84    /// The model will be forced to use a tool.
85    Required,
86    /// The model will use the specified tool.
87    Tool(ToolChoiceTool),
88}
89
90/// The format that the model must output.
91#[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    /// Specifies that the model response should be in plain text format.
96    Text,
97    Json(ResponseFormatJson),
98}
99
100/// A metadata property that describes the capability of the model.
101#[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/// A part of the message that contains text.
118#[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/// A part of the message that contains an image.
127#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
128#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
129pub struct ImagePart {
130    /// The MIME type of the image. E.g. "image/jpeg", "image/png".
131    pub mime_type: String,
132    /// The base64-encoded image data.
133    pub data: String,
134    /// The width of the image in pixels.
135    #[serde(skip_serializing_if = "Option::is_none")]
136    pub width: Option<u32>,
137    /// The height of the image in pixels.
138    #[serde(skip_serializing_if = "Option::is_none")]
139    pub height: Option<u32>,
140    /// The ID of the image part, if applicable
141    #[serde(skip_serializing_if = "Option::is_none")]
142    pub id: Option<String>,
143}
144
145/// A part of the message that contains an audio.
146#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
147#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
148pub struct AudioPart {
149    /// The base64-encoded audio data.
150    pub data: String,
151    /// The format of the audio.
152    pub format: AudioFormat,
153    /// The sample rate of the audio. E.g. 44100, 48000.
154    #[serde(skip_serializing_if = "Option::is_none")]
155    pub sample_rate: Option<u32>,
156    /// The number of channels of the audio. E.g. 1, 2.
157    #[serde(skip_serializing_if = "Option::is_none")]
158    pub channels: Option<u32>,
159    /// The transcript of the audio.
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub transcript: Option<String>,
162    /// The ID of the audio part, if applicable
163    #[serde(skip_serializing_if = "Option::is_none")]
164    pub id: Option<String>,
165}
166
167/// A part of the message that contains a source with structured content.
168/// It will be used for citation for supported models.
169#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
170#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
171pub struct SourcePart {
172    /// The URL or identifier of the document.
173    pub source: String,
174    /// The title of the document.
175    pub title: String,
176    /// The content of the document.
177    pub content: Vec<Part>,
178}
179
180/// A part of the message that represents a call to a tool the model wants to
181/// use.
182#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
183#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
184pub struct ToolCallPart {
185    /// The ID of the tool call, used to match the tool result with the tool
186    /// call.
187    pub tool_call_id: String,
188    /// The name of the tool to call.
189    pub tool_name: String,
190    /// The arguments to pass to the tool.
191    pub args: Value,
192    /// The ID of the tool call, if applicable
193    /// This is different from `tool_call_id`, which is the ID used to match the
194    /// tool result with the tool call.
195    #[serde(skip_serializing_if = "Option::is_none")]
196    pub id: Option<String>,
197}
198
199/// A part of the message that represents the result of a tool call.
200#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
201#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
202pub struct ToolResultPart {
203    /// The ID of the tool call from previous assistant message.
204    pub tool_call_id: String,
205    /// The name of the tool that was called.
206    pub tool_name: String,
207    /// The content of the tool result.
208    pub content: Vec<Part>,
209    /// Marks the tool result as an error.
210    #[serde(skip_serializing_if = "Option::is_none")]
211    pub is_error: Option<bool>,
212}
213
214// A part of the message that represents the model reasoning.
215#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
216#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
217pub struct ReasoningPart {
218    /// The reasoning text content.
219    pub text: String,
220    /// The reasoning internal signature
221    #[serde(skip_serializing_if = "Option::is_none")]
222    pub signature: Option<String>,
223    /// The ID of the reasoning part, if applicable
224    #[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    /**
232     * The URL or identifier of the document being cited.
233     */
234    pub source: String,
235    /**
236     * The title of the document being cited.
237     */
238    #[serde(skip_serializing_if = "Option::is_none")]
239    pub title: Option<String>,
240    /**
241     * The text snippet from the document being cited.
242     */
243    #[serde(skip_serializing_if = "Option::is_none")]
244    pub cited_text: Option<String>,
245    /**
246     * The start index of the document content part being cited.
247     */
248    pub start_index: usize,
249    /**
250     * The end index of the document content part being cited.
251     */
252    pub end_index: usize,
253}
254
255/// Represents a message sent by the user.
256#[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/// Represents a message generated by the model.
263#[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/// A delta update for a text part, used in streaming or incremental updates of
270/// a message.
271#[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/// A delta update for a citation part, used in streaming of citation messages.
280#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
281#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
282pub struct CitationDelta {
283    /// The type of the citation delta.
284    #[serde(rename = "type")]
285    pub r#type: String,
286    /// The URL or identifier of the document being cited.
287    #[serde(skip_serializing_if = "Option::is_none")]
288    pub source: Option<String>,
289    /// The title of the document being cited.
290    #[serde(skip_serializing_if = "Option::is_none")]
291    pub title: Option<String>,
292    /// The text snippet from the document being cited.
293    #[serde(skip_serializing_if = "Option::is_none")]
294    pub cited_text: Option<String>,
295    /// The start index of the document content part being cited.
296    #[serde(skip_serializing_if = "Option::is_none")]
297    pub start_index: Option<usize>,
298    /// The end index of the document content part being cited.
299    #[serde(skip_serializing_if = "Option::is_none")]
300    pub end_index: Option<usize>,
301}
302
303/// A delta update for a tool call part, used in streaming of a tool invocation.
304#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
305#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
306pub struct ToolCallPartDelta {
307    /// The ID of the tool call, used to match the tool result with the tool
308    /// call.
309    #[serde(skip_serializing_if = "Option::is_none")]
310    pub tool_call_id: Option<String>,
311    /// The name of the tool to call.
312    #[serde(skip_serializing_if = "Option::is_none")]
313    pub tool_name: Option<String>,
314    /// The partial JSON string of the arguments to pass to the tool.
315    #[serde(skip_serializing_if = "Option::is_none")]
316    pub args: Option<String>,
317    /// The ID of the tool call, if applicable
318    /// This is different from `tool_call_id`, which is the ID used to match the
319    /// tool result with the tool call.
320    #[serde(skip_serializing_if = "Option::is_none")]
321    pub id: Option<String>,
322}
323
324/// A delta update for an image part, used in streaming of an image message.
325#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
326#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
327pub struct ImagePartDelta {
328    /// The MIME type of the image. E.g. "image/jpeg", "image/png".
329    #[serde(skip_serializing_if = "Option::is_none")]
330    pub mime_type: Option<String>,
331    /// The base64-encoded image data.
332    #[serde(skip_serializing_if = "Option::is_none")]
333    pub data: Option<String>,
334    /// The width of the image in pixels.
335    #[serde(skip_serializing_if = "Option::is_none")]
336    pub width: Option<u32>,
337    /// The height of the image in pixels.
338    #[serde(skip_serializing_if = "Option::is_none")]
339    pub height: Option<u32>,
340    /// The ID of the image part, if applicable
341    #[serde(skip_serializing_if = "Option::is_none")]
342    pub id: Option<String>,
343}
344
345/// A delta update for an audio part, used in streaming of an audio message.
346#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
347#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
348pub struct AudioPartDelta {
349    /// The base64-encoded audio data.
350    #[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    /// The sample rate of the audio. E.g. 44100, 48000.
355    #[serde(skip_serializing_if = "Option::is_none")]
356    pub sample_rate: Option<u32>,
357    /// The number of channels of the audio. E.g. 1, 2.
358    #[serde(skip_serializing_if = "Option::is_none")]
359    pub channels: Option<u32>,
360    /// The transcript of the audio.
361    #[serde(skip_serializing_if = "Option::is_none")]
362    pub transcript: Option<String>,
363    /// The ID of the audio part, if applicable
364    #[serde(skip_serializing_if = "Option::is_none")]
365    pub id: Option<String>,
366}
367
368// A delta update for a reasoning part, used in streaming of reasoning messages.
369#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
370#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
371pub struct ReasoningPartDelta {
372    /// The reasoning text content.
373    #[serde(skip_serializing_if = "Option::is_none")]
374    pub text: Option<String>,
375    /// The reasoning internal signature
376    #[serde(skip_serializing_if = "Option::is_none")]
377    pub signature: Option<String>,
378    /// The ID of the reasoning part, if applicable
379    #[serde(skip_serializing_if = "Option::is_none")]
380    pub id: Option<String>,
381}
382
383/// Represents a delta update in a message's content, enabling partial streaming
384/// updates in LLM responses.
385#[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
392/// Represents a JSON schema.
393pub type JSONSchema = Value;
394
395/// Represents a tool that can be used by the model.
396#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
397#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
398pub struct Tool {
399    /// The name of the tool.
400    pub name: String,
401    /// A description of the tool.
402    pub description: String,
403    /// The JSON schema of the parameters that the tool accepts. The type must
404    /// be "object".
405    pub parameters: JSONSchema,
406}
407
408/// Represents tool result in the message history.
409/// The only parts of `ToolMessage` should be Part(ToolResultPart).
410#[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/// Represents the token usage of the model.
417#[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/// Represents the token usage of the model.
435#[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/// Represents the response generated by the model.
447#[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    /// The cost of the response.
454    #[serde(skip_serializing_if = "Option::is_none")]
455    pub cost: Option<f64>,
456}
457
458/// Represents a partial response from the language model, useful for streaming
459/// output via async generator.
460#[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/// The model will use the specified tool.
469#[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/// Specifies that the model response should be in JSON format adhering to a
476/// specified schema.
477#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
478#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
479pub struct ResponseFormatJson {
480    /// The name of the schema.
481    pub name: String,
482    /// The description of the schema.
483    #[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/// Options for audio generation.
490#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
491#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
492pub struct AudioOptions {
493    /// The format of the audio.
494    #[serde(skip_serializing_if = "Option::is_none")]
495    pub format: Option<AudioFormat>,
496    /// The provider-specifc voice ID to use for audio generation.
497    #[serde(skip_serializing_if = "Option::is_none")]
498    pub voice: Option<String>,
499    /// The language code for the audio generation.
500    #[serde(skip_serializing_if = "Option::is_none")]
501    pub language: Option<String>,
502}
503
504/// Options for reasoning generation.
505#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
506#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
507pub struct ReasoningOptions {
508    /// Whether to enable reasoning output.
509    pub enabled: bool,
510    /// Specify the budget tokens for reasoning generation.
511    #[serde(skip_serializing_if = "Option::is_none")]
512    pub budget_tokens: Option<u32>,
513}
514
515/// Defines the input parameters for the language model completion.
516#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
517#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
518pub struct LanguageModelInput {
519    /// A system prompt is a way of providing context and instructions to the
520    /// model
521    #[serde(skip_serializing_if = "Option::is_none")]
522    pub system_prompt: Option<String>,
523    /// A list of messages comprising the conversation so far.
524    pub messages: Vec<Message>,
525    /// Definitions of tools that the model may use.
526    #[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    /// The maximum number of tokens that can be generated in the chat
533    /// completion.
534    #[serde(skip_serializing_if = "Option::is_none")]
535    pub max_tokens: Option<u32>,
536    /// Amount of randomness injected into the response. Ranges from 0.0 to 1.0
537    #[serde(skip_serializing_if = "Option::is_none")]
538    pub temperature: Option<f64>,
539    /// An alternative to sampling with temperature, called nucleus sampling,
540    /// where the model considers the results of the tokens with `top_p`
541    /// probability mass. Ranges from 0.0 to 1.0
542    #[serde(skip_serializing_if = "Option::is_none")]
543    pub top_p: Option<f64>,
544    /// Only sample from the top K options for each subsequent token. Used to
545    /// remove 'long tail' low probability responses. Must be a non-negative
546    /// integer.
547    #[serde(skip_serializing_if = "Option::is_none")]
548    pub top_k: Option<i32>,
549    /// Positive values penalize new tokens based on whether they appear in the
550    /// text so far, increasing the model's likelihood to talk about new topics.
551    #[serde(skip_serializing_if = "Option::is_none")]
552    pub presence_penalty: Option<f64>,
553    /// Positive values penalize new tokens based on their existing frequency in
554    /// the text so far, decreasing the model's likelihood to repeat the same
555    /// line verbatim.
556    #[serde(skip_serializing_if = "Option::is_none")]
557    pub frequency_penalty: Option<f64>,
558    /// The seed (integer), if set and supported by the model, to enable
559    /// deterministic results.
560    #[serde(skip_serializing_if = "Option::is_none")]
561    pub seed: Option<i64>,
562    /// The modalities that the model should support.
563    #[serde(skip_serializing_if = "Option::is_none")]
564    pub modalities: Option<Vec<Modality>>,
565    /// A set of key/value pairs that store additional information about the
566    /// request. This is forwarded to the model provider if supported.
567    #[serde(skip_serializing_if = "Option::is_none")]
568    pub metadata: Option<HashMap<String, String>>,
569    /// Options for audio generation.
570    #[serde(skip_serializing_if = "Option::is_none")]
571    pub audio: Option<AudioOptions>,
572    /// Options for reasoning generation.
573    pub reasoning: Option<ReasoningOptions>,
574    /// Extra options that the model may support.
575    #[serde(skip_serializing_if = "Option::is_none")]
576    pub extra: Option<LanguageModelInputExtra>,
577}
578
579pub type LanguageModelInputExtra = Value;
580
581/// A metadata property that describes the pricing of the model.
582#[derive(Debug, Clone, Serialize, Deserialize)]
583#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
584pub struct LanguageModelPricing {
585    /// The cost in USD per single text token for input.
586    #[serde(skip_serializing_if = "Option::is_none")]
587    pub input_cost_per_text_token: Option<f64>,
588    /// The cost in USD per single cached text token for input.
589    #[serde(skip_serializing_if = "Option::is_none")]
590    pub input_cost_per_cached_text_token: Option<f64>,
591    /// The cost in USD per single text token for output.
592    #[serde(skip_serializing_if = "Option::is_none")]
593    pub output_cost_per_text_token: Option<f64>,
594    /// The cost in USD per single audio token for input.
595    #[serde(skip_serializing_if = "Option::is_none")]
596    pub input_cost_per_audio_token: Option<f64>,
597    /// The cost in USD per single cached audio token for input.
598    #[serde(skip_serializing_if = "Option::is_none")]
599    pub input_cost_per_cached_audio_token: Option<f64>,
600    /// The cost in USD per single audio token for output.
601    #[serde(skip_serializing_if = "Option::is_none")]
602    pub output_cost_per_audio_token: Option<f64>,
603    /// The cost in USD per single image token for input.
604    #[serde(skip_serializing_if = "Option::is_none")]
605    pub input_cost_per_image_token: Option<f64>,
606    /// The cost in USD per single cached image token for input.
607    #[serde(skip_serializing_if = "Option::is_none")]
608    pub input_cost_per_cached_image_token: Option<f64>,
609    /// The cost in USD per single image token for output.
610    #[serde(skip_serializing_if = "Option::is_none")]
611    pub output_cost_per_image_token: Option<f64>,
612}