1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4use crate::openai::common::*;
5
6use super::{
7 ChatAudioParam, ChatAudioRef, ChatFileRef, ChatWebSearchOptions, CustomToolCall, ImageUrl,
8 InputAudio, PredictionContent, StreamOptions,
9};
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
12#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
13pub struct ChatCompletionRequest {
14 pub messages: Vec<ChatCompletionMessageParam>,
15 pub model: OpenAiModelId,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 pub audio: Option<ChatAudioParam>,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub frequency_penalty: Option<f64>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub function_call: Option<LegacyFunctionCallChoice>,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub functions: Option<Vec<LegacyFunctionDefinition>>,
24 #[serde(skip_serializing_if = "Option::is_none")]
25 pub logit_bias: Option<LogitBias>,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub logprobs: Option<bool>,
28 #[serde(skip_serializing_if = "Option::is_none")]
29 pub max_completion_tokens: Option<u32>,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub max_tokens: Option<u32>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 pub metadata: Option<Metadata>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub modalities: Option<Vec<TextOrAudioModality>>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub moderation: Option<ModerationConfig>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub n: Option<u32>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub parallel_tool_calls: Option<bool>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub prediction: Option<PredictionContent>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub presence_penalty: Option<f64>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub prompt_cache_key: Option<String>,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 pub prompt_cache_options: Option<PromptCacheOptions>,
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub prompt_cache_retention: Option<PromptCacheRetention>,
52 #[serde(skip_serializing_if = "Option::is_none")]
53 pub reasoning_effort: Option<ReasoningEffort>,
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub response_format: Option<ChatResponseFormat>,
56 #[serde(skip_serializing_if = "Option::is_none")]
57 pub safety_identifier: Option<String>,
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub seed: Option<i64>,
60 #[serde(skip_serializing_if = "Option::is_none")]
61 pub service_tier: Option<ServiceTier>,
62 #[serde(skip_serializing_if = "Option::is_none")]
63 pub stop: Option<StringOrList>,
64 #[serde(skip_serializing_if = "Option::is_none")]
65 pub store: Option<bool>,
66 #[serde(skip_serializing_if = "Option::is_none")]
67 pub stream: Option<bool>,
68 #[serde(skip_serializing_if = "Option::is_none")]
69 pub stream_options: Option<StreamOptions>,
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub temperature: Option<f64>,
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub tool_choice: Option<ChatToolChoice>,
74 #[serde(skip_serializing_if = "Option::is_none")]
75 pub tools: Option<Vec<ChatTool>>,
76 #[serde(skip_serializing_if = "Option::is_none")]
77 pub top_logprobs: Option<u32>,
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub top_p: Option<f64>,
80 #[serde(skip_serializing_if = "Option::is_none")]
81 pub user: Option<String>,
82 #[serde(skip_serializing_if = "Option::is_none")]
83 pub verbosity: Option<Verbosity>,
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub web_search_options: Option<ChatWebSearchOptions>,
86 #[serde(default, flatten)]
87 pub rest: Rest,
88}
89
90#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
91#[serde(untagged)]
92#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
93pub enum ChatCompletionMessageParam {
94 Developer(ChatDeveloperMessageParam),
95 System(ChatSystemMessageParam),
96 User(ChatUserMessageParam),
97 Assistant(ChatAssistantMessageParam),
98 Tool(ChatToolMessageParam),
99 Function(ChatFunctionMessageParam),
100 Unknown(Value),
101}
102
103macro_rules! text_message {
104 ($name:ident, $role:ident) => {
105 #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
106 pub struct $name {
107 pub role: $role,
108 pub content: ChatTextContent,
109 #[serde(skip_serializing_if = "Option::is_none")]
110 pub name: Option<String>,
111 #[serde(default, flatten)]
112 pub rest: Rest,
113 }
114 };
115}
116
117text_message!(ChatDeveloperMessageParam, ChatDeveloperRole);
118text_message!(ChatSystemMessageParam, ChatSystemRole);
119
120#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
121#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
122pub struct ChatUserMessageParam {
123 pub role: ChatUserRole,
124 pub content: ChatContent,
125 #[serde(skip_serializing_if = "Option::is_none")]
126 pub name: Option<String>,
127 #[serde(default, flatten)]
128 pub rest: Rest,
129}
130
131#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
132#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
133pub struct ChatAssistantMessageParam {
134 pub role: ChatAssistantRole,
135 #[serde(skip_serializing_if = "Option::is_none")]
136 pub content: Option<ChatAssistantContent>,
137 #[serde(skip_serializing_if = "Option::is_none")]
138 pub audio: Option<ChatAudioRef>,
139 #[serde(skip_serializing_if = "Option::is_none")]
140 pub function_call: Option<FunctionCall>,
141 #[serde(skip_serializing_if = "Option::is_none")]
142 pub name: Option<String>,
143 #[serde(skip_serializing_if = "Option::is_none")]
144 pub reasoning_content: Option<String>,
145 #[serde(skip_serializing_if = "Option::is_none")]
146 pub refusal: Option<String>,
147 #[serde(skip_serializing_if = "Option::is_none")]
148 pub tool_calls: Option<Vec<ChatToolCall>>,
149 #[serde(default, flatten)]
150 pub rest: Rest,
151}
152
153#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
154#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
155pub struct ChatToolMessageParam {
156 pub role: ChatToolRole,
157 pub content: ChatTextContent,
158 pub tool_call_id: String,
159 #[serde(default, flatten)]
160 pub rest: Rest,
161}
162
163#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
164#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
165pub struct ChatFunctionMessageParam {
166 pub role: ChatFunctionRole,
167 pub content: Option<String>,
168 pub name: String,
169 #[serde(default, flatten)]
170 pub rest: Rest,
171}
172
173macro_rules! role {
174 ($name:ident, $variant:ident, $wire:literal) => {
175 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
176 #[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
177 pub enum $name {
178 #[serde(rename = $wire)]
179 $variant,
180 }
181 };
182}
183
184role!(ChatDeveloperRole, Developer, "developer");
185role!(ChatSystemRole, System, "system");
186role!(ChatUserRole, User, "user");
187role!(ChatAssistantRole, Assistant, "assistant");
188role!(ChatToolRole, Tool, "tool");
189role!(ChatFunctionRole, Function, "function");
190
191#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
192#[serde(untagged)]
193#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
194pub enum ChatTextContent {
195 Text(String),
196 Parts(Vec<ChatTextContentPart>),
197 Unknown(Value),
198}
199
200#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
201#[serde(untagged)]
202#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
203pub enum ChatTextContentPart {
204 Text(ChatTextPart),
205 Unknown(Value),
206}
207
208#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
209#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
210pub struct ChatTextPart {
211 #[serde(rename = "type")]
212 pub type_: ChatTextPartType,
213 pub text: String,
214 #[serde(skip_serializing_if = "Option::is_none")]
215 pub prompt_cache_breakpoint: Option<PromptCacheBreakpoint>,
216 #[serde(default, flatten)]
217 pub rest: Rest,
218}
219
220role!(ChatTextPartType, Text, "text");
221
222#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
223#[serde(untagged)]
224#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
225pub enum ChatAssistantContent {
226 Text(String),
227 Parts(Vec<ChatAssistantContentPart>),
228 Unknown(Value),
229}
230
231#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
232#[serde(untagged)]
233#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
234pub enum ChatAssistantContentPart {
235 Text(ChatTextPart),
236 Refusal(ChatRefusalPart),
237 Unknown(Value),
238}
239
240#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
241#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
242pub struct ChatRefusalPart {
243 #[serde(rename = "type")]
244 pub type_: ChatRefusalPartType,
245 pub refusal: String,
246 #[serde(skip_serializing_if = "Option::is_none")]
247 pub prompt_cache_breakpoint: Option<PromptCacheBreakpoint>,
248 #[serde(default, flatten)]
249 pub rest: Rest,
250}
251
252role!(ChatRefusalPartType, Refusal, "refusal");
253
254#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
255#[serde(untagged)]
256#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
257pub enum ChatContent {
258 Text(String),
259 Parts(Vec<ChatContentPart>),
260 Unknown(Value),
261}
262
263#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
264#[serde(untagged)]
265#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
266pub enum ChatContentPart {
267 Text(ChatTextPart),
268 ImageUrl(ChatImageUrlPart),
269 InputAudio(ChatInputAudioPart),
270 File(ChatFilePart),
271 Unknown(Value),
272}
273
274macro_rules! input_part {
275 ($name:ident, $type_name:ident, $variant:ident, $wire:literal, $field:ident, $ty:ty) => {
276 #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
277 pub struct $name {
278 #[serde(rename = "type")]
279 pub type_: $type_name,
280 pub $field: $ty,
281 #[serde(skip_serializing_if = "Option::is_none")]
282 pub prompt_cache_breakpoint: Option<PromptCacheBreakpoint>,
283 #[serde(default, flatten)]
284 pub rest: Rest,
285 }
286 role!($type_name, $variant, $wire);
287 };
288}
289
290input_part!(
291 ChatImageUrlPart,
292 ChatImageUrlPartType,
293 ImageUrl,
294 "image_url",
295 image_url,
296 ImageUrl
297);
298input_part!(
299 ChatInputAudioPart,
300 ChatInputAudioPartType,
301 InputAudio,
302 "input_audio",
303 input_audio,
304 InputAudio
305);
306input_part!(
307 ChatFilePart,
308 ChatFilePartType,
309 File,
310 "file",
311 file,
312 ChatFileRef
313);
314
315#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
316#[serde(untagged)]
317#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
318pub enum ChatTool {
319 Function(ChatFunctionTool),
320 Custom(ChatCustomTool),
321 Unknown(Value),
322}
323
324#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
325#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
326pub struct ChatFunctionTool {
327 #[serde(rename = "type")]
328 pub type_: FunctionToolChoiceType,
329 pub function: FunctionDefinition,
330 #[serde(default, flatten)]
331 pub rest: Rest,
332}
333
334#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
335#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
336pub struct ChatCustomTool {
337 #[serde(rename = "type")]
338 pub type_: CustomToolChoiceType,
339 pub custom: CustomToolDefinition,
340 #[serde(default, flatten)]
341 pub rest: Rest,
342}
343
344#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
345#[serde(untagged)]
346#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
347pub enum ChatToolCall {
348 Function(ChatFunctionToolCall),
349 Custom(ChatCustomToolCall),
350 Unknown(Value),
351}
352
353#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
354#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
355pub struct ChatFunctionToolCall {
356 pub id: String,
357 #[serde(rename = "type")]
358 pub type_: FunctionToolChoiceType,
359 pub function: FunctionCall,
360 #[serde(default, flatten)]
361 pub rest: Rest,
362}
363
364#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
365#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
366pub struct ChatCustomToolCall {
367 pub id: String,
368 #[serde(rename = "type")]
369 pub type_: CustomToolChoiceType,
370 pub custom: CustomToolCall,
371 #[serde(default, flatten)]
372 pub rest: Rest,
373}