Skip to content

Commit c0baa8b

Browse files
authored
DevDay API Update (#131)
* make speech example work * response save api for speech * create_all dir * update image types and examples * cleanup * chat completion request response * completions types * all types of chat completion message types * fix function call examples * bunch of from trait impls * updates to file and fine tune job types * Assistants API group * thread and message types * run object * messages and threads * thread runs * more thread and runs * error fix * run steps * assitant files * message files * update docs * updates * docs * cleanup * updated spec * latest spec * fixes * assistants example * fix * updated example * cargo fix * cargo fmt
1 parent e085d30 commit c0baa8b

File tree

41 files changed

+9016
-2053
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+9016
-2053
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ Cargo.lock
55

66
# directory used to store images
77
data
8+
9+
*.mp3

async-openai/README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@
1919

2020
## Overview
2121

22-
`async-openai` is an unofficial Rust library for OpenAI REST API.
22+
`async-openai` is an unofficial Rust library for OpenAI.
2323

2424
- It's based on [OpenAI OpenAPI spec](https://github.com/openai/openai-openapi)
2525
- Current features:
26+
- [x] Assistants (Beta)
2627
- [x] Audio (Whisper/TTS)
2728
- [x] Chat
2829
- [x] Completions (Legacy)
@@ -108,8 +109,6 @@ Thank you for your time to contribute and improve the project, I'd be happy to h
108109

109110
A good starting point would be existing [open issues](https://github.com/64bit/async-openai/issues).
110111

111-
## Complimentary Crates
112-
- [openai-func-enums](https://github.com/frankfralick/openai-func-enums) provides procedural macros that make it easier to use this library with OpenAI API's function calling feature. It also provides derive macros you can add to existing [clap](https://github.com/clap-rs/clap) application subcommands for natural language use of command line tools.
113112

114113
## License
115114

async-openai/src/assistant_files.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use serde::Serialize;
2+
3+
use crate::{
4+
config::Config,
5+
error::OpenAIError,
6+
types::{
7+
AssistantFileObject, CreateAssistantFileRequest, DeleteAssistantFileResponse,
8+
ListAssistantFilesResponse,
9+
},
10+
Client,
11+
};
12+
13+
/// Files attached to an assistant.
14+
pub struct AssistantFiles<'c, C: Config> {
15+
client: &'c Client<C>,
16+
pub assistant_id: String,
17+
}
18+
19+
impl<'c, C: Config> AssistantFiles<'c, C> {
20+
pub fn new(client: &'c Client<C>, assistant_id: &str) -> Self {
21+
Self {
22+
client,
23+
assistant_id: assistant_id.into(),
24+
}
25+
}
26+
27+
/// Create an assistant file by attaching a [File](https://platform.openai.com/docs/api-reference/files) to an [assistant](https://platform.openai.com/docs/api-reference/assistants).
28+
pub async fn create(
29+
&self,
30+
request: CreateAssistantFileRequest,
31+
) -> Result<AssistantFileObject, OpenAIError> {
32+
self.client
33+
.post(&format!("/assistants/{}/files", self.assistant_id), request)
34+
.await
35+
}
36+
37+
/// Retrieves an AssistantFile.
38+
pub async fn retrieve(&self, file_id: &str) -> Result<AssistantFileObject, OpenAIError> {
39+
self.client
40+
.get(&format!(
41+
"/assistants/{}/files/{file_id}",
42+
self.assistant_id
43+
))
44+
.await
45+
}
46+
47+
/// Delete an assistant file.
48+
pub async fn delete(&self, file_id: &str) -> Result<DeleteAssistantFileResponse, OpenAIError> {
49+
self.client
50+
.delete(&format!(
51+
"/assistants/{}/files/{file_id}",
52+
self.assistant_id
53+
))
54+
.await
55+
}
56+
57+
/// Returns a list of assistant files.
58+
pub async fn list<Q>(&self, query: &Q) -> Result<ListAssistantFilesResponse, OpenAIError>
59+
where
60+
Q: Serialize + ?Sized,
61+
{
62+
self.client
63+
.get_with_query(&format!("/assistants/{}/files", self.assistant_id), query)
64+
.await
65+
}
66+
}

async-openai/src/assistants.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use serde::Serialize;
2+
3+
use crate::{
4+
config::Config,
5+
error::OpenAIError,
6+
types::{
7+
AssistantObject, CreateAssistantRequest, DeleteAssistantResponse, ListAssistantsResponse,
8+
ModifyAssistantRequest,
9+
},
10+
AssistantFiles, Client,
11+
};
12+
13+
/// Build assistants that can call models and use tools to perform tasks.
14+
///
15+
/// [Get started with the Assistants API](https://platform.openai.com/docs/assistants)
16+
pub struct Assistants<'c, C: Config> {
17+
client: &'c Client<C>,
18+
}
19+
20+
impl<'c, C: Config> Assistants<'c, C> {
21+
pub fn new(client: &'c Client<C>) -> Self {
22+
Self { client }
23+
}
24+
25+
/// Assistant [AssistantFiles] API group
26+
pub fn files(&self, assistant_id: &str) -> AssistantFiles<C> {
27+
AssistantFiles::new(self.client, assistant_id)
28+
}
29+
30+
/// Create an assistant with a model and instructions.
31+
pub async fn create(
32+
&self,
33+
request: CreateAssistantRequest,
34+
) -> Result<AssistantObject, OpenAIError> {
35+
self.client.post("/assistants", request).await
36+
}
37+
38+
/// Retrieves an assistant.
39+
pub async fn retrieve(&self, assistant_id: &str) -> Result<AssistantObject, OpenAIError> {
40+
self.client
41+
.get(&format!("/assistants/{assistant_id}"))
42+
.await
43+
}
44+
45+
/// Modifies an assistant.
46+
pub async fn update(
47+
&self,
48+
assistant_id: &str,
49+
request: ModifyAssistantRequest,
50+
) -> Result<AssistantObject, OpenAIError> {
51+
self.client
52+
.post(&format!("/assistants/{assistant_id}"), request)
53+
.await
54+
}
55+
56+
/// Delete an assistant.
57+
pub async fn delete(&self, assistant_id: &str) -> Result<DeleteAssistantResponse, OpenAIError> {
58+
self.client
59+
.delete(&format!("/assistants/{assistant_id}"))
60+
.await
61+
}
62+
63+
/// Returns a list of assistants.
64+
pub async fn list<Q>(&self, query: &Q) -> Result<ListAssistantsResponse, OpenAIError>
65+
where
66+
Q: Serialize + ?Sized,
67+
{
68+
self.client.get_with_query("/assistants", query).await
69+
}
70+
}

async-openai/src/audio.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
use bytes::Bytes;
2-
31
use crate::{
42
config::Config,
53
error::OpenAIError,
64
types::{
7-
CreateSpeechRequest, CreateTranscriptionRequest, CreateTranscriptionResponse,
8-
CreateTranslationRequest, CreateTranslationResponse,
5+
CreateSpeechRequest, CreateSpeechResponse, CreateTranscriptionRequest,
6+
CreateTranscriptionResponse, CreateTranslationRequest, CreateTranslationResponse,
97
},
108
Client,
119
};
@@ -39,7 +37,13 @@ impl<'c, C: Config> Audio<'c, C> {
3937
self.client.post_form("/audio/translations", request).await
4038
}
4139

42-
pub async fn speech(&self, request: CreateSpeechRequest) -> Result<Bytes, OpenAIError> {
43-
self.client.post_raw("/audio/speech", request).await
40+
/// Generates audio from the input text.
41+
pub async fn speech(
42+
&self,
43+
request: CreateSpeechRequest,
44+
) -> Result<CreateSpeechResponse, OpenAIError> {
45+
let bytes = self.client.post_raw("/audio/speech", request).await?;
46+
47+
Ok(CreateSpeechResponse { bytes })
4448
}
4549
}

async-openai/src/client.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
file::Files,
1313
image::Images,
1414
moderation::Moderations,
15-
Audio, Chat, Completions, Embeddings, FineTunes, FineTuning, Models,
15+
Assistants, Audio, Chat, Completions, Embeddings, FineTunes, FineTuning, Models, Threads,
1616
};
1717

