Skip to content

Commit 4754c24

Browse files
authored
feat: complete spec sync (#473)
* add project rate limits api * add usage api * add usage example * fix test * fix test * admin api keys api * certificates api * fix test * nest admin apis in client.admin() * nested types for admin apis * fix example compilation * types::assistants * fix imports in the examples * fix * fix test * only unsigned types * add remanining byot tests * add realtime apis * u64 for timestamps * fix * upated readme * updated readme license * add community project back * update docs for dynamic dispatch * update readme * update readme * fix test * updated spec * cargo fmt
1 parent 0b79656 commit 4754c24

Some content is hidden

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

80 files changed

+68380
-17801
lines changed

async-openai/README.md

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,32 +19,23 @@
1919

2020
## Overview
2121

22-
`async-openai` is an unofficial Rust library for OpenAI.
23-
24-
- It's based on [OpenAI OpenAPI spec](https://github.com/openai/openai-openapi)
25-
- Current features:
26-
- [x] Administration (partially implemented)
27-
- [x] Assistants (beta)
28-
- [x] Audio
29-
- [x] Batch
30-
- [x] Chat
31-
- [x] ChatKit (beta)
32-
- [x] Completions (legacy)
33-
- [x] Conversations
34-
- [x] Containers
35-
- [x] Embeddings
36-
- [x] Evals
37-
- [x] Files
38-
- [x] Fine-Tuning
39-
- [x] Images
40-
- [x] Models
41-
- [x] Moderations
42-
- [x] Realtime (partially implemented)
43-
- [x] Responses
44-
- [x] Uploads
45-
- [x] Vector Stores
46-
- [x] Videos
47-
- [x] Webhooks
22+
`async-openai` is an unofficial Rust library for OpenAI, based on [OpenAI OpenAPI spec](https://github.com/openai/openai-openapi). It implements all APIs from the spec:
23+
24+
| Features | APIs |
25+
|---|---|
26+
| **Responses API** | Responses, Conversations, Streaming events |
27+
| **Webhooks** | Webhook Events |
28+
| **Platform APIs** | Audio, Audio Streaming, Videos, Images, Image Streaming, Embeddings, Evals, Fine-tuning, Graders, Batch, Files, Uploads, Models, Moderations |
29+
| **Vector stores** | Vector stores, Vector store files, Vector store file batches |
30+
| **ChatKit** <sub>(Beta)</sub> | ChatKit |
31+
| **Containers** | Containers, Container Files |
32+
| **Realtime** | Realtime Calls, Client secrets, Client events, Server events |
33+
| **Chat Completions** | Chat Completions, Streaming |
34+
| **Assistants** <sub>(Beta)</sub> | Assistants, Threads, Messages, Runs, Run steps, Streaming |
35+
| **Administration** | Administration, Admin API Keys, Invites, Users, Projects, Project users, Project service accounts, Project API keys, Project rate limits, Audit logs, Usage, Certificates |
36+
| **Legacy** | Completions |
37+
38+
Features that makes `async-openai` unique:
4839
- Bring your own custom types for Request or Response objects.
4940
- SSE streaming on available APIs
5041
- Requests (except SSE streaming) including form submissions are retried with exponential backoff when [rate limited](https://platform.openai.com/docs/guides/rate-limits).
@@ -68,9 +59,9 @@ $Env:OPENAI_API_KEY='sk-...'
6859
- Visit [examples](https://github.com/64bit/async-openai/tree/main/examples) directory on how to use `async-openai`.
6960
- Visit [docs.rs/async-openai](https://docs.rs/async-openai) for docs.
7061

71-
## Realtime API
62+
## Realtime
7263

73-
Only types for Realtime API are implemented, and can be enabled with feature flag `realtime`.
64+
Realtime types and APIs can be enabled with feature flag `realtime`.
7465

7566
## Webhooks
7667

@@ -122,7 +113,11 @@ async fn main() -> Result<(), Box<dyn Error>> {
122113

123114
## Bring Your Own Types
124115

125-
Enable methods whose input and outputs are generics with `byot` feature. It creates a new method with same name and `_byot` suffix.
116+
Enable methods whose input and outputs are generics with `byot` feature. It creates a new method with same name and `_byot` suffix.
117+
118+
`byot` requires trait bounds:
119+
- a request type (`fn` input parameter) needs to implement `serde::Serialize` or `std::fmt::Display` trait
120+
- a response type (`fn` ouput parameter) needs to implement `serde::de::DeserializeOwned` trait.
126121

127122
For example, to use `serde_json::Value` as request and response type:
128123
```rust
@@ -147,27 +142,35 @@ let response: Value = client
147142

148143
This can be useful in many scenarios:
149144
- To use this library with other OpenAI compatible APIs whose types don't exactly match OpenAI.
150-
- Extend existing types in this crate with new fields with `serde`.
145+
- Extend existing types in this crate with new fields with `serde` (for example with `#[serde(flatten)]`).
151146
- To avoid verbose types.
152147
- To escape deserialization errors.
153148

154149
Visit [examples/bring-your-own-type](https://github.com/64bit/async-openai/tree/main/examples/bring-your-own-type)
155150
directory to learn more.
156151

157-
## Dynamic Dispatch for Different Providers
152+
## Dynamic Dispatch for OpenAI-compatible Providers
153+
154+
This allows you to use same code (say a `fn`) to call APIs on different OpenAI-compatible providers.
158155

159-
For any struct that implements `Config` trait, you can wrap it in a smart pointer and cast the pointer to `dyn Config`
160-
trait object, then your client can accept any wrapped configuration type.
156+
For any struct that implements `Config` trait, wrap it in a smart pointer and cast the pointer to `dyn Config`
157+
trait object, then create a client with `Box` or `Arc` wrapped configuration.
161158

162-
For example,
159+
For example:
163160

164161
```rust
165-
use async_openai::{Client, config::Config, config::OpenAIConfig};
162+
use async_openai::{Client, config::{Config, OpenAIConfig}};
163+
164+
// Use `Box` or `std::sync::Arc` to wrap the config
165+
let config = Box::new(OpenAIConfig::default()) as Box<dyn Config>;
166+
// create client
167+
let client: Client<Box<dyn Config>> = Client::with_config(config);
166168

167-
let openai_config = OpenAIConfig::default();
168-
// You can use `std::sync::Arc` to wrap the config as well
169-
let config = Box::new(openai_config) as Box<dyn Config>;
170-
let client: Client<Box<dyn Config> > = Client::with_config(config);
169+
// A function can now accept a `&Client<Box<dyn Config>>` parameter
170+
// which can invoke any openai compatible api
171+
fn chat_completion(client: &Client<Box<dyn Config>>) {
172+
todo!()
173+
}
171174
```
172175

173176
## Contributing
@@ -187,8 +190,11 @@ To maintain quality of the project, a minimum of the following is a must for cod
187190

188191
This project adheres to [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct)
189192

193+
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in async-openai by you, shall be licensed as MIT, without any additional terms or conditions.
194+
190195
## Complimentary Crates
191196
- [async-openai-wasm](https://github.com/ifsheldon/async-openai-wasm) provides WASM support.
197+
- [openai-func-enums](https://github.com/frankfralick/openai-func-enums) macros for working with function/tool calls.
192198

193199
## License
194200

async-openai/src/admin.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use crate::{
2+
admin_api_keys::AdminAPIKeys, audit_logs::AuditLogs, certificates::Certificates,
3+
config::Config, invites::Invites, projects::Projects, users::Users, Client,
4+
};
5+
6+
/// Admin group for all administration APIs.
7+
/// This groups together admin API keys, invites, users, projects, audit logs, and certificates.
8+
pub struct Admin<'c, C: Config> {
9+
client: &'c Client<C>,
10+
}
11+
12+
impl<'c, C: Config> Admin<'c, C> {
13+
pub(crate) fn new(client: &'c Client<C>) -> Self {
14+
Self { client }
15+
}
16+
17+
/// To call [AdminAPIKeys] group related APIs using this client.
18+
pub fn api_keys(&self) -> AdminAPIKeys<'_, C> {
19+
AdminAPIKeys::new(self.client)
20+
}
21+
22+
/// To call [Invites] group related APIs using this client.
23+
pub fn invites(&self) -> Invites<'_, C> {
24+
Invites::new(self.client)
25+
}
26+
27+
/// To call [Users] group related APIs using this client.
28+
pub fn users(&self) -> Users<'_, C> {
29+
Users::new(self.client)
30+
}
31+
32+
/// To call [Projects] group related APIs using this client.
33+
pub fn projects(&self) -> Projects<'_, C> {
34+
Projects::new(self.client)
35+
}
36+
37+
/// To call [AuditLogs] group related APIs using this client.
38+
pub fn audit_logs(&self) -> AuditLogs<'_, C> {
39+
AuditLogs::new(self.client)
40+
}
41+
42+
/// To call [Certificates] group related APIs using this client.
43+
pub fn certificates(&self) -> Certificates<'_, C> {
44+
Certificates::new(self.client)
45+
}
46+
}

async-openai/src/admin_api_keys.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use serde::Serialize;
2+
3+
use crate::{
4+
config::Config,
5+
error::OpenAIError,
6+
types::admin::api_keys::{
7+
AdminApiKey, AdminApiKeyDeleteResponse, ApiKeyList, CreateAdminApiKeyRequest,
8+
},
9+
Client,
10+
};
11+
12+
/// Admin API keys enable Organization Owners to programmatically manage various aspects of their
13+
/// organization, including users, projects, and API keys. These keys provide administrative capabilities,
14+
/// allowing you to automate organization management tasks.
15+
pub struct AdminAPIKeys<'c, C: Config> {
16+
client: &'c Client<C>,
17+
}
18+
19+
impl<'c, C: Config> AdminAPIKeys<'c, C> {
20+
pub fn new(client: &'c Client<C>) -> Self {
21+
Self { client }
22+
}
23+
24+
/// List all organization and project API keys.
25+
#[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
26+
pub async fn list<Q>(&self, query: &Q) -> Result<ApiKeyList, OpenAIError>
27+
where
28+
Q: Serialize + ?Sized,
29+
{
30+
self.client
31+
.get_with_query("/organization/admin_api_keys", &query)
32+
.await
33+
}
34+
35+
/// Create an organization admin API key.
36+
pub async fn create(
37+
&self,
38+
request: CreateAdminApiKeyRequest,
39+
) -> Result<AdminApiKey, OpenAIError> {
40+
self.client
41+
.post("/organization/admin_api_keys", request)
42+
.await
43+
}
44+
45+
/// Retrieve a single organization API key.
46+
#[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
47+
pub async fn retrieve(&self, key_id: &str) -> Result<AdminApiKey, OpenAIError> {
48+
self.client
49+
.get(format!("/organization/admin_api_keys/{key_id}").as_str())
50+
.await
51+
}
52+
53+
/// Delete an organization admin API key.
54+
#[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
55+
pub async fn delete(&self, key_id: &str) -> Result<AdminApiKeyDeleteResponse, OpenAIError> {
56+
self.client
57+
.delete(format!("/organization/admin_api_keys/{key_id}").as_str())
58+
.await
59+
}
60+
}

async-openai/src/assistants.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use serde::Serialize;
33
use crate::{
44
config::Config,
55
error::OpenAIError,
6-
types::{
6+
types::assistants::{
77
AssistantObject, CreateAssistantRequest, DeleteAssistantResponse, ListAssistantsResponse,
88
ModifyAssistantRequest,
99
},

async-openai/src/audit_logs.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use serde::Serialize;
22

3-
use crate::{config::Config, error::OpenAIError, types::ListAuditLogsResponse, Client};
3+
use crate::{
4+
config::Config, error::OpenAIError, types::admin::audit_logs::ListAuditLogsResponse, Client,
5+
};
46

57
/// Logs of user actions and configuration changes within this organization.
68
/// To log events, you must activate logging in the [Organization Settings](https://platform.openai.com/settings/organization/general).

async-openai/src/certificates.rs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
use serde::Serialize;
2+
3+
use crate::{
4+
config::Config,
5+
error::OpenAIError,
6+
types::admin::certificates::{
7+
Certificate, DeleteCertificateResponse, ListCertificatesResponse, ModifyCertificateRequest,
8+
ToggleCertificatesRequest, UploadCertificateRequest,
9+
},
10+
Client,
11+
};
12+
13+
/// Certificates enable Mutual TLS (mTLS) authentication for your organization.
14+
/// Manage certificates at the organization level.
15+
pub struct Certificates<'c, C: Config> {
16+
client: &'c Client<C>,
17+
}
18+
19+
impl<'c, C: Config> Certificates<'c, C> {
20+
pub fn new(client: &'c Client<C>) -> Self {
21+
Self { client }
22+
}
23+
24+
// Organization-level certificate operations
25+
26+
/// List all certificates for the organization.
27+
#[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
28+
pub async fn list_organization<Q>(
29+
&self,
30+
query: &Q,
31+
) -> Result<ListCertificatesResponse, OpenAIError>
32+
where
33+
Q: Serialize + ?Sized,
34+
{
35+
self.client
36+
.get_with_query("/organization/certificates", &query)
37+
.await
38+
}
39+
40+
/// Upload a certificate to the organization.
41+
/// This does not automatically activate the certificate.
42+
pub async fn upload_organization(
43+
&self,
44+
request: UploadCertificateRequest,
45+
) -> Result<Certificate, OpenAIError> {
46+
self.client
47+
.post("/organization/certificates", request)
48+
.await
49+
}
50+
51+
/// Activate certificates for the organization.
52+
/// You can atomically and idempotently activate up to 10 certificates at a time.
53+
pub async fn activate_organization(
54+
&self,
55+
request: ToggleCertificatesRequest,
56+
) -> Result<ListCertificatesResponse, OpenAIError> {
57+
self.client
58+
.post("/organization/certificates/activate", request)
59+
.await
60+
}
61+
62+
/// Deactivate certificates for the organization.
63+
/// You can atomically and idempotently deactivate up to 10 certificates at a time.
64+
pub async fn deactivate_organization(
65+
&self,
66+
request: ToggleCertificatesRequest,
67+
) -> Result<ListCertificatesResponse, OpenAIError> {
68+
self.client
69+
.post("/organization/certificates/deactivate", request)
70+
.await
71+
}
72+
73+
/// Retrieve a single certificate.
74+
#[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
75+
pub async fn retrieve(&self, certificate_id: &str) -> Result<Certificate, OpenAIError> {
76+
self.client
77+
.get(format!("/organization/certificates/{certificate_id}").as_str())
78+
.await
79+
}
80+
81+
/// Retrieve a single certificate with optional include parameters.
82+
pub async fn retrieve_with_query<Q>(
83+
&self,
84+
certificate_id: &str,
85+
query: &Q,
86+
) -> Result<Certificate, OpenAIError>
87+
where
88+
Q: Serialize + ?Sized,
89+
{
90+
self.client
91+
.get_with_query(
92+
format!("/organization/certificates/{certificate_id}").as_str(),
93+
query,
94+
)
95+
.await
96+
}
97+
98+
/// Modify a certificate. Note that only the name can be modified.
99+
#[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
100+
pub async fn modify(
101+
&self,
102+
certificate_id: &str,
103+
request: ModifyCertificateRequest,
104+
) -> Result<Certificate, OpenAIError> {
105+
self.client
106+
.post(
107+
format!("/organization/certificates/{certificate_id}").as_str(),
108+
request,
109+
)
110+
.await
111+
}
112+
113+
/// Delete a certificate from the organization.
114+
/// The certificate must be inactive for the organization and all projects.
115+
#[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
116+
pub async fn delete(
117+
&self,
118+
certificate_id: &str,
119+
) -> Result<DeleteCertificateResponse, OpenAIError> {
120+
self.client
121+
.delete(format!("/organization/certificates/{certificate_id}").as_str())
122+
.await
123+
}
124+
}

0 commit comments

Comments
 (0)