Skip to content

Commit c2f3a6c

Browse files
authored
feat: Add responses API (#373)
* feat: Add responses API Adds support for the OpenAI responses API * feat: Add custom input item There's a lot of possible input items in the responses APIs. Ideally it'd be nice to have strict types, but for now we can use a custom user defined json value.
1 parent 939c4cd commit c2f3a6c

File tree

10 files changed

+1667
-2
lines changed

10 files changed

+1667
-2
lines changed

async-openai/src/client.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::{
1414
moderation::Moderations,
1515
traits::AsyncTryFrom,
1616
Assistants, Audio, AuditLogs, Batches, Chat, Completions, Embeddings, FineTuning, Invites,
17-
Models, Projects, Threads, Uploads, Users, VectorStores,
17+
Models, Projects, Responses, Threads, Uploads, Users, VectorStores,
1818
};
1919

2020
#[derive(Debug, Clone, Default)]
@@ -162,6 +162,11 @@ impl<C: Config> Client<C> {
162162
Projects::new(self)
163163
}
164164

165+
/// To call [Responses] group related APIs using this client.
166+
pub fn responses(&self) -> Responses<C> {
167+
Responses::new(self)
168+
}
169+
165170
pub fn config(&self) -> &C {
166171
&self.config
167172
}
@@ -341,7 +346,12 @@ impl<C: Config> Client<C> {
341346
let message: String = String::from_utf8_lossy(&bytes).into_owned();
342347
tracing::warn!("Server error: {status} - {message}");
343348
return Err(backoff::Error::Transient {
344-
err: OpenAIError::ApiError(ApiError { message, r#type: None, param: None, code: None }),
349+
err: OpenAIError::ApiError(ApiError {
350+
message,
351+
r#type: None,
352+
param: None,
353+
code: None,
354+
}),
345355
retry_after: None,
346356
});
347357
}

async-openai/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ mod project_api_keys;
146146
mod project_service_accounts;
147147
mod project_users;
148148
mod projects;
149+
mod responses;
149150
mod runs;
150151
mod steps;
151152
mod threads;
@@ -177,6 +178,7 @@ pub use project_api_keys::ProjectAPIKeys;
177178
pub use project_service_accounts::ProjectServiceAccounts;
178179
pub use project_users::ProjectUsers;
179180
pub use projects::Projects;
181+
pub use responses::Responses;
180182
pub use runs::Runs;
181183
pub use steps::Steps;
182184
pub use threads::Threads;

async-openai/src/responses.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use crate::{
2+
config::Config,
3+
error::OpenAIError,
4+
types::responses::{CreateResponse, Response},
5+
Client,
6+
};
7+
8+
/// Given text input or a list of context items, the model will generate a response.
9+
///
10+
/// Related guide: [Responses API](https://platform.openai.com/docs/guides/responses)
11+
pub struct Responses<'c, C: Config> {
12+
client: &'c Client<C>,
13+
}
14+
15+
impl<'c, C: Config> Responses<'c, C> {
16+
/// Constructs a new Responses client.
17+
pub fn new(client: &'c Client<C>) -> Self {
18+
Self { client }
19+
}
20+
21+
/// Creates a model response for the given input.
22+
#[crate::byot(
23+
T0 = serde::Serialize,
24+
R = serde::de::DeserializeOwned
25+
)]
26+
pub async fn create(&self, request: CreateResponse) -> Result<Response, OpenAIError> {
27+
self.client.post("/responses", request).await
28+
}
29+
}

async-openai/src/types/impls.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::{
1414
use bytes::Bytes;
1515

1616
use super::{
17+
responses::{CodeInterpreterContainer, Input, InputContent, Role as ResponsesRole},
1718
AddUploadPartRequest, AudioInput, AudioResponseFormat, ChatCompletionFunctionCall,
1819
ChatCompletionFunctions, ChatCompletionNamedToolChoice, ChatCompletionRequestAssistantMessage,
1920
ChatCompletionRequestAssistantMessageContent, ChatCompletionRequestDeveloperMessage,
@@ -987,3 +988,51 @@ impl AsyncTryFrom<AddUploadPartRequest> for reqwest::multipart::Form {
987988
}
988989

989990
// end: types to multipart form
991+
992+
impl Default for Input {
993+
fn default() -> Self {
994+
Self::Text("".to_string())
995+
}
996+
}
997+
998+
impl Default for InputContent {
999+
fn default() -> Self {
1000+
Self::TextInput("".to_string())
1001+
}
1002+
}
1003+
1004+
impl From<String> for Input {
1005+
fn from(value: String) -> Self {
1006+
Input::Text(value)
1007+
}
1008+
}
1009+
1010+
impl From<&str> for Input {
1011+
fn from(value: &str) -> Self {
1012+
Input::Text(value.to_owned())
1013+
}
1014+
}
1015+
1016+
impl Default for ResponsesRole {
1017+
fn default() -> Self {
1018+
Self::User
1019+
}
1020+
}
1021+
1022+
impl From<String> for InputContent {
1023+
fn from(value: String) -> Self {
1024+
Self::TextInput(value)
1025+
}
1026+
}
1027+
1028+
impl From<&str> for InputContent {
1029+
fn from(value: &str) -> Self {
1030+
Self::TextInput(value.to_owned())
1031+
}
1032+
}
1033+
1034+
impl Default for CodeInterpreterContainer {
1035+
fn default() -> Self {
1036+
CodeInterpreterContainer::Id("".to_string())
1037+
}
1038+
}

async-openai/src/types/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ mod projects;
2424
#[cfg_attr(docsrs, doc(cfg(feature = "realtime")))]
2525
#[cfg(feature = "realtime")]
2626
pub mod realtime;
27+
pub mod responses;
2728
mod run;
2829
mod step;
2930
mod thread;

0 commit comments

Comments
 (0)