Skip to main content

async_openai/types/
decisions.rs

1use crate::error::OpenAIError;
2use derive_builder::Builder;
3use serde::{Deserialize, Serialize};
4
5pub use crate::types::shared::{
6    ImageDetail as ImageDetailParam, MessagePhase as MessagePhaseParam,
7};
8pub use crate::types::shared::{InputTokenDetails, OutputTokenDetails, ResponseUsage};
9
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
11pub struct DecisionResponse {
12    /// The model used.
13    pub model: String,
14    /// Answers in question order. Any question can return a refusal instead of an answer; other questions can still receive answers. A refusal has `type: "refusal"` and the question's `name`, or `null` if it was unnamed.
15    pub answers: Vec<AnswerResource>,
16    /// Token usage for the request.
17    pub usage: ResponseUsage,
18}
19
20/// A completed question always includes its name, including null when unnamed.
21#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
22#[serde(tag = "type", rename_all = "snake_case")]
23pub enum AnswerResource {
24    Predicate(AnswerResourcePredicate),
25    Choice(AnswerResourceChoice),
26    Score(AnswerResourceScore),
27    Refusal(AnswerResourceRefusal),
28}
29
30/// The model declined to answer this question. Other questions in the same request can still receive answers.
31#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
32pub struct AnswerResourceRefusal {
33    pub name: Option<String>,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
37pub struct AnswerResourceScore {
38    pub name: Option<String>,
39    pub score: f64,
40    pub probabilities: Vec<ScoreProbabilityResource>,
41    pub confidence: f64,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
45pub struct ScoreProbabilityResource {
46    pub value: i64,
47    pub label: String,
48    pub probability: f64,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
52pub struct AnswerResourceChoice {
53    pub name: Option<String>,
54    pub choice: ChoiceValueResource,
55    pub probabilities: Vec<ChoiceProbabilityResource>,
56    pub confidence: f64,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
60pub struct ChoiceProbabilityResource {
61    pub value: ChoiceValueResource,
62    pub probability: f64,
63}
64
65/// Choice values are typed: a string and a boolean with the same text are distinct.
66#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
67#[serde(untagged)]
68pub enum ChoiceValueResource {
69    Text(String),
70    Boolean(bool),
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
74pub struct AnswerResourcePredicate {
75    pub name: Option<String>,
76    pub probability: f64,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default, Builder)]
80#[builder(
81    name = "DecisionRequestArgs",
82    pattern = "mutable",
83    setter(into, strip_option),
84    default
85)]
86#[builder(build_fn(error = "OpenAIError"))]
87// Required input has no schema default; optional builder fields store Option directly.
88pub struct DecisionRequest {
89    /// The model to use. Only `gpt-6-luna` is supported.
90    pub model: String,
91    pub input: DecisionInput,
92    /// Ask 1–400 questions about the input. Each question can be a predicate, choice, or score. Answers come back in the same order.
93    pub questions: Vec<QuestionParam>,
94    /// Opaque caller-provided end-user identifier, scoped by the verified org. Match Responses' limit; this is never the authenticated user identity.
95    #[serde(skip_serializing_if = "Option::is_none")]
96    pub safety_identifier: Option<String>,
97    /// Partition prompt cache reuse by caller-provided key.
98    #[serde(skip_serializing_if = "Option::is_none")]
99    pub prompt_cache_key: Option<String>,
100    /// Options for prompt caching. Supported for `gpt-5.6` and later models. By default, OpenAI automatically chooses one implicit cache breakpoint. You can add explicit breakpoints to content blocks with `prompt_cache_breakpoint`. Each request can write up to four breakpoints. For cache matching, OpenAI considers up to the latest 80 breakpoints in the conversation, without a content-block lookback limit. Set `mode` to `explicit` to disable the implicit breakpoint. The `ttl` defaults to `30m`, which is currently the only supported value. See the [prompt caching guide](https://developers.openai.com/api/docs/guides/prompt-caching) for current details.
101    #[serde(skip_serializing_if = "Option::is_none")]
102    pub prompt_cache_options: Option<DecisionRequestPromptCacheOptions>,
103}
104
105/// Options for prompt caching. Supported for `gpt-5.6` and later models. By default, OpenAI automatically chooses one implicit cache breakpoint. You can add explicit breakpoints to content blocks with `prompt_cache_breakpoint`. Each request can write up to four breakpoints. For cache matching, OpenAI considers up to the latest 80 breakpoints in the conversation, without a content-block lookback limit. Set `mode` to `explicit` to disable the implicit breakpoint. The `ttl` defaults to `30m`, which is currently the only supported value. See the [prompt caching guide](https://developers.openai.com/api/docs/guides/prompt-caching) for current details.
106#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
107pub struct DecisionRequestPromptCacheOptions {
108    /// The minimum lifetime applied to every implicit and explicit cache breakpoint written by the request. Defaults to `30m`, which is currently the only supported value. The backend may retain cache entries for longer.
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub ttl: Option<DecisionRequestPromptCacheOptionsTtl>,
111    /// Controls whether OpenAI automatically creates an implicit cache breakpoint. Defaults to `implicit`. With `implicit`, OpenAI creates one implicit breakpoint and writes up to the latest three explicit breakpoints in the request. With `explicit`, OpenAI does not create an implicit breakpoint and writes up to the latest four explicit breakpoints. If there are no explicit breakpoints, the request does not use prompt caching.
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub mode: Option<DecisionRequestPromptCacheOptionsMode>,
114}
115
116/// Controls whether OpenAI automatically creates an implicit cache breakpoint. Defaults to `implicit`. With `implicit`, OpenAI creates one implicit breakpoint and writes up to the latest three explicit breakpoints in the request. With `explicit`, OpenAI does not create an implicit breakpoint and writes up to the latest four explicit breakpoints. If there are no explicit breakpoints, the request does not use prompt caching.
117#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
118#[serde(rename_all = "snake_case")]
119pub enum DecisionRequestPromptCacheOptionsMode {
120    Implicit,
121    Explicit,
122}
123
124/// The minimum lifetime applied to every implicit and explicit cache breakpoint written by the request. Defaults to `30m`, which is currently the only supported value. The backend may retain cache entries for longer.
125#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
126pub enum DecisionRequestPromptCacheOptionsTtl {
127    #[serde(rename = "30m")]
128    #[default]
129    Value30m,
130}
131
132/// A question about the request's input, with an optional correlation name.
133#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
134#[serde(tag = "type", rename_all = "snake_case")]
135pub enum QuestionParam {
136    Predicate(QuestionParamPredicate),
137    Choice(QuestionParamChoice),
138    Score(QuestionParamScore),
139}
140
141/// Rate the input against the supplied ordered levels.
142#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
143pub struct QuestionParamScore {
144    #[serde(skip_serializing_if = "Option::is_none")]
145    pub name: Option<String>,
146    pub instructions: QuestionParamInstructions,
147    pub levels: Vec<ScoreLevelParam>,
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
151pub struct ScoreLevelParam {
152    pub label: String,
153    #[serde(skip_serializing_if = "Option::is_none")]
154    pub description: Option<String>,
155}
156
157/// Instructions for a predicate, choice, or score question, as text or an ordered list of content parts.
158#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
159#[serde(untagged)]
160pub enum QuestionParamInstructions {
161    Text(String),
162    Items(Vec<DecisionQuestionInputPart>),
163}
164
165/// A text, image, or JSON content part in a question instruction.
166#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
167#[serde(tag = "type", rename_all = "snake_case")]
168pub enum DecisionQuestionInputPart {
169    InputText(DecisionQuestionInputText),
170    InputImage(DecisionQuestionInputImage),
171    InputJson(DecisionInputJson),
172}
173
174/// A JSON object or an array of objects rendered as text. Nested values may be any JSON value. Limited to 32 container levels, 10,000 values, and 256 KiB of compact UTF-8 JSON.
175#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
176pub struct DecisionInputJson {
177    pub data: DecisionInputJsonData,
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
181#[serde(untagged)]
182pub enum DecisionInputJsonData {
183    Item(serde_json::Value),
184    Items(Vec<serde_json::Value>),
185}
186
187/// An image provided as a base64 data URL or a publicly accessible HTTP(S) URL. File IDs are not supported.
188#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
189pub struct DecisionQuestionInputImage {
190    /// A base64-encoded image in a data URL or a publicly accessible HTTP(S) image URL.
191    pub image_url: String,
192    /// The image detail level, using the selected model's image profile. Defaults to auto.
193    #[serde(skip_serializing_if = "Option::is_none")]
194    pub detail: Option<ImageDetailParam>,
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
198pub struct DecisionQuestionInputText {
199    pub text: String,
200}
201
202/// Choose from the supplied options based on the input.
203#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
204pub struct QuestionParamChoice {
205    #[serde(skip_serializing_if = "Option::is_none")]
206    pub name: Option<String>,
207    pub instructions: QuestionParamInstructions,
208    /// Provide between 2 and 255 choices. Each choice must be unique.
209    pub choices: Vec<ChoiceOptionParam>,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
213pub struct ChoiceOptionParam {
214    pub value: ChoiceValueParam,
215    #[serde(skip_serializing_if = "Option::is_none")]
216    pub description: Option<String>,
217}
218
219/// Choice values are typed: a string and a boolean with the same text are distinct.
220#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
221#[serde(untagged)]
222pub enum ChoiceValueParam {
223    Text(String),
224    Boolean(bool),
225}
226
227/// Estimate how likely it is that a statement about the input is true.
228#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
229pub struct QuestionParamPredicate {
230    #[serde(skip_serializing_if = "Option::is_none")]
231    pub name: Option<String>,
232    pub instructions: QuestionParamInstructions,
233}
234
235/// The input to evaluate for every question. Provide a text string or an ordered array of messages, function calls and outputs, or custom tool calls and outputs. Each tool output must identify a matching call by call ID.
236#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
237#[serde(untagged)]
238pub enum DecisionInput {
239    Text(String),
240    Items(Vec<DecisionInputItem>),
241}
242
243#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
244#[serde(tag = "type", rename_all = "snake_case")]
245pub enum DecisionInputItem {
246    Message(DecisionInputMessage),
247    FunctionCall(DecisionInputFunctionCall),
248    FunctionCallOutput(DecisionInputFunctionCallOutput),
249    CustomToolCall(DecisionInputCustomToolCall),
250    CustomToolCallOutput(DecisionInputCustomToolCallOutput),
251}
252
253#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
254pub struct DecisionInputCustomToolCallOutput {
255    #[serde(skip_serializing_if = "Option::is_none")]
256    pub id: Option<String>,
257    pub call_id: String,
258    pub output: DecisionInputToolOutputContent,
259    #[serde(skip_serializing_if = "Option::is_none")]
260    pub status: Option<FunctionCallStatusParam>,
261}
262
263#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
264#[serde(rename_all = "snake_case")]
265pub enum FunctionCallStatusParam {
266    InProgress,
267    Completed,
268    Incomplete,
269}
270
271/// Text evidence or an ordered list of text and image parts.
272#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
273#[serde(untagged)]
274pub enum DecisionInputToolOutputContent {
275    Text(String),
276    DecisionInputToolOutputContentParts(DecisionInputToolOutputContentParts),
277}
278
279pub type DecisionInputToolOutputContentParts = Vec<DecisionInputToolOutputContentPart>;
280
281#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
282#[serde(tag = "type", rename_all = "snake_case")]
283pub enum DecisionInputToolOutputContentPart {
284    InputText(DecisionInputText),
285    InputImage(DecisionInputImage),
286}
287
288/// An image provided as a base64 data URL or a publicly accessible HTTP(S) URL. File IDs are not supported.
289#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
290pub struct DecisionInputImage {
291    /// A base64-encoded image in a data URL or a publicly accessible HTTP(S) image URL.
292    pub image_url: String,
293    /// The image detail level, using the selected model's image profile. Defaults to auto.
294    #[serde(skip_serializing_if = "Option::is_none")]
295    pub detail: Option<ImageDetailParam>,
296    /// Marks the exact end of a reusable prompt prefix. The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`; the boundary is not rounded to a token block.
297    #[serde(skip_serializing_if = "Option::is_none")]
298    pub prompt_cache_breakpoint: Option<PromptCacheBreakpoint>,
299}
300
301/// Marks the exact end of a reusable prompt prefix. The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`; the boundary is not rounded to a token block.
302#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
303pub struct PromptCacheBreakpoint {
304    /// The breakpoint mode. Always `explicit`.
305    pub mode: PromptCacheBreakpointMode,
306}
307
308/// The breakpoint mode. Always `explicit`.
309#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
310#[serde(rename_all = "snake_case")]
311pub enum PromptCacheBreakpointMode {
312    #[default]
313    Explicit,
314}
315
316#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
317pub struct DecisionInputText {
318    pub text: String,
319    /// Marks the exact end of a reusable prompt prefix. The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`; the boundary is not rounded to a token block.
320    #[serde(skip_serializing_if = "Option::is_none")]
321    pub prompt_cache_breakpoint: Option<PromptCacheBreakpoint>,
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
325pub struct DecisionInputCustomToolCall {
326    #[serde(skip_serializing_if = "Option::is_none")]
327    pub id: Option<String>,
328    pub call_id: String,
329    #[serde(skip_serializing_if = "Option::is_none")]
330    pub namespace: Option<String>,
331    pub name: String,
332    pub input: String,
333    #[serde(skip_serializing_if = "Option::is_none")]
334    pub status: Option<FunctionCallStatusParam>,
335}
336
337#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
338pub struct DecisionInputFunctionCallOutput {
339    #[serde(skip_serializing_if = "Option::is_none")]
340    pub id: Option<String>,
341    pub call_id: String,
342    pub output: DecisionInputToolOutputContent,
343    #[serde(skip_serializing_if = "Option::is_none")]
344    pub status: Option<FunctionCallStatusParam>,
345}
346
347#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
348pub struct DecisionInputFunctionCall {
349    #[serde(skip_serializing_if = "Option::is_none")]
350    pub id: Option<String>,
351    pub call_id: String,
352    #[serde(skip_serializing_if = "Option::is_none")]
353    pub namespace: Option<String>,
354    pub name: String,
355    pub arguments: String,
356    #[serde(skip_serializing_if = "Option::is_none")]
357    pub status: Option<FunctionCallStatusParam>,
358}
359
360#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
361#[serde(tag = "role", rename_all = "snake_case")]
362pub enum DecisionInputMessage {
363    User(DecisionInputUserMessage),
364    Developer(DecisionInputDeveloperMessage),
365    System(DecisionInputSystemMessage),
366    Assistant(DecisionInputAssistantMessage),
367}
368
369/// An assistant message containing output text or refusals.
370#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
371pub struct DecisionInputAssistantMessage {
372    pub content: DecisionInputAssistantContent,
373    /// The phase of an assistant message.
374    #[serde(skip_serializing_if = "Option::is_none")]
375    pub phase: Option<MessagePhaseParam>,
376}
377
378/// A text string or an ordered list of output text and refusal parts.
379#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
380#[serde(untagged)]
381pub enum DecisionInputAssistantContent {
382    Text(String),
383    DecisionInputAssistantContentParts(DecisionInputAssistantContentParts),
384}
385
386pub type DecisionInputAssistantContentParts = Vec<DecisionInputAssistantContentPart>;
387
388#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
389#[serde(tag = "type", rename_all = "snake_case")]
390pub enum DecisionInputAssistantContentPart {
391    OutputText(DecisionInputOutputText),
392    Refusal(DecisionInputRefusal),
393}
394
395#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
396pub struct DecisionInputRefusal {
397    pub refusal: String,
398}
399
400#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
401pub struct DecisionInputOutputText {
402    pub text: String,
403}
404
405/// A system message containing input text.
406#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
407pub struct DecisionInputSystemMessage {
408    pub content: DecisionInputDeveloperContent,
409}
410
411/// A text string or an ordered list of input text parts.
412#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
413#[serde(untagged)]
414pub enum DecisionInputDeveloperContent {
415    Text(String),
416    DecisionInputDeveloperContentParts(DecisionInputDeveloperContentParts),
417}
418
419#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
420#[serde(tag = "type", rename_all = "snake_case")]
421pub enum DecisionInputDeveloperContentPart {
422    InputText(DecisionInputText),
423}
424pub type DecisionInputDeveloperContentParts = Vec<DecisionInputDeveloperContentPart>;
425
426/// A developer message containing input text.
427#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
428pub struct DecisionInputDeveloperMessage {
429    pub content: DecisionInputDeveloperContent,
430}
431
432/// A user message containing input text, images, or JSON.
433#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
434pub struct DecisionInputUserMessage {
435    pub content: DecisionInputContent,
436}
437
438/// A text string or an ordered list of text, image, and JSON parts.
439#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
440#[serde(untagged)]
441pub enum DecisionInputContent {
442    Text(String),
443    DecisionInputContentParts(DecisionInputContentParts),
444}
445
446pub type DecisionInputContentParts = Vec<DecisionInputContentPart>;
447
448#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
449#[serde(tag = "type", rename_all = "snake_case")]
450pub enum DecisionInputContentPart {
451    InputText(DecisionInputText),
452    InputImage(DecisionInputImage),
453    InputJson(DecisionInputJson),
454}
455
456impl From<String> for DecisionInput {
457    fn from(value: String) -> Self {
458        Self::Text(value)
459    }
460}
461impl From<&str> for DecisionInput {
462    fn from(value: &str) -> Self {
463        Self::Text(value.into())
464    }
465}
466
467impl Default for DecisionInput {
468    fn default() -> Self {
469        Self::Text(Default::default())
470    }
471}