1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::borrow::Cow;
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6#[serde(untagged)]
7pub enum ChatMessageContent {
8 Text(String),
9 Parts(Vec<ChatContentPart>),
10}
11
12impl ChatMessageContent {
13 pub fn text(text: impl Into<String>) -> Self {
14 Self::Text(text.into())
15 }
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19#[serde(untagged)]
20pub enum ChatContentPart {
21 Text(ChatContentPartText),
22 ImageUrl(ChatContentPartImageUrl),
23 InputAudio(ChatContentPartInputAudio),
24 File(ChatContentPartFile),
25 Other(Value),
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct ChatContentPartText {
30 #[serde(rename = "type")]
31 pub kind: Cow<'static, str>,
32 pub text: String,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct ChatContentPartImageUrl {
37 #[serde(rename = "type")]
38 pub kind: Cow<'static, str>,
39 pub image_url: ChatImageUrl,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43#[serde(untagged)]
44pub enum ChatImageUrl {
45 Url(String),
46 Object(ChatImageUrlObject),
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct ChatImageUrlObject {
51 pub url: String,
52 pub detail: Option<String>,
53 pub format: Option<String>,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct ChatContentPartInputAudio {
58 #[serde(rename = "type")]
59 pub kind: Cow<'static, str>,
60 pub input_audio: ChatInputAudio,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct ChatInputAudio {
65 pub data: String,
66 pub format: String,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct ChatContentPartFile {
71 #[serde(rename = "type")]
72 pub kind: Cow<'static, str>,
73 pub file: ChatFile,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct ChatFile {
78 pub file_id: Option<String>,
79 pub file_data: Option<String>,
80 pub format: Option<String>,
81 pub detail: Option<String>,
82 pub video_metadata: Option<Value>,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct ChatMessage {
87 pub role: String,
88 pub content: ChatMessageContent,
89 #[serde(skip_serializing_if = "Option::is_none")]
90 pub name: Option<String>,
91 #[serde(skip_serializing_if = "Option::is_none")]
92 pub tool_call_id: Option<String>,
93 #[serde(skip_serializing_if = "Option::is_none")]
94 pub tool_calls: Option<Value>,
95 #[serde(skip_serializing_if = "Option::is_none")]
96 pub function_call: Option<Value>,
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub provider_specific_fields: Option<Value>,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct ChatRequest {
103 pub model: String,
104 pub messages: Vec<ChatMessage>,
105 pub temperature: Option<f32>,
106 pub max_tokens: Option<u32>,
107 pub response_format: Option<Value>,
108 pub max_completion_tokens: Option<u32>,
109 pub tools: Option<Value>,
110 pub tool_choice: Option<Value>,
111 pub parallel_tool_calls: Option<bool>,
112 pub stop: Option<Value>,
113 pub top_p: Option<f32>,
114 pub presence_penalty: Option<f32>,
115 pub frequency_penalty: Option<f32>,
116 pub seed: Option<u64>,
117 pub user: Option<String>,
118 pub metadata: Option<Value>,
119 pub reasoning_effort: Option<Value>,
120 pub thinking: Option<Value>,
121}
122
123impl ChatRequest {
124 pub fn new(model: impl Into<String>) -> Self {
125 Self {
126 model: model.into(),
127 messages: Vec::new(),
128 temperature: None,
129 max_tokens: None,
130 response_format: None,
131 max_completion_tokens: None,
132 tools: None,
133 tool_choice: None,
134 parallel_tool_calls: None,
135 stop: None,
136 top_p: None,
137 presence_penalty: None,
138 frequency_penalty: None,
139 seed: None,
140 user: None,
141 metadata: None,
142 reasoning_effort: None,
143 thinking: None,
144 }
145 }
146
147 pub fn message(mut self, role: impl Into<String>, content: impl Into<String>) -> Self {
148 self.messages.push(ChatMessage {
149 role: role.into(),
150 content: ChatMessageContent::Text(content.into()),
151 name: None,
152 tool_call_id: None,
153 tool_calls: None,
154 function_call: None,
155 provider_specific_fields: None,
156 });
157 self
158 }
159
160 pub fn message_with_content(
161 mut self,
162 role: impl Into<String>,
163 content: ChatMessageContent,
164 ) -> Self {
165 self.messages.push(ChatMessage {
166 role: role.into(),
167 content,
168 name: None,
169 tool_call_id: None,
170 tool_calls: None,
171 function_call: None,
172 provider_specific_fields: None,
173 });
174 self
175 }
176
177 pub fn temperature(mut self, temperature: f32) -> Self {
178 self.temperature = Some(temperature);
179 self
180 }
181
182 pub fn max_tokens(mut self, max_tokens: u32) -> Self {
183 self.max_tokens = Some(max_tokens);
184 self
185 }
186
187 pub fn response_format(mut self, format: Value) -> Self {
188 self.response_format = Some(format);
189 self
190 }
191}
192
193#[derive(Debug, Clone, Serialize, Deserialize)]
194pub struct ChatResponse {
195 pub content: String,
196 pub usage: Usage,
197 pub response_id: Option<String>,
198 pub header_cost: Option<f64>,
199 pub raw: Option<Value>,
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize, Default)]
207pub struct Usage {
208 pub prompt_tokens: Option<u64>,
209 pub completion_tokens: Option<u64>,
210 pub thoughts_tokens: Option<u64>,
211 pub total_tokens: Option<u64>,
212 pub cost_usd: Option<f64>,
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
216pub struct EmbeddingRequest {
217 pub model: String,
218 pub input: Value,
219}
220
221#[derive(Debug, Clone, Serialize, Deserialize)]
222pub struct EmbeddingResponse {
223 pub vectors: Vec<Vec<f32>>,
224 pub usage: Usage,
225 pub raw: Option<Value>,
226}
227
228#[derive(Debug, Clone, Serialize, Deserialize)]
229pub struct ImageRequest {
230 pub model: String,
231 pub prompt: String,
232 pub n: Option<u32>,
233 pub size: Option<String>,
234 pub quality: Option<String>,
235 pub background: Option<String>,
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize)]
239pub struct ImageData {
240 pub b64_json: Option<String>,
241 pub url: Option<String>,
242 pub revised_prompt: Option<String>,
243 pub mime_type: Option<String>,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
247pub struct ImageEditRequest {
248 pub model: String,
249 pub prompt: String,
250 pub images: Vec<ImageInputData>,
251 pub n: Option<u32>,
252 pub size: Option<String>,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize)]
256pub struct ImageInputData {
257 pub b64_json: Option<String>,
258 pub url: Option<String>,
259 pub mime_type: Option<String>,
260}
261
262#[derive(Debug, Clone, Serialize, Deserialize)]
263pub struct ImageResponse {
264 pub images: Vec<ImageData>,
265 pub usage: Usage,
266 pub raw: Option<Value>,
267}
268
269#[derive(Debug, Clone, Serialize, Deserialize)]
270pub struct VideoRequest {
271 pub model: String,
272 pub prompt: String,
273 pub seconds: Option<u32>,
274 pub size: Option<String>,
275}
276
277#[derive(Debug, Clone, Serialize, Deserialize)]
278pub struct VideoResponse {
279 pub video_url: Option<String>,
280 pub raw: Option<Value>,
281}