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 = "audio")]
228mod audio;
229#[cfg(feature = "batch")]
230mod batches;
231#[cfg(feature = "chat-completion")]
232mod chat;
233#[cfg(feature = "chatkit")]
234mod chatkit;
235#[cfg(feature = "_api")]
236mod client;
237#[cfg(feature = "completions")]
238mod completion;
239#[cfg(feature = "_api")]
240pub mod config;
241#[cfg(feature = "container")]
242mod containers;
243#[cfg(feature = "image")]
244mod download;
245#[cfg(feature = "embedding")]
246mod embedding;
247pub mod error;
248#[cfg(feature = "evals")]
249mod evals;
250#[cfg(feature = "_api")]
251mod executor;
252#[cfg(feature = "file")]
253mod file;
254#[cfg(feature = "finetuning")]
255mod fine_tuning;
256#[cfg(feature = "image")]
257mod image;
258#[cfg(feature = "_api")]
259mod impls;
260#[cfg(feature = "middleware")]
261pub mod middleware;
262#[cfg(feature = "model")]
263mod model;
264#[cfg(feature = "moderation")]
265mod moderation;
266#[cfg(feature = "realtime")]
267mod realtime;
268#[cfg(feature = "_api")]
269mod request_options;
270#[cfg(feature = "responses")]
271mod responses;
272#[cfg(feature = "_api")]
273#[allow(dead_code)]
274#[path = "middleware/retry/mod.rs"]
275mod retry;
276#[cfg(feature = "skill")]
277mod skills;
278#[cfg(feature = "_api")]
279pub mod traits;
280pub mod types;
281#[cfg(feature = "upload")]
282mod uploads;
283#[cfg(any(
284    feature = "content-provenance-checks",
285    feature = "audio",
286    feature = "file",
287    feature = "upload",
288    feature = "image",
289    feature = "video",
290    feature = "container",
291    feature = "skill"
292))]
293mod util;
294#[cfg(feature = "vectorstore")]
295mod vectorstores;
296#[cfg(feature = "video")]
297mod video;
298#[cfg(feature = "webhook")]
299pub mod webhooks;
300
301// admin::* would be good - however its expanded here so that docs.rs shows the feature flags
302#[cfg(feature = "administration")]
303pub use admin::{
304    Admin, AdminAPIKeys, AuditLogs, Certificates, GroupRoles, GroupUsers, Groups, Invites,
305    OrganizationDataRetentions, OrganizationSpendAlerts, OrganizationSpendLimit, ProjectAPIKeys,
306    ProjectCertificates, ProjectDataRetentions, ProjectGroupRoles, ProjectGroups,
307    ProjectHostedToolPermission, ProjectModelPermission, ProjectRateLimits, ProjectRoles,
308    ProjectServiceAccounts, ProjectSpendAlerts, ProjectSpendLimit, ProjectUserRoles, ProjectUsers,
309    Projects, Roles, Usage, UserRoles, Users,
310};
311#[cfg(feature = "audio")]
312pub use audio::{Audio, Speech, Transcriptions, Translations};
313#[cfg(feature = "batch")]
314pub use batches::Batches;
315#[cfg(feature = "chat-completion")]
316pub use chat::Chat;
317#[cfg(feature = "chatkit")]
318pub use chatkit::Chatkit;
319#[cfg(feature = "_api")]
320pub use client::Client;
321#[cfg(feature = "completions")]
322pub use completion::Completions;
323#[cfg(feature = "container")]
324pub use containers::{ContainerFiles, Containers};
325#[cfg(feature = "embedding")]
326pub use embedding::Embeddings;
327#[cfg(feature = "evals")]
328pub use evals::{EvalRunOutputItems, EvalRuns, Evals};
329#[cfg(feature = "file")]
330pub use file::Files;
331#[cfg(feature = "finetuning")]
332pub use fine_tuning::FineTuning;
333#[cfg(feature = "image")]
334pub use image::Images;
335#[cfg(feature = "model")]
336pub use model::Models;
337#[cfg(feature = "moderation")]
338pub use moderation::Moderations;
339#[cfg(feature = "realtime")]
340pub use realtime::{Realtime, RealtimeTranslations};
341#[cfg(feature = "_api")]
342pub use request_options::RequestOptions;
343#[cfg(feature = "responses")]
344pub use responses::{ConversationItems, Conversations, Responses};
345#[cfg(feature = "skill")]
346pub use skills::{SkillVersions, Skills};
347#[cfg(feature = "upload")]
348pub use uploads::Uploads;
349#[cfg(feature = "vectorstore")]
350pub use vectorstores::{VectorStoreFileBatches, VectorStoreFiles, VectorStores};
351#[cfg(feature = "video")]
352#[allow(deprecated)]
353pub use video::Videos;
354
355#[cfg(feature = "safety")]
356mod safety;
357#[cfg(feature = "safety")]
358pub use safety::*;
359
360#[cfg(feature = "content-provenance-checks")]
361mod content_provenance_checks;
362#[cfg(feature = "content-provenance-checks")]
363pub use content_provenance_checks::ContentProvenanceChecks;