xai_openapi/
common.rs

1//! Common types shared across multiple xAI API endpoints.
2
3use serde::{Deserialize, Serialize};
4
5use crate::prelude::*;
6
7/// Content of each chat message.
8#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
9#[serde(untagged)]
10pub enum Content {
11    /// Text prompt.
12    Text(String),
13    /// An array of content parts of different types, such as image, text or text file.
14    Parts(Vec<ContentPart>),
15}
16
17impl Default for Content {
18    fn default() -> Self {
19        Content::Text(String::new())
20    }
21}
22
23impl From<&str> for Content {
24    fn from(s: &str) -> Self {
25        Content::Text(s.to_string())
26    }
27}
28
29impl From<String> for Content {
30    fn from(s: String) -> Self {
31        Content::Text(s)
32    }
33}
34
35/// A part of content in a message.
36#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
37pub struct ContentPart {
38    /// The type of the content part.
39    #[serde(rename = "type")]
40    pub content_type: String,
41
42    /// Text prompt.
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub text: Option<String>,
45
46    /// A public URL of image prompt, only available for vision models.
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub image_url: Option<ImageUrl>,
49
50    /// Specifies the detail level of the image.
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub detail: Option<String>,
53
54    /// File path to a text file to be used as prompt.
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub text_file: Option<String>,
57
58    /// File reference for file attachments (OpenAI-compatible nesting).
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub file: Option<FileRef>,
61}
62
63/// Image URL object of image prompt.
64#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
65pub struct ImageUrl {
66    /// URL of the image.
67    pub url: String,
68
69    /// Specifies the detail level of the image.
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub detail: Option<String>,
72}
73
74/// File reference for file attachments.
75#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
76pub struct FileRef {
77    /// The file ID from the Files API.
78    pub file_id: String,
79}
80
81/// Options available when using streaming response.
82#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
83pub struct StreamOptions {
84    /// Set an additional chunk to be streamed before the `data: [DONE]` message.
85    /// The other chunks will return `null` in `usage` field.
86    pub include_usage: bool,
87}
88
89/// Response format parameter for structured outputs.
90#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
91#[serde(tag = "type", rename_all = "snake_case")]
92pub enum ResponseFormat {
93    /// Specify text response format, always `"text"`.
94    #[default]
95    Text,
96    /// Specify `json_object` response format, always `json_object`.
97    /// Used for backward compatibility. Prefer to use `"json_schema"` instead.
98    JsonObject,
99    /// Specify `json_schema` response format with a given schema.
100    JsonSchema {
101        /// A json schema representing the desired response schema.
102        json_schema: serde_json::Value,
103    },
104}
105
106/// Annotation on text output.
107#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
108pub struct Annotation {
109    /// The type of the annotation. Only supported type currently is `url_citation`.
110    #[serde(rename = "type")]
111    pub annotation_type: String,
112
113    /// The URL of the web resource.
114    pub url: String,
115
116    /// The title of the annotation.
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub title: Option<String>,
119
120    /// The start index of the annotation.
121    #[serde(skip_serializing_if = "Option::is_none")]
122    pub start_index: Option<i32>,
123
124    /// The end index of the annotation.
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub end_index: Option<i32>,
127}
128
129/// Details about why a response is incomplete.
130#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
131pub struct IncompleteDetails {
132    /// The reason why the response is incomplete.
133    pub reason: String,
134}
135
136/// API key information.
137#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
138pub struct ApiKey {
139    /// The redacted API key.
140    pub redacted_api_key: String,
141
142    /// User ID the API key belongs to.
143    pub user_id: String,
144
145    /// The name of the API key specified by user.
146    pub name: String,
147
148    /// Creation time of the API key in Unix timestamp.
149    pub create_time: String,
150
151    /// Last modification time of the API key in Unix timestamp.
152    pub modify_time: String,
153
154    /// User ID of the user who last modified the API key.
155    pub modified_by: String,
156
157    /// The team ID of the team that owns the API key.
158    pub team_id: String,
159
160    /// A list of ACLs authorized with the API key.
161    pub acls: Vec<String>,
162
163    /// ID of the API key.
164    pub api_key_id: String,
165
166    /// Indicates whether the team that owns the API key is blocked.
167    pub team_blocked: bool,
168
169    /// Indicates whether the API key is blocked.
170    pub api_key_blocked: bool,
171
172    /// Indicates whether the API key is disabled.
173    pub api_key_disabled: bool,
174}
175
176/// (Legacy) Anthropic compatible complete request on `/v1/complete` endpoint.
177#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
178pub struct CompleteRequest {
179    /// Model to use for completion.
180    #[serde(skip_serializing_if = "Option::is_none")]
181    pub model: Option<String>,
182
183    /// Prompt for the model to perform completion on.
184    #[serde(skip_serializing_if = "Option::is_none")]
185    pub prompt: Option<String>,
186
187    /// The maximum number of tokens to generate before stopping.
188    #[serde(skip_serializing_if = "Option::is_none")]
189    pub max_tokens_to_sample: Option<i32>,
190
191    /// What sampling temperature to use, between 0 and 2.
192    #[serde(skip_serializing_if = "Option::is_none")]
193    pub temperature: Option<f32>,
194
195    /// An alternative to sampling with temperature, called nucleus sampling.
196    #[serde(skip_serializing_if = "Option::is_none")]
197    pub top_p: Option<f32>,
198
199    /// (Unsupported) When generating next tokens, randomly selecting from the k most likely options.
200    #[serde(skip_serializing_if = "Option::is_none")]
201    pub top_k: Option<i32>,
202
203    /// (Not supported by reasoning models) Up to 4 sequences where the API will stop generating.
204    #[serde(skip_serializing_if = "Option::is_none")]
205    pub stop_sequences: Option<Vec<String>>,
206
207    /// (Unsupported) If set, partial message deltas will be sent.
208    #[serde(skip_serializing_if = "Option::is_none")]
209    pub stream: Option<bool>,
210
211    /// An object describing metadata about the request.
212    #[serde(skip_serializing_if = "Option::is_none")]
213    pub metadata: Option<MessageMetadata>,
214}
215
216/// (Legacy) Anthropic compatible complete response on `/v1/complete` endpoint.
217#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
218pub struct CompleteResponse {
219    /// Completion response object type. This is always `"completion"`.
220    #[serde(rename = "type")]
221    pub response_type: String,
222
223    /// ID of the completion response.
224    pub id: String,
225
226    /// The completion content up to and excluding stop sequences.
227    pub completion: String,
228
229    /// The model that handled the request.
230    pub model: String,
231
232    /// The reason to stop completion.
233    #[serde(skip_serializing_if = "Option::is_none")]
234    pub stop_reason: Option<String>,
235}
236
237/// Message metadata.
238#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
239pub struct MessageMetadata {
240    /// A unique identifier representing your end-user.
241    #[serde(skip_serializing_if = "Option::is_none")]
242    pub user_id: Option<String>,
243}
244
245/// (Legacy) Request for `/v1/completions` endpoint.
246#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
247pub struct SampleRequest {
248    /// Specifies the model to be used for the request.
249    #[serde(skip_serializing_if = "Option::is_none")]
250    pub model: Option<String>,
251
252    /// Input for generating completions.
253    #[serde(skip_serializing_if = "Option::is_none")]
254    pub prompt: Option<SampleContent>,
255
256    /// Limits the number of tokens that can be produced in the output.
257    #[serde(skip_serializing_if = "Option::is_none")]
258    pub max_tokens: Option<i32>,
259
260    /// What sampling temperature to use, between 0 and 2.
261    #[serde(skip_serializing_if = "Option::is_none")]
262    pub temperature: Option<f32>,
263
264    /// An alternative to sampling with temperature, called nucleus sampling.
265    #[serde(skip_serializing_if = "Option::is_none")]
266    pub top_p: Option<f32>,
267
268    /// Determines how many completion sequences to produce for each prompt.
269    #[serde(skip_serializing_if = "Option::is_none")]
270    pub n: Option<i32>,
271
272    /// Whether to stream back partial progress.
273    #[serde(skip_serializing_if = "Option::is_none")]
274    pub stream: Option<bool>,
275
276    /// Options for streaming response.
277    #[serde(skip_serializing_if = "Option::is_none")]
278    pub stream_options: Option<StreamOptions>,
279
280    /// (Not supported by reasoning models) Up to 4 sequences where the API will stop generating.
281    #[serde(skip_serializing_if = "Option::is_none")]
282    pub stop: Option<Vec<String>>,
283
284    /// (Not supported by `grok-3` and reasoning models) Presence penalty.
285    #[serde(skip_serializing_if = "Option::is_none")]
286    pub presence_penalty: Option<f32>,
287
288    /// (Unsupported) Frequency penalty.
289    #[serde(skip_serializing_if = "Option::is_none")]
290    pub frequency_penalty: Option<f32>,
291
292    /// Option to include the original prompt in the response.
293    #[serde(skip_serializing_if = "Option::is_none")]
294    pub echo: Option<bool>,
295
296    /// Include the log probabilities on the most likely output tokens.
297    #[serde(skip_serializing_if = "Option::is_none")]
298    pub logprobs: Option<bool>,
299
300    /// (Unsupported) Generates multiple completions internally.
301    #[serde(skip_serializing_if = "Option::is_none")]
302    pub best_of: Option<i32>,
303
304    /// (Unsupported) Logit bias.
305    #[serde(skip_serializing_if = "Option::is_none")]
306    pub logit_bias: Option<serde_json::Value>,
307
308    /// If specified, system will make a best effort to sample deterministically.
309    #[serde(skip_serializing_if = "Option::is_none")]
310    pub seed: Option<i32>,
311
312    /// (Unsupported) Optional string to append after the generated text.
313    #[serde(skip_serializing_if = "Option::is_none")]
314    pub suffix: Option<String>,
315
316    /// A unique identifier representing your end-user.
317    #[serde(skip_serializing_if = "Option::is_none")]
318    pub user: Option<String>,
319}
320
321/// Sample content input.
322#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
323#[serde(untagged)]
324pub enum SampleContent {
325    /// Text prompt.
326    Text(String),
327    /// An array of strings, a token list, or an array of token lists.
328    Array(Vec<String>),
329}
330
331impl Default for SampleContent {
332    fn default() -> Self {
333        SampleContent::Text(String::new())
334    }
335}
336
337/// (Legacy) Response for `/v1/completions` endpoint.
338#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
339pub struct SampleResponse {
340    /// ID of the request.
341    pub id: String,
342
343    /// Object type of the response. This is always `"text_completion"`.
344    pub object: String,
345
346    /// The chat completion creation time in Unix timestamp.
347    pub created: i64,
348
349    /// Model used.
350    pub model: String,
351
352    /// A list of response choices from the model.
353    pub choices: Vec<SampleChoice>,
354
355    /// System fingerprint, used to indicate xAI system configuration changes.
356    #[serde(skip_serializing_if = "Option::is_none")]
357    pub system_fingerprint: Option<String>,
358
359    /// Token usage information.
360    #[serde(skip_serializing_if = "Option::is_none")]
361    pub usage: Option<crate::usage::Usage>,
362}
363
364/// A choice in a sample response.
365#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
366pub struct SampleChoice {
367    /// Index of the choice.
368    pub index: i32,
369
370    /// Text response.
371    pub text: String,
372
373    /// Finish reason.
374    pub finish_reason: String,
375}
376
377/// A unique request ID for deferred chat response.
378#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
379pub struct StartDeferredChatResponse {
380    /// A unique request ID for the chat response.
381    pub request_id: String,
382}
383
384/// `DocumentsSource` defines the source of documents to search over.
385#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
386pub struct DocumentsSource {
387    /// The collection IDs to search in.
388    pub collection_ids: Vec<String>,
389}
390
391/// Deprecated: Metric now comes from collection creation.
392#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
393pub enum RankingMetric {
394    #[default]
395    #[serde(rename = "RANKING_METRIC_UNKNOWN")]
396    Unknown,
397    #[serde(rename = "RANKING_METRIC_L2_DISTANCE")]
398    L2Distance,
399    #[serde(rename = "RANKING_METRIC_COSINE_SIMILARITY")]
400    CosineSimilarity,
401}
402
403/// System message content.
404#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
405#[serde(untagged)]
406pub enum SystemMessageContent {
407    /// Text content of system prompt.
408    Text(String),
409    /// An array of system prompt parts.
410    Parts(Vec<SystemMessagePart>),
411}
412
413impl Default for SystemMessageContent {
414    fn default() -> Self {
415        SystemMessageContent::Text(String::new())
416    }
417}
418
419/// A part of system message content.
420#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
421pub struct SystemMessagePart {
422    /// Type of the object. This is always `"text"`.
423    #[serde(rename = "type")]
424    pub part_type: String,
425
426    /// System prompt text.
427    pub text: String,
428
429    /// (Unsupported) Cache control.
430    #[serde(skip_serializing_if = "Option::is_none")]
431    pub cache_control: Option<serde_json::Value>,
432}
433
434/// Debug output. Only available to trusted testers.
435#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
436pub struct DebugOutput {
437    /// Number of attempts made to the model.
438    pub attempts: i32,
439
440    /// The request received from the user.
441    pub request: String,
442
443    /// The prompt sent to the model in text form.
444    pub prompt: String,
445
446    /// JSON-serialized request sent to the inference engine.
447    pub engine_request: String,
448
449    /// The response(s) received from the model.
450    pub responses: Vec<String>,
451
452    /// The individual chunks returned from the pipeline of samplers.
453    pub chunks: Vec<String>,
454
455    /// Number of cache reads.
456    pub cache_read_count: i32,
457
458    /// Size of cache read.
459    pub cache_read_input_bytes: i64,
460
461    /// Number of cache writes.
462    pub cache_write_count: i32,
463
464    /// Size of cache write.
465    pub cache_write_input_bytes: i64,
466
467    /// The load balancer address.
468    pub lb_address: String,
469
470    /// The tag of the actual engines sitting behind the GTP address.
471    pub sampler_tag: String,
472
473    /// The underlying checkpoint mount path for the sampler that served this request.
474    pub sampler_checkpoint_mount: String,
475}