1use std::collections::VecDeque;
2
3use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer};
4
5use super::function::ToolDef;
6
7use super::prompt::{Choice, Message};
8
9#[derive(Debug, Clone)]
11pub struct APIResponseHeaders {
12 pub retry_after: Option<u64>,
14 pub reset: Option<u64>,
16 pub rate_limit: Option<u64>,
18 pub limit: Option<u64>,
20
21 pub extra_other: Vec<(String, String)>,
23}
24
25#[derive(Debug, Deserialize)]
27pub struct APIRequest {
28 pub model: String,
30
31 pub messages: VecDeque<Message>,
33
34 #[serde(skip_serializing_if = "Vec::is_empty")]
36 pub tools: Vec<ToolDef>,
37
38 #[serde(skip_serializing_if = "Vec::is_empty")]
44 pub tool_choice: serde_json::Value,
45
46 #[serde(skip_serializing_if = "Option::is_none")]
49 pub parallel_tool_calls: Option<bool>,
50
51 #[serde(skip_serializing_if = "Option::is_none")]
55 pub temperature: Option<f64>,
56
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub max_completion_tokens: Option<u64>,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
64 pub top_p: Option<f64>,
65
66 #[serde(skip_serializing_if = "Option::is_none")]
72 pub reasoning_effort: Option<String>,
73
74 #[serde(skip_serializing_if = "Option::is_none")]
77 pub presence_penalty: Option<f64>,
78
79 #[serde(skip_serializing_if = "Option::is_none")]
81 pub web_search_options: Option<WebSearchOptions>,
82}
83
84impl Serialize for APIRequest {
86 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
87 where
88 S: Serializer,
89 {
90 let mut state = serializer.serialize_struct("APIRequest", 10)?;
92
93 state.serialize_field("model", &self.model)?;
94 state.serialize_field("messages", &self.messages)?;
95
96 if !self.tools.is_empty() {
98 state.serialize_field("tools", &self.tools)?;
99 }
100
101 if self.tool_choice != serde_json::Value::String("none".to_string()) {
103 state.serialize_field("tool_choice", &self.tool_choice)?;
104 }
105
106 if let Some(parallel_tool_calls) = &self.parallel_tool_calls {
108 state.serialize_field("parallel_tool_calls", parallel_tool_calls)?;
109 }
110 if let Some(temperature) = &self.temperature {
111 state.serialize_field("temperature", temperature)?;
112 }
113 if let Some(max_completion_tokens) = &self.max_completion_tokens {
114 state.serialize_field("max_completion_tokens", max_completion_tokens)?;
115 }
116 if let Some(top_p) = &self.top_p {
117 state.serialize_field("top_p", top_p)?;
118 }
119 if let Some(reasoning_effort) = &self.reasoning_effort {
120 state.serialize_field("reasoning_effort", reasoning_effort)?;
121 }
122 if let Some(presence_penalty) = &self.presence_penalty {
123 state.serialize_field("presence_penalty", presence_penalty)?;
124 }
125
126 state.end()
127 }
128}
129
130#[derive(Debug, Deserialize, Clone)]
132pub struct APIResponse {
133 pub id: String,
135 pub object: String,
137 pub model: Option<String>,
139 pub choices: Option<Vec<Choice>>,
141 pub error: Option<APIError>,
143 pub usage: Option<APIUsage>,
145 pub created: Option<u64>,
147}
148
149#[derive(Debug, Deserialize, Clone)]
151pub struct APIError {
152 pub message: String,
154 #[serde(rename = "type")]
156 pub err_type: String,
157 pub code: i32,
159}
160
161#[derive(Debug, Deserialize, Clone)]
163pub struct APIUsage {
164 pub prompt_tokens: Option<u64>,
166 pub completion_tokens: Option<u64>,
168 pub total_tokens: Option<u64>,
170}
171
172#[derive(Debug, Clone, Deserialize)]
173pub struct WebSearchOptions {
174 pub search_context_size: Option<String>,
180 pub user_location: UserLocation,
181}
182
183impl Serialize for WebSearchOptions {
184 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
185 where
186 S: Serializer,
187 {
188 let mut state = serializer.serialize_struct("WebSearchOptions", 2)?;
189 let size = self.search_context_size.as_deref().unwrap_or("medium");
191 state.serialize_field("search_context_size", size)?;
192 state.serialize_field("user_location", &self.user_location)?;
193 state.end()
194 }
195}
196
197#[derive(Debug, Clone, Deserialize)]
199pub struct UserLocation {
200 pub city: Option<String>,
203 pub country: Option<String>,
206 pub region: Option<String>,
209 pub timezone: Option<String>,
212}
213
214impl Serialize for UserLocation {
215 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
216 where
217 S: Serializer,
218 {
219
220 let mut state = serializer.serialize_struct("UserLocation", 2)?;
221
222 state.serialize_field("type", "approximate")?;
224
225 let mut approximate = serde_json::Map::new();
227 if let Some(ref city) = self.city {
228 approximate.insert("city".to_string(), serde_json::Value::String(city.clone()));
229 }
230 if let Some(ref country) = self.country {
231 approximate.insert("country".to_string(), serde_json::Value::String(country.clone()));
232 }
233 if let Some(ref region) = self.region {
234 approximate.insert("region".to_string(), serde_json::Value::String(region.clone()));
235 }
236 if let Some(ref timezone) = self.timezone {
237 approximate.insert("timezone".to_string(), serde_json::Value::String(timezone.clone()));
238 }
239
240 state.serialize_field("approximate", &approximate)?;
241 state.end()
242 }
243}