openai_tools/responses/
request.rs1use crate::{
2 common::{
3 errors::{OpenAIToolError, Result},
4 message::Message,
5 structured_output::Schema,
6 tool::Tool,
7 },
8 responses::response::Response,
9};
10use derive_new::new;
11use dotenvy::dotenv;
12use request;
13use serde::{ser::SerializeStruct, Serialize};
14use std::env;
15
16#[derive(Debug, Clone, Default, Serialize, new)]
17pub struct Format {
18 pub format: Schema,
19}
20
21#[derive(Debug, Clone, Default, new)]
22pub struct Body {
23 pub model: String,
24 pub instructions: Option<String>,
25 pub plain_text_input: Option<String>,
26 pub messages_input: Option<Vec<Message>>,
27 pub tools: Option<Vec<Tool>>,
28 pub text: Option<Format>,
29}
30
31impl Serialize for Body {
32 fn serialize<S>(&self, serializer: S) -> anyhow::Result<S::Ok, S::Error>
33 where
34 S: serde::Serializer,
35 {
36 let input = if self.plain_text_input.is_some() {
37 self.plain_text_input.clone().unwrap()
38 } else if self.messages_input.is_some() {
39 serde_json::to_string(&self.messages_input).unwrap()
40 } else {
41 return Err(serde::ser::Error::custom("Either plain_text_input or messages_input must be set."));
42 };
43 let mut state = serializer.serialize_struct("ResponsesBody", 4)?;
44 state.serialize_field("model", &self.model)?;
45 state.serialize_field("instructions", &self.instructions)?;
46 state.serialize_field("input", &input)?;
47 if self.tools.is_some() {
48 state.serialize_field("tools", &self.tools)?;
49 }
50 if self.text.is_some() {
51 state.serialize_field("text", &self.text)?;
52 }
53 state.end()
54 }
55}
56
57#[derive(Debug, Clone, Default, Serialize)]
58pub struct Responses {
59 api_key: String,
60 pub request_body: Body,
61}
62
63impl Responses {
64 pub fn new() -> Self {
65 dotenv().ok();
66 let api_key = env::var("OPENAI_API_KEY").expect("OPENAI_API_KEY is not set.");
67 Self { api_key, request_body: Body::default() }
68 }
69
70 pub fn model_id<T: AsRef<str>>(&mut self, model_id: T) -> &mut Self {
71 self.request_body.model = model_id.as_ref().to_string();
72 self
73 }
74
75 pub fn instructions<T: AsRef<str>>(&mut self, instructions: T) -> &mut Self {
76 self.request_body.instructions = Some(instructions.as_ref().to_string());
77 self
78 }
79
80 pub fn plain_text_input<T: AsRef<str>>(&mut self, input: T) -> &mut Self {
81 self.request_body.plain_text_input = Some(input.as_ref().to_string());
82 self
83 }
84
85 pub fn messages(&mut self, messages: Vec<Message>) -> &mut Self {
86 self.request_body.messages_input = Some(messages);
87 self
88 }
89
90 pub fn tools(&mut self, tools: Vec<Tool>) -> &mut Self {
91 self.request_body.tools = Some(tools);
92 self
93 }
94
95 pub fn text(&mut self, text_format: Schema) -> &mut Self {
96 self.request_body.text = Option::from(Format::new(text_format));
97 self
98 }
99
100 pub async fn complete(&self) -> Result<Response> {
101 if self.api_key.is_empty() {
102 return Err(OpenAIToolError::Error("API key is not set.".into()));
103 }
104 if self.request_body.model.is_empty() {
105 return Err(OpenAIToolError::Error("Model ID is not set.".into()));
106 }
107 if self.request_body.messages_input.is_none() && self.request_body.plain_text_input.is_none() {
108 return Err(OpenAIToolError::Error("Messages are not set.".into()));
109 } else if self.request_body.plain_text_input.is_none() && self.request_body.messages_input.is_none() {
110 return Err(OpenAIToolError::Error("Both plain text input and messages are set. Please use one of them.".into()));
111 }
112
113 let body = serde_json::to_string(&self.request_body)?;
114 let url = "https://api.openai.com/v1/responses".to_string();
115
116 let client = request::Client::new();
117 let mut header = request::header::HeaderMap::new();
118 header.insert("Content-Type", request::header::HeaderValue::from_static("application/json"));
119 header.insert("Authorization", request::header::HeaderValue::from_str(&format!("Bearer {}", self.api_key)).unwrap());
120 header.insert("User-Agent", request::header::HeaderValue::from_static("openai-tools-rust/0.1.0"));
121
122 if cfg!(debug_assertions) {
123 let body_for_debug = serde_json::to_string_pretty(&self.request_body).unwrap().replace(&self.api_key, "*************");
125 tracing::info!("Request body: {}", body_for_debug);
127 }
128
129 let response = client.post(url).headers(header).body(body).send().await.map_err(OpenAIToolError::RequestError)?;
130 let content = response.text().await.map_err(OpenAIToolError::RequestError)?;
131
132 if cfg!(debug_assertions) {
133 tracing::info!("Response content: {}", content);
134 }
135
136 serde_json::from_str::<Response>(&content).map_err(OpenAIToolError::SerdeJsonError)
137 }
138}