1use serde::{Deserialize, Serialize};
4
5use crate::prelude::*;
6
7use crate::common::{DebugOutput, IncompleteDetails};
8use crate::search::SearchParameters;
9use crate::tools::{
10 CodeInterpreterCall, CustomToolCall, FileSearchCall, FunctionToolCall, FunctionToolCallOutput,
11 McpCall, ModelTool, ModelToolChoice, OutputMessageContent, WebSearchCall,
12};
13use crate::usage::ModelUsage;
14
15#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
17pub struct ModelRequest {
18 pub input: ModelInput,
20
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub model: Option<String>,
24
25 #[serde(skip_serializing_if = "Option::is_none")]
27 pub instructions: Option<String>,
28
29 #[serde(skip_serializing_if = "Option::is_none")]
31 pub temperature: Option<f32>,
32
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub top_p: Option<f32>,
36
37 #[serde(skip_serializing_if = "Option::is_none")]
39 pub max_output_tokens: Option<i32>,
40
41 #[serde(skip_serializing_if = "Option::is_none")]
43 pub stream: Option<bool>,
44
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub logprobs: Option<bool>,
48
49 #[serde(skip_serializing_if = "Option::is_none")]
51 pub store: Option<bool>,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub previous_response_id: Option<String>,
56
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub tools: Option<Vec<ModelTool>>,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
63 pub tool_choice: Option<ModelToolChoice>,
64
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub parallel_tool_calls: Option<bool>,
68
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub search_parameters: Option<SearchParameters>,
72
73 #[serde(skip_serializing_if = "Option::is_none")]
75 pub reasoning: Option<ReasoningConfiguration>,
76
77 #[serde(skip_serializing_if = "Option::is_none")]
79 pub text: Option<ModelResponseConfiguration>,
80
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub include: Option<Vec<String>>,
84
85 #[serde(skip_serializing_if = "Option::is_none")]
87 pub metadata: Option<serde_json::Value>,
88
89 #[serde(skip_serializing_if = "Option::is_none")]
91 pub service_tier: Option<String>,
92
93 #[serde(skip_serializing_if = "Option::is_none")]
95 pub background: Option<bool>,
96}
97
98#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
100#[serde(untagged)]
101pub enum ModelInput {
102 Text(String),
104 Parts(Vec<ModelInputPart>),
106}
107
108impl Default for ModelInput {
109 fn default() -> Self {
110 ModelInput::Text(String::new())
111 }
112}
113
114#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
116#[serde(untagged)]
117pub enum ModelInputPart {
118 Message {
120 role: String,
122 content: ModelInputContent,
124 #[serde(skip_serializing_if = "Option::is_none")]
126 name: Option<String>,
127 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
129 message_type: Option<String>,
130 },
131 Item(ModelInputItem),
133}
134
135impl Default for ModelInputPart {
136 fn default() -> Self {
137 ModelInputPart::Message {
138 role: "user".to_string(),
139 content: ModelInputContent::default(),
140 name: None,
141 message_type: None,
142 }
143 }
144}
145
146#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
148#[serde(untagged)]
149pub enum ModelInputContent {
150 Text(String),
152 Parts(Vec<ModelInputContentItem>),
154}
155
156impl Default for ModelInputContent {
157 fn default() -> Self {
158 ModelInputContent::Text(String::new())
159 }
160}
161
162#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
164#[serde(tag = "type", rename_all = "snake_case")]
165pub enum ModelInputContentItem {
166 InputText {
168 text: String,
170 },
171 InputImage {
173 image_url: String,
175 #[serde(skip_serializing_if = "Option::is_none")]
177 detail: Option<String>,
178 #[serde(skip_serializing_if = "Option::is_none")]
180 file_id: Option<String>,
181 },
182 InputFile {
184 file_id: String,
186 },
187}
188
189impl Default for ModelInputContentItem {
190 fn default() -> Self {
191 ModelInputContentItem::InputText {
192 text: String::new(),
193 }
194 }
195}
196
197#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
199#[serde(untagged)]
200pub enum ModelInputItem {
201 Output(ModelOutput),
203 FunctionOutput(FunctionToolCallOutput),
205}
206
207impl Default for ModelInputItem {
208 fn default() -> Self {
209 ModelInputItem::FunctionOutput(FunctionToolCallOutput::default())
210 }
211}
212
213#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
215pub struct ModelResponse {
216 pub id: String,
218
219 pub object: String,
221
222 pub created_at: i64,
224
225 pub model: String,
227
228 pub output: Vec<ModelOutput>,
230
231 pub parallel_tool_calls: bool,
233
234 pub text: ModelResponseConfiguration,
236
237 pub tool_choice: ModelToolChoice,
239
240 pub tools: Vec<ModelTool>,
242
243 pub status: String,
245
246 pub store: bool,
248
249 pub metadata: serde_json::Value,
251
252 #[serde(skip_serializing_if = "Option::is_none")]
254 pub usage: Option<ModelUsage>,
255
256 #[serde(skip_serializing_if = "Option::is_none")]
258 pub temperature: Option<f32>,
259
260 #[serde(skip_serializing_if = "Option::is_none")]
262 pub top_p: Option<f32>,
263
264 #[serde(skip_serializing_if = "Option::is_none")]
266 pub max_output_tokens: Option<i32>,
267
268 #[serde(skip_serializing_if = "Option::is_none")]
270 pub previous_response_id: Option<String>,
271
272 #[serde(skip_serializing_if = "Option::is_none")]
274 pub reasoning: Option<ReasoningConfiguration>,
275
276 #[serde(skip_serializing_if = "Option::is_none")]
278 pub user: Option<String>,
279
280 #[serde(skip_serializing_if = "Option::is_none")]
282 pub incomplete_details: Option<IncompleteDetails>,
283
284 #[serde(skip_serializing_if = "Option::is_none")]
286 pub background: Option<bool>,
287
288 #[serde(skip_serializing_if = "Option::is_none")]
290 pub debug_output: Option<DebugOutput>,
291}
292
293#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
295#[serde(untagged)]
296pub enum ModelOutput {
297 Message(OutputMessage),
299 FunctionCall(FunctionToolCall),
301 Reasoning(Reasoning),
303 WebSearch(WebSearchCall),
305 FileSearch(FileSearchCall),
307 CodeInterpreter(CodeInterpreterCall),
309 Mcp(McpCall),
311 Custom(CustomToolCall),
313}
314
315impl Default for ModelOutput {
316 fn default() -> Self {
317 ModelOutput::Message(OutputMessage::default())
318 }
319}
320
321#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
323pub struct OutputMessage {
324 #[serde(rename = "type")]
326 pub message_type: String,
327
328 pub role: String,
330
331 pub content: Vec<OutputMessageContent>,
333
334 #[serde(skip_serializing_if = "Option::is_none")]
336 pub id: Option<String>,
337
338 #[serde(skip_serializing_if = "Option::is_none")]
340 pub status: Option<String>,
341}
342
343#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
345pub struct ReasoningConfiguration {
346 #[serde(skip_serializing_if = "Option::is_none")]
348 pub effort: Option<String>,
349
350 #[serde(skip_serializing_if = "Option::is_none")]
352 pub summary: Option<String>,
353
354 #[serde(skip_serializing_if = "Option::is_none")]
356 pub generate_summary: Option<String>,
357}
358
359#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
361pub struct Reasoning {
362 #[serde(rename = "type")]
364 pub reasoning_type: String,
365
366 pub summary: Vec<ReasoningText>,
368
369 #[serde(skip_serializing_if = "Option::is_none")]
371 pub id: Option<String>,
372
373 #[serde(skip_serializing_if = "Option::is_none")]
375 pub encrypted_content: Option<String>,
376
377 #[serde(skip_serializing_if = "Option::is_none")]
379 pub status: Option<String>,
380}
381
382#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
384pub struct ReasoningText {
385 #[serde(rename = "type")]
387 pub text_type: String,
388
389 pub text: String,
391}
392
393#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
395pub struct ModelResponseConfiguration {
396 #[serde(skip_serializing_if = "Option::is_none")]
398 pub format: Option<ModelResponseFormat>,
399}
400
401#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
403#[serde(tag = "type", rename_all = "snake_case")]
404pub enum ModelResponseFormat {
405 #[default]
407 Text,
408 JsonObject,
410 JsonSchema {
412 schema: serde_json::Value,
414 #[serde(skip_serializing_if = "Option::is_none")]
416 name: Option<String>,
417 #[serde(skip_serializing_if = "Option::is_none")]
419 description: Option<String>,
420 #[serde(skip_serializing_if = "Option::is_none")]
422 strict: Option<bool>,
423 },
424}
425
426#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
428pub struct DeleteStoredCompletionResponse {
429 pub id: String,
431
432 pub object: String,
434
435 pub deleted: bool,
437}