1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Deserialize)]
11pub struct ChatCompletionRequest {
12 pub model: String,
14 pub messages: Vec<ChatMessage>,
16 #[serde(default)]
18 pub temperature: Option<f32>,
19 #[serde(default)]
21 pub top_p: Option<f32>,
22 #[serde(default)]
24 pub n: Option<u32>,
25 #[serde(default)]
27 pub stream: Option<bool>,
28 #[serde(default)]
30 pub stop: Option<Vec<String>>,
31 #[serde(default)]
33 pub max_tokens: Option<u32>,
34 #[serde(default)]
36 pub presence_penalty: Option<f32>,
37 #[serde(default)]
39 pub frequency_penalty: Option<f32>,
40 #[serde(default)]
42 pub user: Option<String>,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct ChatMessage {
48 pub role: String,
50 pub content: String,
52 #[serde(skip_serializing_if = "Option::is_none")]
54 pub name: Option<String>,
55}
56
57#[derive(Debug, Clone, Serialize)]
59pub struct ChatCompletionResponse {
60 pub id: String,
62 pub object: String,
64 pub created: i64,
66 pub model: String,
68 pub choices: Vec<ChatChoice>,
70 pub usage: Usage,
72}
73
74#[derive(Debug, Clone, Serialize)]
76pub struct ChatChoice {
77 pub index: u32,
79 pub message: ChatMessage,
81 pub finish_reason: String,
83}
84
85#[derive(Debug, Clone, Serialize)]
87pub struct ChatCompletionChunk {
88 pub id: String,
90 pub object: String,
92 pub created: i64,
94 pub model: String,
96 pub choices: Vec<ChatChunkChoice>,
98}
99
100#[derive(Debug, Clone, Serialize)]
102pub struct ChatChunkChoice {
103 pub index: u32,
105 pub delta: ChatDelta,
107 #[serde(skip_serializing_if = "Option::is_none")]
109 pub finish_reason: Option<String>,
110}
111
112#[derive(Debug, Clone, Serialize, Default)]
114pub struct ChatDelta {
115 #[serde(skip_serializing_if = "Option::is_none")]
117 pub role: Option<String>,
118 #[serde(skip_serializing_if = "Option::is_none")]
120 pub content: Option<String>,
121}
122
123#[derive(Debug, Clone, Deserialize)]
127pub struct CompletionRequest {
128 pub model: String,
130 pub prompt: String,
132 #[serde(default)]
134 pub temperature: Option<f32>,
135 #[serde(default)]
137 pub top_p: Option<f32>,
138 #[serde(default)]
140 pub n: Option<u32>,
141 #[serde(default)]
143 pub stream: Option<bool>,
144 #[serde(default)]
146 pub stop: Option<Vec<String>>,
147 #[serde(default)]
149 pub max_tokens: Option<u32>,
150 #[serde(default)]
152 pub logprobs: Option<u32>,
153 #[serde(default)]
155 pub echo: Option<bool>,
156 #[serde(default)]
158 pub suffix: Option<String>,
159}
160
161#[derive(Debug, Clone, Serialize)]
163pub struct CompletionResponse {
164 pub id: String,
166 pub object: String,
168 pub created: i64,
170 pub model: String,
172 pub choices: Vec<CompletionChoice>,
174 pub usage: Usage,
176}
177
178#[derive(Debug, Clone, Serialize)]
180pub struct CompletionChoice {
181 pub text: String,
183 pub index: u32,
185 pub finish_reason: String,
187 #[serde(skip_serializing_if = "Option::is_none")]
189 pub logprobs: Option<LogProbs>,
190}
191
192#[derive(Debug, Clone, Serialize)]
194pub struct LogProbs {
195 pub tokens: Vec<String>,
197 pub token_logprobs: Vec<f32>,
199 pub top_logprobs: Vec<std::collections::HashMap<String, f32>>,
201 pub text_offset: Vec<u32>,
203}
204
205#[derive(Debug, Clone, Deserialize)]
209pub struct EmbeddingRequest {
210 pub model: String,
212 pub input: EmbeddingInput,
214 #[serde(default)]
216 pub encoding_format: Option<String>,
217 #[serde(default)]
219 pub dimensions: Option<u32>,
220}
221
222#[derive(Debug, Clone, Deserialize)]
224#[serde(untagged)]
225pub enum EmbeddingInput {
226 Single(String),
228 Multiple(Vec<String>),
230}
231
232#[derive(Debug, Clone, Serialize)]
234pub struct EmbeddingResponse {
235 pub object: String,
237 pub data: Vec<EmbeddingData>,
239 pub model: String,
241 pub usage: EmbeddingUsage,
243}
244
245#[derive(Debug, Clone, Serialize)]
247pub struct EmbeddingData {
248 pub object: String,
250 pub index: u32,
252 pub embedding: Vec<f32>,
254}
255
256#[derive(Debug, Clone, Serialize)]
258pub struct EmbeddingUsage {
259 pub prompt_tokens: u32,
261 pub total_tokens: u32,
263}
264
265#[derive(Debug, Clone, Serialize)]
269pub struct ModelsResponse {
270 pub object: String,
272 pub data: Vec<ModelObject>,
274}
275
276#[derive(Debug, Clone, Serialize)]
278pub struct ModelObject {
279 pub id: String,
281 pub object: String,
283 pub created: i64,
285 pub owned_by: String,
287}
288
289#[derive(Debug, Clone, Default, Serialize, Deserialize)]
293pub struct Usage {
294 pub prompt_tokens: u32,
296 pub completion_tokens: u32,
298 pub total_tokens: u32,
300}
301
302impl Usage {
303 pub fn new(prompt_tokens: u32, completion_tokens: u32) -> Self {
305 Self {
306 prompt_tokens,
307 completion_tokens,
308 total_tokens: prompt_tokens + completion_tokens,
309 }
310 }
311}
312
313#[cfg(test)]
314mod tests {
315 use super::*;
316
317 #[test]
318 fn test_chat_request_deserialization() {
319 let json = r#"{
320 "model": "gpt-4",
321 "messages": [
322 {"role": "system", "content": "You are a helpful assistant."},
323 {"role": "user", "content": "Hello!"}
324 ],
325 "temperature": 0.7,
326 "max_tokens": 100
327 }"#;
328
329 let req: ChatCompletionRequest = serde_json::from_str(json).unwrap();
330 assert_eq!(req.model, "gpt-4");
331 assert_eq!(req.messages.len(), 2);
332 assert_eq!(req.temperature, Some(0.7));
333 assert_eq!(req.max_tokens, Some(100));
334 }
335
336 #[test]
337 fn test_chat_response_serialization() {
338 let response = ChatCompletionResponse {
339 id: "chatcmpl-123".to_string(),
340 object: "chat.completion".to_string(),
341 created: 1677652288,
342 model: "gpt-4".to_string(),
343 choices: vec![ChatChoice {
344 index: 0,
345 message: ChatMessage {
346 role: "assistant".to_string(),
347 content: "Hello!".to_string(),
348 name: None,
349 },
350 finish_reason: "stop".to_string(),
351 }],
352 usage: Usage::new(10, 5),
353 };
354
355 let json = serde_json::to_string(&response).unwrap();
356 assert!(json.contains("chatcmpl-123"));
357 assert!(json.contains("Hello!"));
358 }
359
360 #[test]
361 fn test_embedding_input_variants() {
362 let json = r#"{"model": "text-embedding-3-small", "input": "Hello"}"#;
364 let req: EmbeddingRequest = serde_json::from_str(json).unwrap();
365 matches!(req.input, EmbeddingInput::Single(_));
366
367 let json = r#"{"model": "text-embedding-3-small", "input": ["Hello", "World"]}"#;
369 let req: EmbeddingRequest = serde_json::from_str(json).unwrap();
370 matches!(req.input, EmbeddingInput::Multiple(_));
371 }
372
373 #[test]
374 fn test_usage() {
375 let usage = Usage::new(100, 50);
376 assert_eq!(usage.prompt_tokens, 100);
377 assert_eq!(usage.completion_tokens, 50);
378 assert_eq!(usage.total_tokens, 150);
379 }
380}