1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct ChatCompletionsRequest {
12 pub model: String,
14
15 pub messages: Vec<ChatMessage>,
17
18 #[serde(skip_serializing_if = "Option::is_none")]
20 pub max_tokens: Option<u32>,
21
22 #[serde(skip_serializing_if = "Option::is_none")]
24 pub temperature: Option<f32>,
25
26 #[serde(skip_serializing_if = "Option::is_none")]
28 pub top_p: Option<f32>,
29
30 #[serde(skip_serializing_if = "Option::is_none")]
32 pub n: Option<u32>,
33
34 #[serde(skip_serializing_if = "Option::is_none")]
36 pub stream: Option<bool>,
37
38 #[serde(skip_serializing_if = "Option::is_none")]
40 pub stop: Option<Vec<String>>,
41
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub presence_penalty: Option<f32>,
45
46 #[serde(skip_serializing_if = "Option::is_none")]
48 pub frequency_penalty: Option<f32>,
49
50 #[serde(skip_serializing_if = "Option::is_none")]
52 pub logit_bias: Option<HashMap<String, f32>>,
53
54 #[serde(skip_serializing_if = "Option::is_none")]
56 pub user: Option<String>,
57
58 #[serde(skip_serializing_if = "Option::is_none")]
60 pub seed: Option<u64>,
61
62 #[serde(skip_serializing_if = "Option::is_none")]
64 pub response_format: Option<OpenAiResponseFormat>,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct OpenAiResponseFormat {
70 #[serde(rename = "type")]
72 pub format_type: String,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct ChatMessage {
78 pub role: MessageRole,
80
81 pub content: String,
83
84 #[serde(skip_serializing_if = "Option::is_none")]
86 pub name: Option<String>,
87}
88
89#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
91#[serde(rename_all = "lowercase")]
92pub enum MessageRole {
93 System,
94 User,
95 Assistant,
96 Function,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct ChatCompletionsResponse {
102 pub id: String,
104
105 pub object: String,
107
108 pub created: u64,
110
111 pub model: String,
113
114 pub choices: Vec<ChatChoice>,
116
117 #[serde(skip_serializing_if = "Option::is_none")]
119 pub usage: Option<Usage>,
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct ChatChoice {
125 pub index: u32,
127
128 #[serde(skip_serializing_if = "Option::is_none")]
130 pub message: Option<ChatMessage>,
131
132 #[serde(skip_serializing_if = "Option::is_none")]
134 pub delta: Option<ChatMessage>,
135
136 #[serde(skip_serializing_if = "Option::is_none")]
138 pub finish_reason: Option<String>,
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
143pub struct CompletionsRequest {
144 pub model: String,
146
147 pub prompt: String,
149
150 #[serde(skip_serializing_if = "Option::is_none")]
152 pub max_tokens: Option<u32>,
153
154 #[serde(skip_serializing_if = "Option::is_none")]
156 pub temperature: Option<f32>,
157
158 #[serde(skip_serializing_if = "Option::is_none")]
160 pub top_p: Option<f32>,
161
162 #[serde(skip_serializing_if = "Option::is_none")]
164 pub stream: Option<bool>,
165
166 #[serde(skip_serializing_if = "Option::is_none")]
168 pub stop: Option<Vec<String>>,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
173pub struct CompletionsResponse {
174 pub id: String,
175 pub object: String,
176 pub created: u64,
177 pub model: String,
178 pub choices: Vec<CompletionChoice>,
179 pub usage: Option<Usage>,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct CompletionChoice {
185 pub text: String,
186 pub index: u32,
187 pub finish_reason: Option<String>,
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct Usage {
193 pub prompt_tokens: u32,
194 pub completion_tokens: u32,
195 pub total_tokens: u32,
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct ModelListResponse {
201 pub object: String,
202 pub data: Vec<ModelInfo>,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize)]
207pub struct ModelInfo {
208 pub id: String,
209 pub object: String,
210 pub created: u64,
211 pub owned_by: String,
212 pub permission: Vec<ModelPermission>,
213 pub root: Option<String>,
214 pub parent: Option<String>,
215}
216
217#[derive(Debug, Clone, Serialize, Deserialize)]
219pub struct ModelPermission {
220 pub id: String,
221 pub object: String,
222 pub created: u64,
223 pub allow_create_engine: bool,
224 pub allow_sampling: bool,
225 pub allow_logprobs: bool,
226 pub allow_search_indices: bool,
227 pub allow_view: bool,
228 pub allow_fine_tuning: bool,
229 pub organization: String,
230 pub group: Option<String>,
231 pub is_blocking: bool,
232}
233
234#[derive(Debug, Clone, Serialize, Deserialize)]
238pub struct EmbeddingsRequest {
239 pub model: String,
241
242 pub input: EmbeddingInput,
244
245 #[serde(skip_serializing_if = "Option::is_none")]
247 pub encoding_format: Option<String>,
248}
249
250#[derive(Debug, Clone, Serialize, Deserialize)]
253#[serde(untagged)]
254pub enum EmbeddingInput {
255 Single(String),
257 Batch(Vec<String>),
259 SingleObject(EmbeddingItem),
261 BatchObjects(Vec<EmbeddingItem>),
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
267pub struct EmbeddingItem {
268 #[serde(skip_serializing_if = "Option::is_none")]
270 pub text: Option<String>,
271 #[serde(skip_serializing_if = "Option::is_none")]
273 pub image: Option<String>,
274}
275
276#[derive(Debug, Clone, Serialize, Deserialize)]
278pub struct EmbeddingsResponse {
279 pub object: String,
280 pub data: Vec<EmbeddingData>,
281 pub model: String,
282 pub usage: EmbeddingUsage,
283}
284
285#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct EmbeddingData {
288 pub object: String,
289 pub embedding: Vec<f32>,
290 pub index: usize,
291}
292
293#[derive(Debug, Clone, Serialize, Deserialize)]
295pub struct EmbeddingUsage {
296 pub prompt_tokens: u32,
297 pub total_tokens: u32,
298}
299
300#[derive(Debug, Clone, Serialize, Deserialize)]
304pub struct TranscriptionResponse {
305 pub text: String,
306}
307
308#[derive(Debug, Clone, Serialize, Deserialize)]
312pub struct OpenAiError {
313 pub error: OpenAiErrorDetail,
314}
315
316#[derive(Debug, Clone, Serialize, Deserialize)]
318pub struct OpenAiErrorDetail {
319 pub message: String,
320 #[serde(rename = "type")]
321 pub error_type: String,
322 pub param: Option<String>,
323 pub code: Option<String>,
324}
325
326#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
328pub enum OpenAiErrorType {
329 InvalidRequestError,
330 AuthenticationError,
331 PermissionError,
332 NotFoundError,
333 RateLimitError,
334 InternalServerError,
335 ServiceUnavailableError,
336}
337
338#[derive(Debug, Clone)]
340pub struct SseEvent {
341 pub event: Option<String>,
342 pub data: String,
343 pub id: Option<String>,
344 pub retry: Option<u32>,
345}
346
347impl SseEvent {
348 pub fn data(data: String) -> Self {
349 Self {
350 event: None,
351 data,
352 id: None,
353 retry: None,
354 }
355 }
356
357 pub fn json(value: &serde_json::Value) -> Result<Self, serde_json::Error> {
358 Ok(Self::data(serde_json::to_string(value)?))
359 }
360
361 pub fn to_string(&self) -> String {
362 let mut result = String::new();
363
364 if let Some(event) = &self.event {
365 result.push_str(&format!("event: {}\n", event));
366 }
367
368 if let Some(id) = &self.id {
369 result.push_str(&format!("id: {}\n", id));
370 }
371
372 if let Some(retry) = self.retry {
373 result.push_str(&format!("retry: {}\n", retry));
374 }
375
376 result.push_str(&format!("data: {}\n\n", self.data));
377 result
378 }
379}
380
381#[derive(Debug, Clone, Serialize, Deserialize)]
383pub struct SpeechRequest {
384 #[serde(default = "default_tts_model")]
386 pub model: String,
387
388 pub input: String,
390
391 #[serde(default = "default_voice")]
393 pub voice: String,
394
395 #[serde(default = "default_audio_format")]
397 pub response_format: String,
398
399 #[serde(default = "default_language")]
401 pub language: String,
402
403 #[serde(default)]
405 pub stream: bool,
406}
407
408fn default_tts_model() -> String {
409 "qwen3-tts".to_string()
410}
411fn default_voice() -> String {
412 "default".to_string()
413}
414fn default_audio_format() -> String {
415 "wav".to_string()
416}
417fn default_language() -> String {
418 "auto".to_string()
419}