Skip to main content

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/// The capabilities supported by the model.
101#[allow(clippy::struct_excessive_bools)]
102#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
103#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
104pub struct LanguageModelCapabilities {
105    pub text_input: bool,
106    pub text_output: bool,
107    pub image_input: bool,
108    pub image_output: bool,
109    pub audio_input: bool,
110    pub audio_output: bool,
111    pub function_calling: bool,
112    pub structured_output: bool,
113    pub citation: bool,
114    pub reasoning: bool,
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 provider-specific signature used to preserve reasoning/tool
193    /// continuity.
194    #[serde(skip_serializing_if = "Option::is_none")]
195    pub signature: Option<String>,
196    /// The ID of the tool call, if applicable
197    /// This is different from `tool_call_id`, which is the ID used to match the
198    /// tool result with the tool call.
199    #[serde(skip_serializing_if = "Option::is_none")]
200    pub id: Option<String>,
201}
202
203/// A part of the message that represents the result of a tool call.
204#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
205#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
206pub struct ToolResultPart {
207    /// The ID of the tool call from previous assistant message.
208    pub tool_call_id: String,
209    /// The name of the tool that was called.
210    pub tool_name: String,
211    /// The content of the tool result.
212    pub content: Vec<Part>,
213    /// Marks the tool result as an error.
214    #[serde(skip_serializing_if = "Option::is_none")]
215    pub is_error: Option<bool>,
216}
217
218// A part of the message that represents the model reasoning.
219#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
220#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
221pub struct ReasoningPart {
222    /// The reasoning text content.
223    pub text: String,
224    /// The reasoning internal signature
225    #[serde(skip_serializing_if = "Option::is_none")]
226    pub signature: Option<String>,
227    /// The ID of the reasoning part, if applicable
228    #[serde(skip_serializing_if = "Option::is_none")]
229    pub id: Option<String>,
230}
231
232#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
233#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
234pub struct Citation {
235    /**
236     * The URL or identifier of the document being cited.
237     */
238    pub source: String,
239    /**
240     * The title of the document being cited.
241     */
242    #[serde(skip_serializing_if = "Option::is_none")]
243    pub title: Option<String>,
244    /**
245     * The text snippet from the document being cited.
246     */
247    #[serde(skip_serializing_if = "Option::is_none")]
248    pub cited_text: Option<String>,
249    /**
250     * The start index of the document content part being cited.
251     */
252    pub start_index: usize,
253    /**
254     * The end index of the document content part being cited.
255     */
256    pub end_index: usize,
257}
258
259/// Represents a message sent by the user.
260#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
261#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
262pub struct UserMessage {
263    pub content: Vec<Part>,
264}
265
266/// Represents a message generated by the model.
267#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
268#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
269pub struct AssistantMessage {
270    pub content: Vec<Part>,
271}
272
273/// A delta update for a text part, used in streaming or incremental updates of
274/// a message.
275#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
276#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
277pub struct TextPartDelta {
278    pub text: String,
279    #[serde(skip_serializing_if = "Option::is_none")]
280    pub citation: Option<CitationDelta>,
281}
282
283/// A delta update for a citation part, used in streaming of citation messages.
284#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
285#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
286pub struct CitationDelta {
287    /// The type of the citation delta.
288    #[serde(rename = "type")]
289    pub r#type: String,
290    /// The URL or identifier of the document being cited.
291    #[serde(skip_serializing_if = "Option::is_none")]
292    pub source: Option<String>,
293    /// The title of the document being cited.
294    #[serde(skip_serializing_if = "Option::is_none")]
295    pub title: Option<String>,
296    /// The text snippet from the document being cited.
297    #[serde(skip_serializing_if = "Option::is_none")]
298    pub cited_text: Option<String>,
299    /// The start index of the document content part being cited.
300    #[serde(skip_serializing_if = "Option::is_none")]
301    pub start_index: Option<usize>,
302    /// The end index of the document content part being cited.
303    #[serde(skip_serializing_if = "Option::is_none")]
304    pub end_index: Option<usize>,
305}
306
307/// A delta update for a tool call part, used in streaming of a tool invocation.
308#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
309#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
310pub struct ToolCallPartDelta {
311    /// The ID of the tool call, used to match the tool result with the tool
312    /// call.
313    #[serde(skip_serializing_if = "Option::is_none")]
314    pub tool_call_id: Option<String>,
315    /// The name of the tool to call.
316    #[serde(skip_serializing_if = "Option::is_none")]
317    pub tool_name: Option<String>,
318    /// The partial JSON string of the arguments to pass to the tool.
319    #[serde(skip_serializing_if = "Option::is_none")]
320    pub args: Option<String>,
321    /// The provider-specific signature used to preserve reasoning/tool
322    /// continuity.
323    #[serde(skip_serializing_if = "Option::is_none")]
324    pub signature: Option<String>,
325    /// The ID of the tool call, if applicable
326    /// This is different from `tool_call_id`, which is the ID used to match the
327    /// tool result with the tool call.
328    #[serde(skip_serializing_if = "Option::is_none")]
329    pub id: Option<String>,
330}
331
332/// A delta update for an image part, used in streaming of an image message.
333#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
334#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
335pub struct ImagePartDelta {
336    /// The MIME type of the image. E.g. "image/jpeg", "image/png".
337    #[serde(skip_serializing_if = "Option::is_none")]
338    pub mime_type: Option<String>,
339    /// The base64-encoded image data.
340    #[serde(skip_serializing_if = "Option::is_none")]
341    pub data: Option<String>,
342    /// The width of the image in pixels.
343    #[serde(skip_serializing_if = "Option::is_none")]
344    pub width: Option<u32>,
345    /// The height of the image in pixels.
346    #[serde(skip_serializing_if = "Option::is_none")]
347    pub height: Option<u32>,
348    /// The ID of the image part, if applicable
349    #[serde(skip_serializing_if = "Option::is_none")]
350    pub id: Option<String>,
351}
352
353/// A delta update for an audio part, used in streaming of an audio message.
354#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
355#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
356pub struct AudioPartDelta {
357    /// The base64-encoded audio data.
358    #[serde(skip_serializing_if = "Option::is_none")]
359    pub data: Option<String>,
360    #[serde(skip_serializing_if = "Option::is_none")]
361    pub format: Option<AudioFormat>,
362    /// The sample rate of the audio. E.g. 44100, 48000.
363    #[serde(skip_serializing_if = "Option::is_none")]
364    pub sample_rate: Option<u32>,
365    /// The number of channels of the audio. E.g. 1, 2.
366    #[serde(skip_serializing_if = "Option::is_none")]
367    pub channels: Option<u32>,
368    /// The transcript of the audio.
369    #[serde(skip_serializing_if = "Option::is_none")]
370    pub transcript: Option<String>,
371    /// The ID of the audio part, if applicable
372    #[serde(skip_serializing_if = "Option::is_none")]
373    pub id: Option<String>,
374}
375
376// A delta update for a reasoning part, used in streaming of reasoning messages.
377#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
378#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
379pub struct ReasoningPartDelta {
380    /// The reasoning text content.
381    #[serde(skip_serializing_if = "Option::is_none")]
382    pub text: Option<String>,
383    /// The reasoning internal signature
384    #[serde(skip_serializing_if = "Option::is_none")]
385    pub signature: Option<String>,
386    /// The ID of the reasoning part, if applicable
387    #[serde(skip_serializing_if = "Option::is_none")]
388    pub id: Option<String>,
389}
390
391/// Represents a delta update in a message's content, enabling partial streaming
392/// updates in LLM responses.
393#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
394#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
395pub struct ContentDelta {
396    pub index: usize,
397    pub part: PartDelta,
398}
399
400/// Represents a JSON schema.
401pub type JSONSchema = Value;
402
403/// Represents a tool that can be used by the model.
404#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
405#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
406pub struct Tool {
407    /// The name of the tool.
408    pub name: String,
409    /// A description of the tool.
410    pub description: String,
411    /// The JSON schema of the parameters that the tool accepts. The type must
412    /// be "object".
413    pub parameters: JSONSchema,
414}
415
416/// Represents tool result in the message history.
417/// The only parts of `ToolMessage` should be Part(ToolResultPart).
418#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
419#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
420pub struct ToolMessage {
421    pub content: Vec<Part>,
422}
423
424/// Represents the token usage of the model.
425#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
426#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
427pub struct ModelTokensDetails {
428    #[serde(skip_serializing_if = "Option::is_none")]
429    pub text_tokens: Option<u32>,
430    #[serde(skip_serializing_if = "Option::is_none")]
431    pub cached_text_tokens: Option<u32>,
432    #[serde(skip_serializing_if = "Option::is_none")]
433    pub audio_tokens: Option<u32>,
434    #[serde(skip_serializing_if = "Option::is_none")]
435    pub cached_audio_tokens: Option<u32>,
436    #[serde(skip_serializing_if = "Option::is_none")]
437    pub image_tokens: Option<u32>,
438    #[serde(skip_serializing_if = "Option::is_none")]
439    pub cached_image_tokens: Option<u32>,
440}
441
442/// Represents the token usage of the model.
443#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
444#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
445pub struct ModelUsage {
446    pub input_tokens: u32,
447    pub output_tokens: u32,
448    #[serde(skip_serializing_if = "Option::is_none")]
449    pub input_tokens_details: Option<ModelTokensDetails>,
450    #[serde(skip_serializing_if = "Option::is_none")]
451    pub output_tokens_details: Option<ModelTokensDetails>,
452}
453
454/// Represents the response generated by the model.
455#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
456#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
457pub struct ModelResponse {
458    pub content: Vec<Part>,
459    #[serde(skip_serializing_if = "Option::is_none")]
460    pub usage: Option<ModelUsage>,
461    /// The cost of the response.
462    #[serde(skip_serializing_if = "Option::is_none")]
463    pub cost: Option<f64>,
464}
465
466/// Represents a partial response from the language model, useful for streaming
467/// output via async generator.
468#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
469#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
470pub struct PartialModelResponse {
471    pub delta: Option<ContentDelta>,
472    pub usage: Option<ModelUsage>,
473    pub cost: Option<f64>,
474}
475
476/// The model will use the specified tool.
477#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
478#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
479pub struct ToolChoiceTool {
480    pub tool_name: String,
481}
482
483/// Specifies that the model response should be in JSON format adhering to a
484/// specified schema.
485#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
486#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
487pub struct ResponseFormatJson {
488    /// The name of the schema.
489    pub name: String,
490    /// The description of the schema.
491    #[serde(skip_serializing_if = "Option::is_none")]
492    pub description: Option<String>,
493    #[serde(skip_serializing_if = "Option::is_none")]
494    pub schema: Option<JSONSchema>,
495}
496
497/// Options for audio generation.
498#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
499#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
500pub struct AudioOptions {
501    /// The format of the audio.
502    #[serde(skip_serializing_if = "Option::is_none")]
503    pub format: Option<AudioFormat>,
504    /// The provider-specifc voice ID to use for audio generation.
505    #[serde(skip_serializing_if = "Option::is_none")]
506    pub voice: Option<String>,
507    /// The language code for the audio generation.
508    #[serde(skip_serializing_if = "Option::is_none")]
509    pub language: Option<String>,
510}
511
512/// Options for reasoning generation.
513#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
514#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
515pub struct ReasoningOptions {
516    /// Whether to enable reasoning output.
517    pub enabled: bool,
518    /// Specify the budget tokens for reasoning generation.
519    #[serde(skip_serializing_if = "Option::is_none")]
520    pub budget_tokens: Option<u32>,
521}
522
523/// Defines the input parameters for the language model completion.
524#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
525#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
526pub struct LanguageModelInput {
527    /// A system prompt is a way of providing context and instructions to the
528    /// model
529    #[serde(skip_serializing_if = "Option::is_none")]
530    pub system_prompt: Option<String>,
531    /// A list of messages comprising the conversation so far.
532    pub messages: Vec<Message>,
533    /// Definitions of tools that the model may use.
534    #[serde(skip_serializing_if = "Option::is_none")]
535    pub tools: Option<Vec<Tool>>,
536    #[serde(skip_serializing_if = "Option::is_none")]
537    pub tool_choice: Option<ToolChoiceOption>,
538    #[serde(skip_serializing_if = "Option::is_none")]
539    pub response_format: Option<ResponseFormatOption>,
540    /// The maximum number of tokens that can be generated in the chat
541    /// completion.
542    #[serde(skip_serializing_if = "Option::is_none")]
543    pub max_tokens: Option<u32>,
544    /// Amount of randomness injected into the response. Ranges from 0.0 to 1.0
545    #[serde(skip_serializing_if = "Option::is_none")]
546    pub temperature: Option<f64>,
547    /// An alternative to sampling with temperature, called nucleus sampling,
548    /// where the model considers the results of the tokens with `top_p`
549    /// probability mass. Ranges from 0.0 to 1.0
550    #[serde(skip_serializing_if = "Option::is_none")]
551    pub top_p: Option<f64>,
552    /// Only sample from the top K options for each subsequent token. Used to
553    /// remove 'long tail' low probability responses. Must be a non-negative
554    /// integer.
555    #[serde(skip_serializing_if = "Option::is_none")]
556    pub top_k: Option<i32>,
557    /// Positive values penalize new tokens based on whether they appear in the
558    /// text so far, increasing the model's likelihood to talk about new topics.
559    #[serde(skip_serializing_if = "Option::is_none")]
560    pub presence_penalty: Option<f64>,
561    /// Positive values penalize new tokens based on their existing frequency in
562    /// the text so far, decreasing the model's likelihood to repeat the same
563    /// line verbatim.
564    #[serde(skip_serializing_if = "Option::is_none")]
565    pub frequency_penalty: Option<f64>,
566    /// The seed (integer), if set and supported by the model, to enable
567    /// deterministic results.
568    #[serde(skip_serializing_if = "Option::is_none")]
569    pub seed: Option<i64>,
570    /// The modalities that the model should support.
571    #[serde(skip_serializing_if = "Option::is_none")]
572    pub modalities: Option<Vec<Modality>>,
573    /// A set of key/value pairs that store additional information about the
574    /// request. This is forwarded to the model provider if supported.
575    #[serde(skip_serializing_if = "Option::is_none")]
576    pub metadata: Option<HashMap<String, String>>,
577    /// Options for audio generation.
578    #[serde(skip_serializing_if = "Option::is_none")]
579    pub audio: Option<AudioOptions>,
580    /// Options for reasoning generation.
581    pub reasoning: Option<ReasoningOptions>,
582}
583
584/// A metadata property that describes the pricing of the model.
585#[derive(Debug, Clone, Serialize, Deserialize)]
586#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
587pub struct LanguageModelPricing {
588    /// The cost in USD per single text token for input.
589    #[serde(skip_serializing_if = "Option::is_none")]
590    pub input_cost_per_text_token: Option<f64>,
591    /// The cost in USD per single cached text token for input.
592    #[serde(skip_serializing_if = "Option::is_none")]
593    pub input_cost_per_cached_text_token: Option<f64>,
594    /// The cost in USD per single text token for output.
595    #[serde(skip_serializing_if = "Option::is_none")]
596    pub output_cost_per_text_token: Option<f64>,
597    /// The cost in USD per single audio token for input.
598    #[serde(skip_serializing_if = "Option::is_none")]
599    pub input_cost_per_audio_token: Option<f64>,
600    /// The cost in USD per single cached audio token for input.
601    #[serde(skip_serializing_if = "Option::is_none")]
602    pub input_cost_per_cached_audio_token: Option<f64>,
603    /// The cost in USD per single audio token for output.
604    #[serde(skip_serializing_if = "Option::is_none")]
605    pub output_cost_per_audio_token: Option<f64>,
606    /// The cost in USD per single image token for input.
607    #[serde(skip_serializing_if = "Option::is_none")]
608    pub input_cost_per_image_token: Option<f64>,
609    /// The cost in USD per single cached image token for input.
610    #[serde(skip_serializing_if = "Option::is_none")]
611    pub input_cost_per_cached_image_token: Option<f64>,
612    /// The cost in USD per single image token for output.
613    #[serde(skip_serializing_if = "Option::is_none")]
614    pub output_cost_per_image_token: Option<f64>,
615}