1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
7#[serde(rename_all = "lowercase")]
8pub enum Role {
9 System,
10 User,
11 Assistant,
12 Tool,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct Message {
18 pub role: Role,
20 #[serde(skip_serializing_if = "Option::is_none")]
22 pub content: Option<String>,
23 #[serde(skip_serializing_if = "Option::is_none")]
25 pub tool_calls: Option<Vec<ToolCall>>,
26 #[serde(skip_serializing_if = "Option::is_none")]
28 pub tool_call_id: Option<String>,
29}
30
31impl Message {
32 pub fn system(content: impl Into<String>) -> Self {
34 Self {
35 role: Role::System,
36 content: Some(content.into()),
37 tool_calls: None,
38 tool_call_id: None,
39 }
40 }
41
42 pub fn user(content: impl Into<String>) -> Self {
44 Self {
45 role: Role::User,
46 content: Some(content.into()),
47 tool_calls: None,
48 tool_call_id: None,
49 }
50 }
51
52 pub fn assistant(content: impl Into<String>) -> Self {
54 Self {
55 role: Role::Assistant,
56 content: Some(content.into()),
57 tool_calls: None,
58 tool_call_id: None,
59 }
60 }
61
62 pub fn assistant_with_tool_calls(tool_calls: Vec<ToolCall>) -> Self {
64 Self {
65 role: Role::Assistant,
66 content: None,
67 tool_calls: Some(tool_calls),
68 tool_call_id: None,
69 }
70 }
71
72 pub fn tool(tool_call_id: impl Into<String>, content: impl Into<String>) -> Self {
74 Self {
75 role: Role::Tool,
76 content: Some(content.into()),
77 tool_calls: None,
78 tool_call_id: Some(tool_call_id.into()),
79 }
80 }
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct ToolCall {
86 pub id: String,
88 #[serde(rename = "type")]
90 pub tool_type: String,
91 pub function: FunctionCall,
93}
94
95impl ToolCall {
96 pub fn new(
98 id: impl Into<String>,
99 name: impl Into<String>,
100 arguments: impl Into<String>,
101 ) -> Self {
102 Self {
103 id: id.into(),
104 tool_type: "function".to_string(),
105 function: FunctionCall {
106 name: name.into(),
107 arguments: arguments.into(),
108 },
109 }
110 }
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct FunctionCall {
116 pub name: String,
118 pub arguments: String,
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct Tool {
125 #[serde(rename = "type")]
127 pub tool_type: String,
128 pub function: FunctionDefinition,
130}
131
132impl Tool {
133 pub fn function(
135 name: impl Into<String>,
136 description: impl Into<String>,
137 parameters: serde_json::Value,
138 ) -> Self {
139 Self {
140 tool_type: "function".to_string(),
141 function: FunctionDefinition {
142 name: name.into(),
143 description: description.into(),
144 parameters,
145 },
146 }
147 }
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct FunctionDefinition {
153 pub name: String,
155 pub description: String,
157 pub parameters: serde_json::Value,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize, Default)]
163pub struct ProviderPreferences {
164 #[serde(skip_serializing_if = "Option::is_none")]
166 pub allow_fallbacks: Option<bool>,
167 #[serde(skip_serializing_if = "Option::is_none")]
169 pub require_parameters: Option<bool>,
170 #[serde(skip_serializing_if = "Option::is_none")]
172 pub data_collection: Option<String>,
173 #[serde(skip_serializing_if = "Option::is_none")]
175 pub order: Option<Vec<String>>,
176 #[serde(skip_serializing_if = "Option::is_none")]
178 pub ignore: Option<Vec<String>>,
179 #[serde(skip_serializing_if = "Option::is_none")]
181 pub quantizations: Option<Vec<String>>,
182}
183
184#[derive(Debug, Clone, Serialize)]
186pub struct CreateChatCompletionRequest {
187 pub model: String,
189 pub messages: Vec<Message>,
191 #[serde(skip_serializing_if = "Option::is_none")]
193 pub max_tokens: Option<usize>,
194 #[serde(skip_serializing_if = "Option::is_none")]
196 pub temperature: Option<f32>,
197 #[serde(skip_serializing_if = "Option::is_none")]
199 pub top_p: Option<f32>,
200 #[serde(skip_serializing_if = "Option::is_none")]
202 pub stop: Option<Vec<String>>,
203 #[serde(skip_serializing_if = "Option::is_none")]
205 pub tools: Option<Vec<Tool>>,
206 #[serde(skip_serializing_if = "Option::is_none")]
208 pub stream: Option<bool>,
209 #[serde(skip_serializing_if = "Option::is_none")]
211 pub n: Option<usize>,
212 #[serde(skip_serializing_if = "Option::is_none")]
214 pub presence_penalty: Option<f32>,
215 #[serde(skip_serializing_if = "Option::is_none")]
217 pub frequency_penalty: Option<f32>,
218 #[serde(skip_serializing_if = "Option::is_none")]
220 pub provider: Option<ProviderPreferences>,
221 #[serde(skip_serializing_if = "Option::is_none")]
223 pub models: Option<Vec<String>>,
224 #[serde(skip_serializing_if = "Option::is_none")]
226 pub route: Option<String>,
227}
228
229impl CreateChatCompletionRequest {
230 pub fn new(model: impl Into<String>, messages: Vec<Message>) -> Self {
232 Self {
233 model: model.into(),
234 messages,
235 max_tokens: None,
236 temperature: None,
237 top_p: None,
238 stop: None,
239 tools: None,
240 stream: None,
241 n: None,
242 presence_penalty: None,
243 frequency_penalty: None,
244 provider: None,
245 models: None,
246 route: None,
247 }
248 }
249
250 pub fn with_max_tokens(mut self, max_tokens: usize) -> Self {
252 self.max_tokens = Some(max_tokens);
253 self
254 }
255
256 pub fn with_temperature(mut self, temperature: f32) -> Self {
258 self.temperature = Some(temperature);
259 self
260 }
261
262 pub fn with_top_p(mut self, top_p: f32) -> Self {
264 self.top_p = Some(top_p);
265 self
266 }
267
268 pub fn with_stop(mut self, stop: Vec<String>) -> Self {
270 self.stop = Some(stop);
271 self
272 }
273
274 pub fn with_tools(mut self, tools: Vec<Tool>) -> Self {
276 self.tools = Some(tools);
277 self
278 }
279
280 pub fn with_provider(mut self, provider: ProviderPreferences) -> Self {
282 self.provider = Some(provider);
283 self
284 }
285
286 pub fn with_fallback_models(mut self, models: Vec<String>) -> Self {
288 self.models = Some(models);
289 self
290 }
291
292 pub fn with_route(mut self, route: impl Into<String>) -> Self {
294 self.route = Some(route.into());
295 self
296 }
297}
298
299#[derive(Debug, Clone, Deserialize)]
301pub struct Usage {
302 pub prompt_tokens: usize,
304 pub completion_tokens: usize,
306 pub total_tokens: usize,
308}
309
310#[derive(Debug, Clone, Deserialize)]
312pub struct Choice {
313 pub index: usize,
315 pub message: Message,
317 pub finish_reason: Option<String>,
319}
320
321#[derive(Debug, Clone, Deserialize)]
323pub struct CreateChatCompletionResponse {
324 pub id: String,
326 pub object: String,
328 pub created: u64,
330 pub model: String,
332 pub choices: Vec<Choice>,
334 pub usage: Option<Usage>,
336}
337
338impl CreateChatCompletionResponse {
339 pub fn content(&self) -> Option<&str> {
341 self.choices
342 .first()
343 .and_then(|c| c.message.content.as_deref())
344 }
345
346 pub fn tool_calls(&self) -> Option<&Vec<ToolCall>> {
348 self.choices
349 .first()
350 .and_then(|c| c.message.tool_calls.as_ref())
351 }
352
353 pub fn has_tool_calls(&self) -> bool {
355 self.choices
356 .first()
357 .is_some_and(|c| c.message.tool_calls.is_some())
358 }
359}
360
361#[derive(Debug, Clone, Deserialize)]
363pub struct ModelPricing {
364 pub prompt: String,
366 pub completion: String,
368 #[serde(default)]
370 pub image: Option<String>,
371 #[serde(default)]
373 pub request: Option<String>,
374}
375
376#[derive(Debug, Clone, Deserialize)]
378pub struct Model {
379 pub id: String,
381 pub name: String,
383 #[serde(default)]
385 pub description: Option<String>,
386 pub context_length: usize,
388 pub pricing: ModelPricing,
390 #[serde(default)]
392 pub top_provider: Option<TopProvider>,
393 #[serde(default)]
395 pub architecture: Option<ModelArchitecture>,
396}
397
398#[derive(Debug, Clone, Deserialize)]
400pub struct TopProvider {
401 #[serde(default)]
403 pub context_length: Option<usize>,
404 #[serde(default)]
406 pub max_completion_tokens: Option<usize>,
407 #[serde(default)]
409 pub is_moderated: Option<bool>,
410}
411
412#[derive(Debug, Clone, Deserialize)]
414pub struct ModelArchitecture {
415 #[serde(default)]
417 pub modality: Option<String>,
418 #[serde(default)]
420 pub tokenizer: Option<String>,
421 #[serde(default)]
423 pub instruct_type: Option<String>,
424}
425
426#[derive(Debug, Clone, Deserialize)]
428pub struct ModelList {
429 pub data: Vec<Model>,
431}
432
433#[derive(Debug, Clone, Deserialize)]
435pub struct GenerationStats {
436 pub id: String,
438 #[serde(default)]
440 pub total_cost: Option<f64>,
441 #[serde(default)]
443 pub tokens_prompt: Option<usize>,
444 #[serde(default)]
446 pub tokens_completion: Option<usize>,
447 #[serde(default)]
449 pub native_tokens_prompt: Option<usize>,
450 #[serde(default)]
452 pub native_tokens_completion: Option<usize>,
453}
454
455#[derive(Debug, Clone, Deserialize)]
457pub struct CreditsResponse {
458 #[serde(default)]
460 pub data: Option<CreditsData>,
461}
462
463#[derive(Debug, Clone, Deserialize)]
465pub struct CreditsData {
466 #[serde(default)]
468 pub label: Option<String>,
469 #[serde(default)]
471 pub balance: Option<f64>,
472 #[serde(default)]
474 pub usage: Option<f64>,
475 #[serde(default)]
477 pub limit: Option<f64>,
478 #[serde(default)]
480 pub is_free_tier: Option<bool>,
481}
482
483#[derive(Debug, Clone, Deserialize)]
485pub struct ErrorResponse {
486 pub error: ErrorDetail,
488}
489
490#[derive(Debug, Clone, Deserialize)]
492pub struct ErrorDetail {
493 pub message: String,
495 #[serde(rename = "type")]
497 #[serde(default)]
498 pub error_type: Option<String>,
499 #[serde(default)]
501 pub code: Option<i32>,
502}