Skip to main content

gproxy_protocol/openai/generate_content/chat/
request.rs

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}