Skip to main content

gproxy_protocol/wire/openai/chat/
response.rs

1use super::content::{FunctionCall, MessageToolCall};
2use super::content::{present_nullable, required_nullable};
3use crate::{Rest, WireResponse};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
7#[serde(rename_all = "snake_case")]
8#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
9#[derive(gproxy_protocol_macros::DeclaredFields)]
10pub struct GenerateContentResponseBody {
11    pub id: String,
12    pub choices: Vec<Choice>,
13    pub created: i64,
14    pub model: String,
15    pub object: CompletionObject,
16    #[serde(
17        default,
18        deserialize_with = "present_nullable",
19        skip_serializing_if = "Option::is_none"
20    )]
21    pub service_tier: Option<Option<ResponseServiceTier>>,
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub system_fingerprint: Option<String>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub usage: Option<Usage>,
26    #[serde(
27        default,
28        deserialize_with = "present_nullable",
29        skip_serializing_if = "Option::is_none"
30    )]
31    pub moderation: Option<Option<ModerationResponse>>,
32    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
33    pub rest: Rest,
34}
35pub type GenerateContentResponse = WireResponse<GenerateContentResponseBody>;
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
37#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
38#[derive(gproxy_protocol_macros::DeclaredFields)]
39pub enum CompletionObject {
40    #[serde(rename = "chat.completion")]
41    ChatCompletion,
42}
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
44#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
45#[derive(gproxy_protocol_macros::DeclaredFields)]
46pub enum ResponseServiceTier {
47    #[serde(rename = "auto")]
48    Auto,
49    #[serde(rename = "default")]
50    Default,
51    #[serde(rename = "flex")]
52    Flex,
53    #[serde(rename = "scale")]
54    Scale,
55    #[serde(rename = "priority")]
56    Priority,
57    #[serde(rename = "fast")]
58    Fast,
59    #[serde(rename = "ultrafast")]
60    Ultrafast,
61}
62#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
63#[serde(rename_all = "snake_case")]
64#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
65#[derive(gproxy_protocol_macros::DeclaredFields)]
66pub struct Choice {
67    pub finish_reason: FinishReason,
68    pub index: i64,
69    #[wire(required)]
70    #[serde(default, deserialize_with = "required_nullable")]
71    pub logprobs: Option<Logprobs>,
72    pub message: ResponseMessage,
73    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
74    pub rest: Rest,
75}
76#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
77#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
78#[derive(gproxy_protocol_macros::DeclaredFields)]
79pub enum FinishReason {
80    #[serde(rename = "stop")]
81    Stop,
82    #[serde(rename = "length")]
83    Length,
84    #[serde(rename = "tool_calls")]
85    ToolCalls,
86    #[serde(rename = "content_filter")]
87    ContentFilter,
88    #[serde(rename = "function_call")]
89    FunctionCall,
90}
91#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
92#[serde(rename_all = "snake_case")]
93#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
94#[derive(gproxy_protocol_macros::DeclaredFields)]
95pub struct ResponseMessage {
96    #[serde(
97        default,
98        deserialize_with = "present_nullable",
99        skip_serializing_if = "Option::is_none"
100    )]
101    pub reasoning_details: Option<Option<Vec<super::reasoning::ReasoningDetail>>>,
102    /// Plain-text reasoning returned by compatible providers (for example DeepSeek).
103    #[serde(
104        default,
105        deserialize_with = "present_nullable",
106        skip_serializing_if = "Option::is_none"
107    )]
108    pub reasoning_content: Option<Option<String>>,
109    /// Alternative compatible-provider spelling. Kept separately on the wire.
110    #[serde(
111        default,
112        deserialize_with = "present_nullable",
113        skip_serializing_if = "Option::is_none"
114    )]
115    pub reasoning: Option<Option<String>>,
116    #[wire(required)]
117    #[serde(default, deserialize_with = "required_nullable")]
118    pub content: Option<String>,
119    #[wire(required)]
120    #[serde(default, deserialize_with = "required_nullable")]
121    pub refusal: Option<String>,
122    pub role: ResponseRole,
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub annotations: Option<Vec<Annotation>>,
125    #[serde(
126        default,
127        deserialize_with = "present_nullable",
128        skip_serializing_if = "Option::is_none"
129    )]
130    pub audio: Option<Option<ResponseAudio>>,
131    #[serde(skip_serializing_if = "Option::is_none")]
132    pub function_call: Option<FunctionCall>,
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub tool_calls: Option<Vec<MessageToolCall>>,
135    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
136    pub rest: Rest,
137}
138#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
139#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
140#[derive(gproxy_protocol_macros::DeclaredFields)]
141pub enum ResponseRole {
142    #[serde(rename = "assistant")]
143    Assistant,
144}
145#[derive(
146    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
147)]
148#[serde(rename_all = "snake_case")]
149#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
150#[derive(gproxy_protocol_macros::DeclaredFields)]
151pub struct ResponseAudio {
152    pub id: String,
153    pub data: String,
154    pub expires_at: i64,
155    pub transcript: String,
156    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
157    pub rest: Rest,
158}
159#[derive(
160    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
161)]
162#[serde(rename_all = "snake_case")]
163#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
164#[derive(gproxy_protocol_macros::DeclaredFields)]
165pub struct Annotation {
166    #[serde(rename = "type")]
167    pub type_: AnnotationType,
168    pub url_citation: UrlCitation,
169    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
170    pub rest: Rest,
171}
172#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
173#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
174#[derive(gproxy_protocol_macros::DeclaredFields)]
175pub enum AnnotationType {
176    #[serde(rename = "url_citation")]
177    UrlCitation,
178}
179#[derive(
180    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
181)]
182#[serde(rename_all = "snake_case")]
183#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
184#[derive(gproxy_protocol_macros::DeclaredFields)]
185pub struct UrlCitation {
186    pub end_index: i64,
187    pub start_index: i64,
188    pub title: String,
189    pub url: String,
190    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
191    pub rest: Rest,
192}
193#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
194#[serde(rename_all = "snake_case")]
195#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
196#[derive(gproxy_protocol_macros::DeclaredFields)]
197pub struct Logprobs {
198    #[wire(required)]
199    #[serde(deserialize_with = "required_nullable")]
200    pub content: Option<Vec<TokenLogprob>>,
201    #[wire(required)]
202    #[serde(deserialize_with = "required_nullable")]
203    pub refusal: Option<Vec<TokenLogprob>>,
204    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
205    pub rest: Rest,
206}
207#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
208#[serde(rename_all = "snake_case")]
209#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
210#[derive(gproxy_protocol_macros::DeclaredFields)]
211pub struct TokenLogprob {
212    pub token: String,
213    #[wire(required)]
214    #[serde(deserialize_with = "required_nullable")]
215    pub bytes: Option<Vec<i64>>,
216    pub logprob: f64,
217    pub top_logprobs: Vec<TokenLogprobTop>,
218    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
219    pub rest: Rest,
220}
221#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
222#[serde(rename_all = "snake_case")]
223#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
224#[derive(gproxy_protocol_macros::DeclaredFields)]
225pub struct TokenLogprobTop {
226    pub token: String,
227    #[wire(required)]
228    #[serde(deserialize_with = "required_nullable")]
229    pub bytes: Option<Vec<i64>>,
230    pub logprob: f64,
231    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
232    pub rest: Rest,
233}
234#[derive(
235    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
236)]
237#[serde(rename_all = "snake_case")]
238#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
239#[derive(gproxy_protocol_macros::DeclaredFields)]
240pub struct Usage {
241    pub prompt_tokens: i64,
242    pub completion_tokens: i64,
243    pub total_tokens: i64,
244    #[serde(skip_serializing_if = "Option::is_none")]
245    pub prompt_tokens_details: Option<PromptTokensDetails>,
246    #[serde(skip_serializing_if = "Option::is_none")]
247    pub completion_tokens_details: Option<CompletionTokensDetails>,
248    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
249    pub rest: Rest,
250}
251#[derive(
252    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
253)]
254#[serde(rename_all = "snake_case")]
255#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
256#[derive(gproxy_protocol_macros::DeclaredFields)]
257pub struct PromptTokensDetails {
258    #[serde(skip_serializing_if = "Option::is_none")]
259    pub cache_write_tokens: Option<i64>,
260
261    #[serde(skip_serializing_if = "Option::is_none")]
262    pub cached_tokens: Option<i64>,
263    #[serde(skip_serializing_if = "Option::is_none")]
264    pub audio_tokens: Option<i64>,
265    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
266    pub rest: Rest,
267}
268#[derive(
269    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
270)]
271#[serde(rename_all = "snake_case")]
272#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
273#[derive(gproxy_protocol_macros::DeclaredFields)]
274pub struct CompletionTokensDetails {
275    #[serde(skip_serializing_if = "Option::is_none")]
276    pub accepted_prediction_tokens: Option<i64>,
277    #[serde(skip_serializing_if = "Option::is_none")]
278    pub rejected_prediction_tokens: Option<i64>,
279
280    #[serde(skip_serializing_if = "Option::is_none")]
281    pub reasoning_tokens: Option<i64>,
282    #[serde(skip_serializing_if = "Option::is_none")]
283    pub audio_tokens: Option<i64>,
284    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
285    pub rest: Rest,
286}
287#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
288#[serde(rename_all = "snake_case")]
289#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
290#[derive(gproxy_protocol_macros::DeclaredFields)]
291pub struct ModerationResponse {
292    pub input: ModerationResultOrError,
293    pub output: ModerationResultOrError,
294    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
295    pub rest: Rest,
296}
297#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
298#[serde(untagged)]
299#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
300#[derive(gproxy_protocol_macros::DeclaredFields)]
301pub enum ModerationResultOrError {
302    Result(ModerationResult),
303    Error(ModerationError),
304}
305#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
306#[serde(rename_all = "snake_case")]
307#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
308#[derive(gproxy_protocol_macros::DeclaredFields)]
309pub struct ModerationResult {
310    pub model: String,
311    pub results: Vec<ModerationResultItem>,
312    #[serde(rename = "type")]
313    pub type_: ModerationResultType,
314    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
315    pub rest: Rest,
316}
317#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
318#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
319#[derive(gproxy_protocol_macros::DeclaredFields)]
320pub enum ModerationResultType {
321    #[serde(rename = "moderation_results")]
322    ModerationResults,
323}
324#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
325#[serde(rename_all = "snake_case")]
326#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
327#[derive(gproxy_protocol_macros::DeclaredFields)]
328pub struct ModerationResultItem {
329    pub categories: std::collections::BTreeMap<String, bool>,
330    pub category_applied_input_types: std::collections::BTreeMap<String, Vec<ModerationInputType>>,
331    pub category_scores: std::collections::BTreeMap<String, f64>,
332    pub flagged: bool,
333    pub model: String,
334    #[serde(rename = "type")]
335    pub type_: ModerationItemType,
336    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
337    pub rest: Rest,
338}
339#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
340#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
341#[derive(gproxy_protocol_macros::DeclaredFields)]
342pub enum ModerationInputType {
343    #[serde(rename = "text")]
344    Text,
345    #[serde(rename = "image")]
346    Image,
347}
348#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
349#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
350#[derive(gproxy_protocol_macros::DeclaredFields)]
351pub enum ModerationItemType {
352    #[serde(rename = "moderation_result")]
353    ModerationResult,
354}
355#[derive(
356    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
357)]
358#[serde(rename_all = "snake_case")]
359#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
360#[derive(gproxy_protocol_macros::DeclaredFields)]
361pub struct ModerationError {
362    pub code: String,
363    pub message: String,
364    #[serde(rename = "type")]
365    pub type_: ModerationErrorType,
366    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
367    pub rest: Rest,
368}
369#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
370#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
371#[derive(gproxy_protocol_macros::DeclaredFields)]
372pub enum ModerationErrorType {
373    #[serde(rename = "error")]
374    Error,
375}