1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "lowercase")]
8pub enum Role {
9 System,
10 User,
11 Assistant,
12 Tool,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17#[serde(untagged)]
18pub enum Content {
19 Text(String),
20 Parts(Vec<ContentPart>),
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
25#[serde(tag = "type", rename_all = "snake_case")]
26pub enum ContentPart {
27 Text { text: String },
28 ImageUrl { image_url: ImageUrl },
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct ImageUrl {
34 pub url: String,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub detail: Option<String>,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct Message {
42 pub role: Role,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 pub content: Option<Content>,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub name: Option<String>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub tool_calls: Option<Vec<ToolCall>>,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub tool_call_id: Option<String>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub reasoning_content: Option<String>,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct ToolCall {
58 pub id: String,
59 #[serde(rename = "type")]
60 pub call_type: String,
61 pub function: FunctionCall,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct FunctionCall {
67 pub name: String,
68 pub arguments: String,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct ToolDefinition {
74 #[serde(rename = "type")]
75 pub tool_type: String,
76 pub function: FunctionObject,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct FunctionObject {
82 pub name: String,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub description: Option<String>,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub parameters: Option<serde_json::Value>,
87 #[serde(skip_serializing_if = "Option::is_none")]
88 pub strict: Option<bool>,
89}
90
91#[derive(Debug, Clone, Serialize)]
93pub struct ChatRequest {
94 pub model: String,
95 pub messages: Vec<Message>,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub tools: Option<Vec<ToolDefinition>>,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub stream: Option<bool>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub max_tokens: Option<u32>,
102 #[serde(flatten)]
103 pub extra: serde_json::Map<String, serde_json::Value>,
104}
105
106#[derive(Debug, Clone, Deserialize, Default)]
110pub struct TokenUsage {
111 #[serde(default)]
112 pub prompt_tokens: u64,
113 #[serde(default)]
114 pub completion_tokens: u64,
115 #[serde(default)]
116 #[allow(dead_code)]
117 pub total_tokens: u64,
118}
119
120#[derive(Debug, Clone, Deserialize)]
122pub struct ChatResponse {
123 pub choices: Vec<Choice>,
124 #[serde(default)]
125 pub usage: Option<TokenUsage>,
126}
127
128#[derive(Debug, Clone, Deserialize)]
130pub struct Choice {
131 pub message: ResponseMessage,
132 pub finish_reason: Option<String>,
133}
134
135#[allow(dead_code)]
136impl Choice {
137 pub fn is_tool_calls(&self) -> bool {
139 self.finish_reason.as_deref() == Some("tool_calls")
140 }
141}
142
143#[derive(Debug, Clone, Deserialize)]
145#[allow(dead_code)]
146pub struct ResponseMessage {
147 pub content: Option<String>,
148 pub reasoning_content: Option<String>,
149 pub tool_calls: Option<Vec<ToolCall>>,
150}
151
152#[derive(Debug, Clone, Deserialize)]
156pub struct ChatStreamChunk {
157 pub choices: Vec<StreamChoice>,
158 #[serde(default)]
159 pub usage: Option<TokenUsage>,
160}
161
162#[derive(Debug, Clone, Deserialize)]
164pub struct StreamChoice {
165 #[serde(default)]
166 pub index: u32,
167 pub delta: Delta,
168 pub finish_reason: Option<String>,
169}
170
171impl StreamChoice {
172 #[allow(dead_code)]
174 pub fn is_tool_calls(&self) -> bool {
175 self.finish_reason.as_deref() == Some("tool_calls")
176 }
177}
178
179#[derive(Debug, Clone, Deserialize)]
181pub struct Delta {
182 #[allow(dead_code)]
183 pub role: Option<Role>,
184 pub content: Option<String>,
185 pub reasoning_content: Option<String>,
186 pub tool_calls: Option<Vec<DeltaToolCall>>,
187}
188
189#[derive(Debug, Clone, Deserialize)]
191pub struct DeltaToolCall {
192 #[serde(default)]
193 pub index: u32,
194 #[serde(default)]
195 pub id: Option<String>,
196 pub function: Option<DeltaFunction>,
197}
198
199#[derive(Debug, Clone, Deserialize)]
201pub struct DeltaFunction {
202 pub name: Option<String>,
203 pub arguments: Option<String>,
204}