Skip to main content

openresponses_rust/types/
content.rs

1use super::enums::ImageDetail;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
5#[serde(tag = "type")]
6pub enum InputContent {
7    #[serde(rename = "input_text")]
8    Text { text: String },
9    #[serde(rename = "input_image")]
10    Image {
11        image_url: Option<String>,
12        #[serde(default)]
13        detail: ImageDetail,
14    },
15    #[serde(rename = "input_file")]
16    File {
17        filename: Option<String>,
18        #[serde(skip_serializing_if = "Option::is_none")]
19        file_data: Option<String>,
20        #[serde(skip_serializing_if = "Option::is_none")]
21        file_url: Option<String>,
22    },
23    #[serde(rename = "input_video")]
24    Video { video_url: String },
25}
26
27impl InputContent {
28    pub fn text<S: Into<String>>(text: S) -> Self {
29        InputContent::Text { text: text.into() }
30    }
31
32    pub fn image_url<S: Into<String>>(url: S) -> Self {
33        InputContent::Image {
34            image_url: Some(url.into()),
35            detail: ImageDetail::default(),
36        }
37    }
38
39    pub fn image_url_with_detail<S: Into<String>>(url: S, detail: ImageDetail) -> Self {
40        InputContent::Image {
41            image_url: Some(url.into()),
42            detail,
43        }
44    }
45
46    pub fn file_url<S: Into<String>>(url: S) -> Self {
47        InputContent::File {
48            filename: None,
49            file_data: None,
50            file_url: Some(url.into()),
51        }
52    }
53
54    pub fn file_data<S: Into<String>>(data: S, filename: Option<String>) -> Self {
55        InputContent::File {
56            filename,
57            file_data: Some(data.into()),
58            file_url: None,
59        }
60    }
61
62    pub fn video_url<S: Into<String>>(url: S) -> Self {
63        InputContent::Video {
64            video_url: url.into(),
65        }
66    }
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
70#[serde(tag = "type")]
71pub enum OutputContent {
72    #[serde(rename = "output_text")]
73    Text {
74        text: String,
75        #[serde(default)]
76        annotations: Vec<Annotation>,
77        #[serde(skip_serializing_if = "Option::is_none")]
78        logprobs: Option<Vec<LogProb>>,
79    },
80    #[serde(rename = "refusal")]
81    Refusal { refusal: String },
82    #[serde(rename = "text")]
83    PlainText { text: String },
84    #[serde(rename = "summary_text")]
85    SummaryText { text: String },
86    #[serde(rename = "reasoning_text")]
87    ReasoningText { text: String },
88}
89
90impl OutputContent {
91    pub fn text<S: Into<String>>(text: S) -> Self {
92        OutputContent::Text {
93            text: text.into(),
94            annotations: Vec::new(),
95            logprobs: None,
96        }
97    }
98
99    pub fn refusal<S: Into<String>>(text: S) -> Self {
100        OutputContent::Refusal {
101            refusal: text.into(),
102        }
103    }
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
107#[serde(tag = "type")]
108pub enum Annotation {
109    #[serde(rename = "url_citation")]
110    UrlCitation {
111        url: String,
112        title: String,
113        start_index: i32,
114        end_index: i32,
115    },
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
119pub struct LogProb {
120    pub token: String,
121    pub logprob: f64,
122    pub bytes: Vec<u8>,
123    pub top_logprobs: Vec<TopLogProb>,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
127pub struct TopLogProb {
128    pub token: String,
129    pub logprob: f64,
130    pub bytes: Vec<u8>,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
134#[serde(untagged)]
135pub enum Content {
136    Input(InputContent),
137    Output(OutputContent),
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
141#[serde(untagged)]
142pub enum ContentParam {
143    Array(Vec<InputContent>),
144    Single(String),
145}