1818
#[derive(Debug, Clone)]
@@ -118,6 +118,16 @@ impl<C: Config> Client<C> {
118118
Audio::new(self)
119119
}
120120

121+
/// To call [Assistants] group related APIs using this client.
122+
pub fn assistants(&self) -> Assistants<C> {
123+
Assistants::new(self)
124+
}
125+
126+
/// To call [Threads] group related APIs using this client.
127+
pub fn threads(&self) -> Threads<C> {
128+
Threads::new(self)
129+
}
130+
121131
pub fn config(&self) -> &C {
122132
&self.config
123133
}

async-openai/src/config.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ pub const OPENAI_API_BASE: &str = "https://api.openai.com/v1";
88
/// Name for organization header
99
pub const OPENAI_ORGANIZATION_HEADER: &str = "OpenAI-Organization";
1010

11+
/// Calls to the Assistants API require that you pass a Beta header
12+
pub const OPENAI_BETA_HEADER: &str = "OpenAI-Beta";
13+
1114
/// [crate::Client] relies on this for every API call on OpenAI
1215
/// or Azure OpenAI service
1316
pub trait Config: Clone {
@@ -33,7 +36,9 @@ impl Default for OpenAIConfig {
3336
fn default() -> Self {
3437
Self {
3538
api_base: OPENAI_API_BASE.to_string(),
36-
api_key: std::env::var("OPENAI_API_KEY").unwrap_or_else(|_| "".to_string()).into(),
39+
api_key: std::env::var("OPENAI_API_KEY")
40+
.unwrap_or_else(|_| "".to_string())
41+
.into(),
3742
org_id: Default::default(),
3843
}
3944
}
@@ -80,9 +85,16 @@ impl Config for OpenAIConfig {
8085

8186
headers.insert(
8287
AUTHORIZATION,
83-
format!("Bearer {}", self.api_key.expose_secret()).as_str().parse().unwrap(),
88+
format!("Bearer {}", self.api_key.expose_secret())
89+
.as_str()
90+
.parse()
91+
.unwrap(),
8492
);
8593

94+
// hack for Assistants APIs
95+
// Calls to the Assistants API require that you pass a Beta header
96+
headers.insert(OPENAI_BETA_HEADER, "assistants=v1".parse().unwrap());
97+
8698
headers
8799
}
88100

@@ -113,12 +125,13 @@ pub struct AzureConfig {
113125
api_key: Secret<String>,
114126
}
115127

116-
117128
impl Default for AzureConfig {
118129
fn default() -> Self {
119130
Self {
120131
api_base: Default::default(),
121-
api_key: std::env::var("OPENAI_API_KEY").unwrap_or_else(|_| "".to_string()).into(),
132+
api_key: std::env::var("OPENAI_API_KEY")
133+
.unwrap_or_else(|_| "".to_string())
134+
.into(),
122135
deployment_id: Default::default(),
123136
api_version: Default::default(),
124137
}
@@ -157,7 +170,10 @@ impl Config for AzureConfig {
157170
fn headers(&self) -> HeaderMap {
158171
let mut headers = HeaderMap::new();
159172

160-
headers.insert("api-key", self.api_key.expose_secret().as_str().parse().unwrap());
173+
headers.insert(
174+
"api-key",
175+
self.api_key.expose_secret().as_str().parse().unwrap(),
176+
);
161177

162178
headers
163179
}

async-openai/src/file.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
Client,
66
};
77

8-
/// Files are used to upload documents that can be used with features like [Fine-tuning](https://platform.openai.com/docs/api-reference/fine-tuning).
8+
/// Files are used to upload documents that can be used with features like Assistants and Fine-tuning.
99
pub struct Files<'c, C: Config> {
1010
client: &'c Client<C>,
1111
}
@@ -71,7 +71,7 @@ mod tests {
7171

7272
assert_eq!(openai_file.bytes, 135);
7373
assert_eq!(openai_file.filename, "test.jsonl");
74-
assert_eq!(openai_file.purpose, "fine-tune");
74+
//assert_eq!(openai_file.purpose, "fine-tune");
7575

7676
//assert_eq!(openai_file.status, Some("processed".to_owned())); // uploaded or processed
7777

async-openai/src/lib.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Async Rust library for OpenAI REST API based on OpenAPI spec.
1+
//! Rust library for OpenAI
22
//!
33
//! ## Creating client
44
//!
@@ -76,6 +76,8 @@
7676
//! ## Examples
7777
//! For full working examples for all supported features see [examples](https://github.com/64bit/async-openai/tree/main/examples) directory in the repository.
7878
//!
79+
mod assistant_files;
80+
mod assistants;
7981
mod audio;
8082
mod chat;
8183
mod client;
@@ -91,11 +93,18 @@ mod file;
9193
mod fine_tune;
9294
mod fine_tuning;
9395
mod image;
96+
mod message_files;
97+
mod messages;
9498
mod model;
9599
mod moderation;
100+
mod runs;
101+
mod steps;
102+
mod threads;
96103
pub mod types;
97104
mod util;
98105

106+
pub use assistant_files::AssistantFiles;
107+
pub use assistants::Assistants;
99108
pub use audio::Audio;
100109
pub use chat::Chat;
101110
pub use client::Client;
@@ -106,5 +115,10 @@ pub use file::Files;
106115
pub use fine_tune::FineTunes;
107116
pub use fine_tuning::FineTuning;
108117
pub use image::Images;
118+
pub use message_files::MessageFiles;
119+
pub use messages::Messages;
109120
pub use model::Models;
110121
pub use moderation::Moderations;
122+
pub use runs::Runs;
123+
pub use steps::Steps;
124+
pub use threads::Threads;

0 commit comments

Comments
 (0)