Expand description
§openai-ergonomic
Ergonomic Rust wrapper for the OpenAI API, providing type-safe builder patterns and async/await support.
§Features
- Type-safe - full type safety with builder patterns using
bon - Async/await - built on
tokioandreqwestfor modern async Rust - Streaming - first-class support for streaming responses
- Comprehensive - covers all
OpenAIAPI endpoints - Azure
OpenAI- seamless support for AzureOpenAIdeployments - Well-tested - extensive test coverage with mock support
- Well-documented - rich documentation with examples
§Status
Status: under construction. The crate is still in active development and not yet ready for production use.
§Quick Start
Add openai-ergonomic to your Cargo.toml:
[dependencies]
openai-ergonomic = "0.1"
tokio = { version = "1.0", features = ["full"] }§Basic Usage
use openai_ergonomic::{Client, Config};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Build client from environment variables
let client = Client::from_env()?.build();
let response = client
.chat_completions()
.model("gpt-4")
.message("user", "Hello, world!")
.send()
.await?;
println!("{}", response.choices[0].message.content);
Ok(())
}§Streaming Example
use openai_ergonomic::Client;
use futures::StreamExt;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Build client from environment variables
let client = Client::from_env()?.build();
let builder = client
.chat()
.user("Tell me a story");
let mut stream = client.send_chat_stream(builder).await?;
while let Some(chunk) = stream.next().await {
let chunk = chunk?;
if let Some(content) = chunk.content() {
print!("{}", content);
}
}
Ok(())
}§Custom HTTP Client with Retry Logic
You can provide your own reqwest::Client with custom retry, timeout, and middleware configuration.
Note: When using a custom HTTP client, you must configure the timeout on the reqwest::Client itself:
use openai_ergonomic::{Client, Config};
use reqwest_middleware::ClientBuilder;
use reqwest_retry::{RetryTransientMiddleware, policies::ExponentialBackoff};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a retry policy with exponential backoff
let retry_policy = ExponentialBackoff::builder()
.build_with_max_retries(3);
// Build a reqwest client with custom timeout
let reqwest_client = reqwest::Client::builder()
.timeout(Duration::from_secs(60)) // Configure timeout here
.build()?;
// Add retry middleware
let http_client = ClientBuilder::new(reqwest_client)
.with(RetryTransientMiddleware::new_with_policy(retry_policy))
.build();
// Create OpenAI client with custom HTTP client
let config = Config::builder()
.api_key("your-api-key")
.http_client(http_client)
.build();
let client = Client::new(config)?.build();
// Use the client normally - retries and timeout are handled automatically
let response = client.chat_simple("Hello!").await?;
println!("{}", response);
Ok(())
}§Azure OpenAI Support
The crate seamlessly supports Azure OpenAI deployments. Azure-specific configuration can be provided through environment variables or programmatically.
§Using Environment Variables
export AZURE_OPENAI_ENDPOINT="https://my-resource.openai.azure.com"
export AZURE_OPENAI_API_KEY="your-azure-api-key"
export AZURE_OPENAI_DEPLOYMENT="gpt-4"
export AZURE_OPENAI_API_VERSION="2024-02-01" # Optional, defaults to 2024-02-01use openai_ergonomic::Client;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Build client from Azure environment variables
let client = Client::from_env()?.build();
// Use exactly the same API as standard OpenAI
let response = client.chat_simple("Hello from Azure!").await?;
println!("{}", response);
Ok(())
}§Manual Configuration
use openai_ergonomic::{Client, Config};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::builder()
.api_key("your-azure-api-key")
.api_base("https://my-resource.openai.azure.com")
.azure_deployment("gpt-4")
.azure_api_version("2024-02-01")
.build();
let client = Client::new(config)?.build();
let response = client.chat_simple("Hello!").await?;
println!("{}", response);
Ok(())
}Note: The library automatically handles the differences between Azure OpenAI and standard OpenAI (authentication, URL paths, API versioning). You use the same API regardless of the provider.
§Documentation
- Getting Started Guide
- Architecture Overview
- API Coverage Status - See what APIs are available
- Examples Index - Browse all examples by category
- Responses-First Workflows
- Tool Orchestration
- Vector Store Operations
- Langfuse Integration
- API Documentation
§Examples
The examples/ directory contains comprehensive examples for all major OpenAI API features:
§Core Examples
- quickstart.rs - Quick introduction to the library with basic usage patterns
- chat_streaming.rs - Real-time chat streaming with Server-Sent Events (SSE)
- tool_calling_multiturn.rs - Multi-turn tool calling with proper conversation history management
- responses_comprehensive.rs - Complete responses API demonstration including function calling and web search
- responses_streaming.rs - Real-time streaming responses with progress indicators
- chat_comprehensive.rs - Full chat completions API with conversation history
- structured_outputs.rs - JSON mode and schema-based structured outputs
- vision_chat.rs - Image understanding with GPT-4 Vision
§Media & AI Capabilities
- audio_speech.rs - Text-to-speech generation with multiple voices
- audio_transcription.rs - Speech-to-text transcription and translation
- images_comprehensive.rs - Image generation, editing, and variations
- embeddings.rs - Vector embeddings with similarity search patterns
§Advanced APIs
- assistants_basic.rs - Introduction to the Assistants API with threads and tools
Run any example with:
# Set your OpenAI API key
export OPENAI_API_KEY="your-api-key-here"
# Run an example
cargo run --example quickstart
cargo run --example responses_streaming
cargo run --example vision_chatEach example includes:
- Comprehensive documentation and inline comments
- Error handling best practices
- Real-world use cases and patterns
- Progressive complexity from basic to advanced usage
§Contributing
We welcome contributions! Please see our Contributing Guide for details.
§License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
§Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
§openai-ergonomic
An ergonomic Rust wrapper for the OpenAI API, providing type-safe builder patterns
and async/await support for all OpenAI endpoints.
§Features
- Type-safe builders - Use builder patterns with compile-time validation
- Async/await support - Built on tokio and reqwest for modern async Rust
- Streaming responses - First-class support for real-time streaming
- Comprehensive coverage - Support for all
OpenAIAPI endpoints - Error handling - Structured error types for robust applications
- Testing support - Mock-friendly design for unit testing
§Quick Start
use openai_ergonomic::{Client, Config};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a client from environment variables
let client = Client::from_env()?;
// Simple chat completion
let response = client
.chat_simple("Hello, how are you?")
.await?;
println!("{}", response);
Ok(())
}§Streaming Example
use openai_ergonomic::Client;
use futures::StreamExt;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::from_env()?.build();
// Stream chat completions
let builder = client
.chat()
.user("Tell me a story");
let mut stream = client.send_chat_stream(builder).await?;
while let Some(chunk) = stream.next().await {
let chunk = chunk?;
if let Some(content) = chunk.content() {
print!("{}", content);
}
}
Ok(())
}§Error Handling
use openai_ergonomic::{Client, Error};
#[tokio::main]
async fn main() {
let client = Client::from_env().expect("API key required");
match client.chat_simple("Hello").await {
Ok(response) => println!("{}", response),
Err(Error::RateLimit { .. }) => {
println!("Rate limited, please retry later");
}
Err(e) => eprintln!("Error: {}", e),
}
}§Custom Configuration
use openai_ergonomic::{Client, Config};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::builder()
.api_key("your-api-key")
.organization_id("org-123")
.timeout(Duration::from_secs(30))
.max_retries(5)
.build();
let client = Client::builder(config)?.build();
Ok(())
}§Testing with Mocks
#[cfg(test)]
mod tests {
use openai_ergonomic::test_utils::MockOpenAIServer;
#[tokio::test]
async fn test_chat_completion() {
let mock = MockOpenAIServer::new();
mock.mock_chat_completion("Hello!", "Hi there!");
let client = mock.client();
let response = client.chat_simple("Hello!").await.unwrap();
assert_eq!(response, "Hi there!");
}
}§Modules
Re-exports§
pub use client::Client;pub use config::Config;pub use config::ConfigBuilder;pub use errors::Error;pub use errors::Result;pub use interceptor::AfterResponseContext;pub use interceptor::BeforeRequestContext;pub use interceptor::ErrorContext;pub use interceptor::Interceptor;pub use interceptor::StreamChunkContext;pub use interceptor::StreamEndContext;pub use langfuse_interceptor::LangfuseConfig;pub use langfuse_interceptor::LangfuseInterceptor;pub use langfuse_interceptor::LangfuseState;pub use builders::audio::SpeechBuilder;pub use builders::audio::TimestampGranularity;pub use builders::audio::TranscriptionBuilder;pub use builders::audio::TranscriptionRequest;pub use builders::audio::TranslationBuilder;pub use builders::audio::TranslationRequest;pub use builders::chat::image_base64_part;pub use builders::chat::image_base64_part_with_detail;pub use builders::chat::image_url_part;pub use builders::chat::image_url_part_with_detail;pub use builders::chat::system_user;pub use builders::chat::text_part;pub use builders::chat::user_message;pub use builders::embeddings::EmbeddingInput;pub use builders::embeddings::EmbeddingsBuilder;pub use builders::images::ImageEditBuilder;pub use builders::images::ImageEditRequest;pub use builders::images::ImageGenerationBuilder;pub use builders::images::ImageVariationBuilder;pub use builders::images::ImageVariationRequest;pub use builders::threads::AttachmentTool;pub use builders::threads::MessageAttachment;pub use builders::threads::ThreadMessageBuilder;pub use builders::threads::ThreadRequestBuilder;pub use builders::uploads::UploadBuilder;pub use builders::responses::responses_simple;pub use builders::responses::responses_system_user;pub use builders::responses::ResponsesBuilder;pub use builders::Builder;pub use builders::ChatCompletionBuilder;pub use builders::Sendable;pub use responses::chat::ChatCompletionResponseExt;pub use responses::chat::ToolCallExt;pub use responses::tool_function;pub use responses::tool_web_search;pub use responses::ChatCompletionResponseWrapper;pub use responses::Response;pub use streaming::ChatCompletionChunk;pub use streaming::ChatCompletionStream;pub use streaming::InterceptedStream;pub use bon;
Modules§
- azure_
middleware - Middleware for Azure
OpenAIauthentication. - builders
- Builder pattern implementations for
OpenAIAPI requests. - client
- Client wrapper for ergonomic
OpenAIAPI access. - config
- Configuration for the
OpenAIergonomic client. - errors
- Error types for the
OpenAIergonomic wrapper. - interceptor
- Interceptor system for middleware and observability.
- langfuse_
interceptor - Langfuse interceptor for OpenTelemetry-based LLM observability.
- responses
- Response type wrappers and ergonomic helpers.
- semantic_
conventions - OpenTelemetry Semantic Conventions for Generative AI
- streaming
- Streaming support for chat completions.
Structs§
- Chat
Choice - Chat
Completion Response - CreateChatCompletionResponse : Represents a chat completion response returned by model, based on the provided input.
- Function
Call - ChatCompletionMessageToolCallFunction : The function that the model called.
- Response
Chat Message - ChatCompletionResponseMessage : A chat completion message generated by the model.
- Tool
- Re-export commonly used types from openai-client-base for convenience ChatCompletionTool : A function tool that can be used to generate a response.
- Usage
- Re-export commonly used types from openai-client-base for convenience CompletionUsage : Usage statistics for the completion request.
Enums§
- Background
- Allows to set transparency for the background of the generated image(s). This parameter is only supported for
gpt-image-1. Must be one oftransparent,opaqueorauto(default value). Whenautois used, the model will automatically determine the best background for the image. Iftransparent, the output format needs to support transparency, so it should be set to eitherpng(default value) orwebp. - Detail
- Specifies the detail level of the image. Learn more in the Vision guide.
- Image
Input Fidelity - ImageInputFidelity - Untagged union type
- Image
Input Fidelity Text Variant Enum - ImageInputFidelityTextVariantEnum - String enum type
- Moderation
- Control the content-moderation level for images generated by
gpt-image-1. Must be eitherlowfor less restrictive filtering orauto(default value). - Output
Format - The format in which the generated images are returned. This parameter is only supported for
gpt-image-1. Must be one ofpng,jpeg, orwebp. - Quality
- The quality of the image that will be generated. -
auto(default value) will automatically select the best quality for the given model. -high,mediumandloware supported forgpt-image-1. -hdandstandardare supported fordall-e-3. -standardis the only option fordall-e-2. - Response
Format - The format in which generated images with
dall-e-2anddall-e-3are returned. Must be one ofurlorb64_json. URLs are only valid for 60 minutes after the image has been generated. This parameter isn’t supported forgpt-image-1which will always return base64-encoded images. - Size
- The size of the generated images. Must be one of
1024x1024,1536x1024(landscape),1024x1536(portrait), orauto(default value) forgpt-image-1, one of256x256,512x512, or1024x1024fordall-e-2, and one of1024x1024,1792x1024, or1024x1792fordall-e-3. - Style
- The style of the generated images. This parameter is only supported for
dall-e-3. Must be one ofvividornatural. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. - Tool
Call - Tool
Choice - Re-export commonly used types from openai-client-base for convenience ChatCompletionToolChoiceOption - Untagged union type
- Upload
Purpose - The intended purpose of the uploaded file. See the documentation on File purposes.