xai_openapi/
chat.rs

1//! Chat completions API types for `/v1/chat/completions` endpoint.
2
3use serde::{Deserialize, Serialize};
4
5use crate::prelude::*;
6
7use crate::common::{Content, DebugOutput, ResponseFormat, StreamOptions};
8use crate::search::SearchParameters;
9use crate::tools::{Tool, ToolCall, ToolChoice};
10use crate::usage::Usage;
11
12/// The chat request body for `/v1/chat/completions` endpoint.
13#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
14pub struct ChatRequest {
15    /// A list of messages that make up the chat conversation.
16    #[serde(default)]
17    pub messages: Vec<Message>,
18
19    /// Model name for the model to use.
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub model: Option<String>,
22
23    /// What sampling temperature to use, between 0 and 2.
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub temperature: Option<f32>,
26
27    /// An alternative to sampling with temperature, called nucleus sampling.
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub top_p: Option<f32>,
30
31    /// How many chat completion choices to generate for each input message.
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub n: Option<i32>,
34
35    /// If set, partial message deltas will be sent as server-sent events.
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub stream: Option<bool>,
38
39    /// Options for streaming response.
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub stream_options: Option<StreamOptions>,
42
43    /// (Not supported by reasoning models) Up to 4 sequences where the API will stop generating.
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub stop: Option<Vec<String>>,
46
47    /// An upper bound for the number of tokens that can be generated for a completion.
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub max_completion_tokens: Option<i32>,
50
51    /// \[DEPRECATED\] The maximum number of tokens that can be generated.
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub max_tokens: Option<i32>,
54
55    /// (Not supported by `grok-3` and reasoning models) Presence penalty.
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub presence_penalty: Option<f32>,
58
59    /// (Not supported by reasoning models) Frequency penalty.
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub frequency_penalty: Option<f32>,
62
63    /// (Unsupported) A JSON object that maps tokens to an associated bias value.
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub logit_bias: Option<serde_json::Value>,
66
67    /// Whether to return log probabilities of the output tokens.
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub logprobs: Option<bool>,
70
71    /// Number of most likely tokens to return at each token position.
72    #[serde(skip_serializing_if = "Option::is_none")]
73    pub top_logprobs: Option<i32>,
74
75    /// A unique identifier representing your end-user.
76    #[serde(skip_serializing_if = "Option::is_none")]
77    pub user: Option<String>,
78
79    /// An object specifying the format that the model must output.
80    #[serde(skip_serializing_if = "Option::is_none")]
81    pub response_format: Option<ResponseFormat>,
82
83    /// If specified, system will make a best effort to sample deterministically.
84    #[serde(skip_serializing_if = "Option::is_none")]
85    pub seed: Option<i32>,
86
87    /// A list of tools the model may call.
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub tools: Option<Vec<Tool>>,
90
91    /// Controls which (if any) tool is called by the model.
92    #[serde(skip_serializing_if = "Option::is_none")]
93    pub tool_choice: Option<ToolChoice>,
94
95    /// If set to false, the model can perform maximum one tool call.
96    #[serde(skip_serializing_if = "Option::is_none")]
97    pub parallel_tool_calls: Option<bool>,
98
99    /// Set the parameters to be used for searched data.
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub search_parameters: Option<SearchParameters>,
102
103    /// Options to control the web search.
104    #[serde(skip_serializing_if = "Option::is_none")]
105    pub web_search_options: Option<crate::tools::WebSearchOptions>,
106
107    /// Constrains how hard a reasoning model thinks before responding.
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub reasoning_effort: Option<String>,
110
111    /// If set to `true`, the request returns a `request_id` for deferred completion.
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub deferred: Option<bool>,
114
115    /// (Internal) Bootstrap host address for disaggregated prefill/decode.
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub bootstrap_host: Option<String>,
118
119    /// (Internal) Bootstrap room ID for disaggregated prefill/decode.
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub bootstrap_room: Option<i64>,
122}
123
124/// Chat message objects.
125#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
126#[serde(tag = "role", rename_all = "lowercase")]
127pub enum Message {
128    /// System message, usually instructions for the model to respond in a certain way.
129    System {
130        /// System prompt content.
131        content: Content,
132        /// A unique identifier representing your end-user.
133        #[serde(skip_serializing_if = "Option::is_none")]
134        name: Option<String>,
135    },
136    /// User message, typically request from user for the model to answer.
137    User {
138        /// User prompt content.
139        content: Content,
140        /// A unique identifier representing your end-user.
141        #[serde(skip_serializing_if = "Option::is_none")]
142        name: Option<String>,
143    },
144    /// Assistant role message, previous chat messages from the model.
145    Assistant {
146        /// Assistant prompt content.
147        #[serde(skip_serializing_if = "Option::is_none")]
148        content: Option<Content>,
149        /// A unique identifier representing your end-user.
150        #[serde(skip_serializing_if = "Option::is_none")]
151        name: Option<String>,
152        /// Assistant reasoning content.
153        #[serde(skip_serializing_if = "Option::is_none")]
154        reasoning_content: Option<String>,
155        /// An array of tool calls available to the model.
156        #[serde(skip_serializing_if = "Option::is_none")]
157        tool_calls: Option<Vec<ToolCall>>,
158    },
159    /// Tool call role message, used to return function call result to the model.
160    Tool {
161        /// Content of the tool call result.
162        content: Content,
163        /// The ID of the tool call received from assistant message response.
164        #[serde(skip_serializing_if = "Option::is_none")]
165        tool_call_id: Option<String>,
166    },
167    /// Function call role message. Deprecated in favor of `tool`.
168    Function {
169        /// Content of the tool call result.
170        content: Content,
171        /// A unique identifier representing your end-user.
172        #[serde(skip_serializing_if = "Option::is_none")]
173        name: Option<String>,
174    },
175}
176
177impl Default for Message {
178    fn default() -> Self {
179        Message::User {
180            content: Content::default(),
181            name: None,
182        }
183    }
184}
185
186/// The chat response body for `/v1/chat/completions` endpoint.
187#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
188pub struct ChatResponse {
189    /// A unique ID for the chat response.
190    pub id: String,
191
192    /// The object type, which is always `"chat.completion"`.
193    pub object: String,
194
195    /// The chat completion creation time in Unix timestamp.
196    pub created: i64,
197
198    /// Model ID used to create chat completion.
199    pub model: String,
200
201    /// A list of response choices from the model.
202    pub choices: Vec<Choice>,
203
204    /// Token usage information.
205    #[serde(skip_serializing_if = "Option::is_none")]
206    pub usage: Option<Usage>,
207
208    /// System fingerprint, used to indicate xAI system configuration changes.
209    #[serde(skip_serializing_if = "Option::is_none")]
210    pub system_fingerprint: Option<String>,
211
212    /// List of all the external pages used by the model to answer.
213    #[serde(skip_serializing_if = "Option::is_none")]
214    pub citations: Option<Vec<String>>,
215
216    /// Debug output. Only available to trusted testers.
217    #[serde(skip_serializing_if = "Option::is_none")]
218    pub debug_output: Option<DebugOutput>,
219}
220
221/// A response choice from the model.
222#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
223pub struct Choice {
224    /// Index of the choice within the response choices, starting from 0.
225    pub index: i32,
226
227    /// The generated chat completion message.
228    pub message: ChoiceMessage,
229
230    /// Finish reason.
231    #[serde(skip_serializing_if = "Option::is_none")]
232    pub finish_reason: Option<String>,
233
234    /// The log probabilities of each output token.
235    #[serde(skip_serializing_if = "Option::is_none")]
236    pub logprobs: Option<LogProbs>,
237}
238
239/// The generated chat completion message.
240#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
241pub struct ChoiceMessage {
242    /// The role that the message belongs to, the response from model is always `"assistant"`.
243    pub role: String,
244
245    /// The content of the message.
246    #[serde(skip_serializing_if = "Option::is_none")]
247    pub content: Option<String>,
248
249    /// The reasoning trace generated by the model.
250    #[serde(skip_serializing_if = "Option::is_none")]
251    pub reasoning_content: Option<String>,
252
253    /// The reason given by model if unable to generate a response.
254    #[serde(skip_serializing_if = "Option::is_none")]
255    pub refusal: Option<String>,
256
257    /// A list of tool calls asked by model for user to perform.
258    #[serde(skip_serializing_if = "Option::is_none")]
259    pub tool_calls: Option<Vec<ToolCall>>,
260}
261
262/// Streaming chat response chunk.
263#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
264pub struct ChatResponseChunk {
265    /// A unique ID for the chat response chunk.
266    pub id: String,
267
268    /// The object type, which is always `"chat.completion.chunk"`.
269    pub object: String,
270
271    /// The chat completion creation time in Unix timestamp.
272    pub created: i64,
273
274    /// The model ID used to create chat completion.
275    pub model: String,
276
277    /// A list of response choices from the model.
278    pub choices: Vec<ChoiceChunk>,
279
280    /// Token usage information.
281    #[serde(skip_serializing_if = "Option::is_none")]
282    pub usage: Option<Usage>,
283
284    /// System fingerprint, used to indicate xAI system configuration changes.
285    #[serde(skip_serializing_if = "Option::is_none")]
286    pub system_fingerprint: Option<String>,
287
288    /// List of all the external pages used by the model to answer.
289    #[serde(skip_serializing_if = "Option::is_none")]
290    pub citations: Option<Vec<String>>,
291
292    /// Debug output. Only available to trusted testers.
293    #[serde(skip_serializing_if = "Option::is_none")]
294    pub debug_output: Option<DebugOutput>,
295}
296
297/// A streaming response choice chunk.
298#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
299pub struct ChoiceChunk {
300    /// Index of the choice.
301    pub index: i32,
302
303    /// Additional difference (delta) of the result.
304    pub delta: Delta,
305
306    /// Finish reason.
307    #[serde(skip_serializing_if = "Option::is_none")]
308    pub finish_reason: Option<String>,
309
310    /// The log probabilities of each output token.
311    #[serde(skip_serializing_if = "Option::is_none")]
312    pub logprobs: Option<LogProbs>,
313}
314
315/// Delta content in streaming response.
316#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
317pub struct Delta {
318    /// The role of the message.
319    #[serde(skip_serializing_if = "Option::is_none")]
320    pub role: Option<String>,
321
322    /// The content delta.
323    #[serde(skip_serializing_if = "Option::is_none")]
324    pub content: Option<String>,
325
326    /// The reasoning content delta.
327    #[serde(skip_serializing_if = "Option::is_none")]
328    pub reasoning_content: Option<String>,
329
330    /// Tool calls delta.
331    #[serde(skip_serializing_if = "Option::is_none")]
332    pub tool_calls: Option<Vec<ToolCall>>,
333
334    /// Images generated by the model.
335    #[serde(skip_serializing_if = "Option::is_none")]
336    pub images: Option<Vec<String>>,
337}
338
339/// Log probabilities.
340#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
341pub struct LogProbs {
342    /// An array of the log probabilities of each output token returned.
343    #[serde(skip_serializing_if = "Option::is_none")]
344    pub content: Option<Vec<TokenLogProb>>,
345}
346
347/// Token log probability.
348#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
349pub struct TokenLogProb {
350    /// The token.
351    pub token: String,
352
353    /// The log probability of returning this token.
354    pub logprob: f32,
355
356    /// An array of the most likely tokens to return at this token position.
357    pub top_logprobs: Vec<TopLogProb>,
358
359    /// The ASCII encoding of the output character.
360    #[serde(skip_serializing_if = "Option::is_none")]
361    pub bytes: Option<Vec<u32>>,
362}
363
364/// Top log probability.
365#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
366pub struct TopLogProb {
367    /// The token.
368    pub token: String,
369
370    /// The log probability of returning this token.
371    pub logprob: f32,
372
373    /// The ASCII encoding of the output character.
374    #[serde(skip_serializing_if = "Option::is_none")]
375    pub bytes: Option<Vec<u32>>,
376}