Skip to main content

async_openai/
lib.rs

1//! Rust library for OpenAI
2//!
3//! ## Creating client
4//!
5//! ```
6//! use async_openai::{Client, config::OpenAIConfig};
7//!
8//! // Create a OpenAI client with api key from env var OPENAI_API_KEY and default base url.
9//! let client = Client::new();
10//!
11//! // Above is shortcut for
12//! let config = OpenAIConfig::default();
13//! let client = Client::with_config(config);
14//!
15//! // OR use API key from different source and a non default organization
16//! let api_key = "sk-..."; // This secret could be from a file, or environment variable.
17//! let config = OpenAIConfig::new()
18//!     .with_api_key(api_key)
19//!     .with_org_id("the-continental");
20//!
21//! let client = Client::with_config(config);
22//!
23//! // Use custom reqwest client
24//! let http_client = reqwest::ClientBuilder::new().user_agent("async-openai").build().unwrap();
25//! let client = Client::new().with_http_client(http_client);
26//! ```
27//!
28//!
29//! ## Making requests
30//!
31//!```
32//!# tokio_test::block_on(async {
33//! use async_openai::{Client, types::responses::{CreateResponseArgs}};
34//!
35//! // Create client
36//! let client = Client::new();
37//!
38//! // Create request using builder pattern
39//! // Every request struct has companion builder struct with same name + Args suffix
40//! let request = CreateResponseArgs::default()
41//!     .model("gpt-5-mini")
42//!     .input("tell me the recipe of pav bhaji")
43//!     .max_output_tokens(512u32)
44//!     .build()?;
45//!
46//! // Call API
47//! let response = client
48//!     .responses()      // Get the API "group" (responses, images, etc.) from the client
49//!     .create(request)  // Make the API call in that "group"
50//!     .await?;
51//!
52//! println!("{:?}", response.output_text());
53//! # Ok::<(), Box<dyn std::error::Error>>(())
54//! # });
55//!```
56//!
57//! ## OpenAI Compatible Providers
58//!
59//! Even though the scope of the crate is official OpenAI APIs, it is very configurable to work with compatible providers.
60//!
61//! ### Bring Your Own Types
62//!
63//! To use custom types for inputs and outputs, enable `byot` feature which provides additional generic methods with same name and `_byot` suffix.
64//! This feature is available on methods whose return type is not `Bytes`
65//!
66//!```
67//!# #[cfg(feature = "byot")]
68//!# tokio_test::block_on(async {
69//! use async_openai::Client;
70//! use serde_json::{Value, json};
71//!
72//! let client = Client::new();
73//!
74//! let response: Value = client
75//!        .chat()
76//!        .create_byot(json!({
77//!            "messages": [
78//!                {
79//!                    "role": "developer",
80//!                    "content": "You are a helpful assistant"
81//!                },
82//!                {
83//!                    "role": "user",
84//!                    "content": "What do you think about life?"
85//!                }
86//!            ],
87//!            "model": "gpt-4o",
88//!            "store": false
89//!        }))
90//!        .await?;
91//!
92//!  if let Some(content) = response["choices"][0]["message"]["content"].as_str() {
93//!     println!("{}", content);
94//!  }
95//! # Ok::<(), Box<dyn std::error::Error>>(())
96//! # });
97//!```
98//!
99//! **References: Borrow Instead of Move**
100//!
101//! With `byot` use reference to request types
102//!
103//! ```
104//! # #[cfg(feature = "byot")]
105//! # tokio_test::block_on(async {
106//! # use async_openai::{Client, types::responses::{CreateResponse, Response}};
107//! # let client = Client::new();
108//! # let request = CreateResponse::default();
109//! let response: Response = client
110//!   .responses()
111//!   .create_byot(&request).await?;
112//! # Ok::<(), Box<dyn std::error::Error>>(())
113//! # });
114//! ```
115//!
116//! ### Configurable Requests
117//! Configure path, headers, and query parameters for a HTTP request.
118//!
119//! **Request Options**
120//!
121//! Use `path()`, `.query()`, `.header()`, `.headers()` on the API group. Path overrides the default path but all other methods are additive - adds to existing query or headers.
122//!
123//! For demonstration:
124//! ```
125//! # tokio_test::block_on(async {
126//! # use async_openai::Client;
127//! # use async_openai::traits::RequestOptionsBuilder;
128//! # let client = Client::new();
129//! client
130//!   .chat()
131//!   // override default path
132//!   .path("/v1/messages")
133//!   // query can be a struct or a map too - additive
134//!   .query(&[("limit", "10")])?
135//!   // header for unique id for this API request - additive
136//!   .header("x-request-id", "id123")?
137//!   .list()
138//!   .await?;
139//! # Ok::<(), Box<dyn std::error::Error>>(())
140//! # });
141//! ```
142//!
143//! **Modifying all Requests**
144//!
145//! Use `Config`, `OpenAIConfig` etc. for configuring url, headers or query parameters globally for all requests.
146//!
147//!
148//! ### Dynamic Dispatch
149//!
150//! This allows you to use same code (say a `fn`) to call APIs on different OpenAI-compatible providers.
151//!
152//! Create a client with `Box` or `Arc` wrapped configuration.
153//!
154//! For example:
155//! ```
156//! use async_openai::{Client, config::{Config, OpenAIConfig}};
157//!
158//! // Use `Box` or `std::sync::Arc` to wrap the config
159//! let config = Box::new(OpenAIConfig::default()) as Box<dyn Config>;
160//! // create client
161//! let client: Client<Box<dyn Config>> = Client::with_config(config);
162//!
163//! // A function can now accept a `&Client<Box<dyn Config>>` parameter
164//! // which can invoke any openai compatible api
165//! fn chat_completion(client: &Client<Box<dyn Config>>) {
166//!     todo!()
167//! }
168//! ```
169//!
170//! ### Microsoft Azure
171//!
172//! ```
173//! use async_openai::{Client, config::AzureConfig};
174//!
175//! let config = AzureConfig::new()
176//!     .with_api_base("https://my-resource-name.openai.azure.com")
177//!     .with_api_version("2023-03-15-preview")
178//!     .with_deployment_id("deployment-id")
179//!     .with_api_key("...");
180//!
181//! let client = Client::with_config(config);
182//!
183//!
184//! ```
185//!
186//!
187//! ## Rust Types
188//!
189//! To only use Rust types from the crate - use feature flag `types`.
190//!
191//! There are granular feature flags like `response-types`, `chat-completion-types`, etc.
192//!
193//! These granular types are enabled when the corresponding API feature is enabled - for example `responses` will enable `response-types`.
194//!
195//! ## WASM
196//! WASM is supported for all APIs.
197//! See [examples/wasm-responses](https://github.com/64bit/async-openai/tree/main/examples/wasm-responses) or [examples/tower-wasm](https://github.com/64bit/async-openai/tree/main/examples/tower-wasm).
198//!
199//!
200//! ## Middleware
201//!
202//! Middleware is supported via Tower ecosystem. See [`middleware`] for more detail.
203//!
204//! ## Examples
205//! For full working examples for all supported features see [examples](https://github.com/64bit/async-openai/tree/main/examples) directory in the repository.
206//!
207#![cfg_attr(docsrs, feature(doc_cfg))]
208
209#[cfg(all(feature = "_api", feature = "byot"))]
210#[allow(unused_imports)]
211pub(crate) use async_openai_macros::byot;
212
213#[cfg(all(feature = "_api", not(feature = "byot")))]
214#[allow(unused_imports)]
215pub(crate) use async_openai_macros::byot_passthrough as byot;
216
217// #[cfg(all(not(feature = "_api"), not(feature = "byot")))]
218// #[macro_export]
219// macro_rules! byot {
220//     ($($tt:tt)*) => {
221//         $($tt)*
222//     };
223// }
224
225#[cfg(feature = "administration")]
226mod admin;
227#[cfg(feature = "assistant")]
228mod assistants;
229#[cfg(feature = "audio")]
230mod audio;
231#[cfg(feature = "batch")]
232mod batches;
233#[cfg(feature = "chat-completion")]
234mod chat;
235#[cfg(feature = "chatkit")]
236mod chatkit;
237#[cfg(feature = "_api")]
238mod client;
239#[cfg(feature = "completions")]
240mod completion;
241#[cfg(feature = "_api")]
242pub mod config;
243#[cfg(feature = "container")]
244mod containers;
245#[cfg(feature = "image")]
246mod download;
247#[cfg(feature = "embedding")]
248mod embedding;
249pub mod error;
250#[cfg(feature = "evals")]
251mod evals;
252#[cfg(feature = "_api")]
253mod executor;
254#[cfg(feature = "file")]
255mod file;
256#[cfg(feature = "finetuning")]
257mod fine_tuning;
258#[cfg(feature = "image")]
259mod image;
260#[cfg(feature = "_api")]
261mod impls;
262#[cfg(feature = "middleware")]
263pub mod middleware;
264#[cfg(feature = "model")]
265mod model;
266#[cfg(feature = "moderation")]
267mod moderation;
268#[cfg(feature = "realtime")]
269mod realtime;
270#[cfg(feature = "_api")]
271mod request_options;
272#[cfg(feature = "responses")]
273mod responses;
274#[cfg(feature = "_api")]
275#[allow(dead_code)]
276#[path = "middleware/retry/mod.rs"]
277mod retry;
278#[cfg(feature = "skill")]
279mod skills;
280#[cfg(feature = "_api")]
281pub mod traits;
282pub mod types;
283#[cfg(feature = "upload")]
284mod uploads;
285#[cfg(any(
286    feature = "audio",
287    feature = "file",
288    feature = "upload",
289    feature = "image",
290    feature = "video",
291    feature = "container",
292    feature = "skill"
293))]
294mod util;
295#[cfg(feature = "vectorstore")]
296mod vectorstores;
297#[cfg(feature = "video")]
298mod video;
299#[cfg(feature = "webhook")]
300pub mod webhooks;
301
302// admin::* would be good - however its expanded here so that docs.rs shows the feature flags
303#[cfg(feature = "administration")]
304pub use admin::{
305    Admin, AdminAPIKeys, AuditLogs, Certificates, GroupRoles, GroupUsers, Groups, Invites,
306    ProjectAPIKeys, ProjectCertificates, ProjectGroupRoles, ProjectGroups, ProjectRateLimits,
307    ProjectRoles, ProjectServiceAccounts, ProjectUserRoles, ProjectUsers, Projects, Roles, Usage,
308    UserRoles, Users,
309};
310#[cfg(feature = "assistant")]
311#[deprecated(
312    note = "Assistants API is deprecated and will be removed in August 2026. Use the Responses API."
313)]
314#[allow(deprecated)]
315pub use assistants::{Assistants, Messages, Runs, Steps, Threads};
316#[cfg(feature = "audio")]
317pub use audio::{Audio, Speech, Transcriptions, Translations};
318#[cfg(feature = "batch")]
319pub use batches::Batches;
320#[cfg(feature = "chat-completion")]
321pub use chat::Chat;
322#[cfg(feature = "chatkit")]
323pub use chatkit::Chatkit;
324#[cfg(feature = "_api")]
325pub use client::Client;
326#[cfg(feature = "completions")]
327pub use completion::Completions;
328#[cfg(feature = "container")]
329pub use containers::{ContainerFiles, Containers};
330#[cfg(feature = "embedding")]
331pub use embedding::Embeddings;
332#[cfg(feature = "evals")]
333pub use evals::{EvalRunOutputItems, EvalRuns, Evals};
334#[cfg(feature = "file")]
335pub use file::Files;
336#[cfg(feature = "finetuning")]
337pub use fine_tuning::FineTuning;
338#[cfg(feature = "image")]
339pub use image::Images;
340#[cfg(feature = "model")]
341pub use model::Models;
342#[cfg(feature = "moderation")]
343pub use moderation::Moderations;
344#[cfg(feature = "realtime")]
345pub use realtime::Realtime;
346#[cfg(feature = "_api")]
347pub use request_options::RequestOptions;
348#[cfg(feature = "responses")]
349pub use responses::{ConversationItems, Conversations, Responses};
350#[cfg(feature = "skill")]
351pub use skills::{SkillVersions, Skills};
352#[cfg(feature = "upload")]
353pub use uploads::Uploads;
354#[cfg(feature = "vectorstore")]
355pub use vectorstores::{VectorStoreFileBatches, VectorStoreFiles, VectorStores};
356#[cfg(feature = "video")]
357pub use video::Videos;