openai_tools/lib.rs
1//! # OpenAI Tools for Rust
2//!
3//! A comprehensive Rust library for interacting with OpenAI's APIs, providing easy-to-use
4//! interfaces for chat completions, responses, and various AI-powered functionalities.
5//! This crate offers both high-level convenience methods and low-level control for
6//! advanced use cases.
7//!
8//! ## Features
9//!
10//! ### Core APIs
11//! - **Chat Completions API**: Chat with streaming, function calling, and structured output
12//! - **Responses API**: Assistant-style interactions with multi-modal input
13//! - **Conversations API**: Long-running conversation state management
14//! - **Embedding API**: Text to vector embeddings for semantic search
15//! - **Realtime API**: WebSocket-based real-time audio/text streaming
16//! - **Live API**: Full-duplex speech-to-speech streaming over WebSocket
17//!
18//! ### Content & Media APIs
19//! - **Images API**: DALL-E image generation, editing, and variations
20//! - **Audio API**: Text-to-speech, transcription, and translation
21//! - **Moderations API**: Content policy violation detection
22//!
23//! ### Management APIs
24//! - **Models API**: List and retrieve available models
25//! - **Files API**: Upload and manage files for fine-tuning/batch
26//! - **Batch API**: Async bulk processing with 50% cost savings
27//! - **Fine-tuning API**: Custom model training
28//!
29//! ## Quick Start
30//!
31//! Add this to your `Cargo.toml`:
32//!
33//! ```toml
34//! [dependencies]
35//! openai-tools = "3.2"
36//! tokio = { version = "1.0", features = ["full"] }
37//! serde = { version = "1.0", features = ["derive"] }
38//! ```
39//!
40//! Set up your API key:
41//!
42//! ```bash
43//! export OPENAI_API_KEY="your-api-key-here"
44//! ```
45//!
46//! ## Basic Chat Completion
47//!
48//! ```rust,no_run
49//! use openai_tools::chat::request::ChatCompletion;
50//! use openai_tools::common::message::Message;
51//! use openai_tools::common::role::Role;
52//! use openai_tools::common::models::ChatModel;
53//!
54//! #[tokio::main]
55//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
56//! let mut chat = ChatCompletion::new();
57//! let messages = vec![
58//! Message::from_string(Role::User, "Hello! How are you?")
59//! ];
60//!
61//! let response = chat
62//! .model(ChatModel::Gpt4oMini) // Type-safe model selection
63//! .messages(messages)
64//! .temperature(0.7)
65//! .chat()
66//! .await?;
67//!
68//! println!("AI: {}", response.choices[0].message.content.as_ref().unwrap().text.as_ref().unwrap());
69//! Ok(())
70//! }
71//! ```
72//!
73//! ## Structured Output with JSON Schema
74//!
75//! ```rust,no_run
76//! use openai_tools::chat::request::ChatCompletion;
77//! use openai_tools::common::{message::Message, role::Role, structured_output::Schema, models::ChatModel};
78//! use serde::{Deserialize, Serialize};
79//!
80//! #[derive(Debug, Serialize, Deserialize)]
81//! struct PersonInfo {
82//! name: String,
83//! age: u32,
84//! occupation: String,
85//! }
86//!
87//! #[tokio::main]
88//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
89//! let mut chat = ChatCompletion::new();
90//!
91//! // Create JSON schema
92//! let mut schema = Schema::chat_json_schema("person_info");
93//! schema.add_property("name", "string", "Person's full name");
94//! schema.add_property("age", "number", "Person's age");
95//! schema.add_property("occupation", "string", "Person's job");
96//!
97//! let messages = vec![
98//! Message::from_string(Role::User,
99//! "Extract info: John Smith, 30, Software Engineer")
100//! ];
101//!
102//! let response = chat
103//! .model(ChatModel::Gpt4oMini)
104//! .messages(messages)
105//! .json_schema(schema)
106//! .chat()
107//! .await?;
108//!
109//! let person: PersonInfo = serde_json::from_str(
110//! response.choices[0].message.content.as_ref().unwrap().text.as_ref().unwrap()
111//! )?;
112//!
113//! println!("Extracted: {} ({}), {}", person.name, person.age, person.occupation);
114//! Ok(())
115//! }
116//! ```
117//!
118//! ## Function Calling with Tools
119//!
120//! ```rust,no_run
121//! use openai_tools::chat::request::ChatCompletion;
122//! use openai_tools::common::{message::Message, role::Role, tool::Tool, parameters::ParameterProperty, models::ChatModel};
123//!
124//! #[tokio::main]
125//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
126//! let mut chat = ChatCompletion::new();
127//!
128//! // Define a weather tool
129//! let weather_tool = Tool::function(
130//! "get_weather",
131//! "Get current weather for a location",
132//! vec![
133//! ("location", ParameterProperty::from_string("City name")),
134//! ("unit", ParameterProperty::from_string("Temperature unit (celsius/fahrenheit)")),
135//! ],
136//! false,
137//! );
138//!
139//! let messages = vec![
140//! Message::from_string(Role::User, "What's the weather in Tokyo?")
141//! ];
142//!
143//! let response = chat
144//! .model(ChatModel::Gpt4oMini)
145//! .messages(messages)
146//! .tools(vec![weather_tool])
147//! .chat()
148//! .await?;
149//!
150//! // Handle tool calls
151//! if let Some(tool_calls) = &response.choices[0].message.tool_calls {
152//! for call in tool_calls {
153//! println!("Tool: {}", call.function.name);
154//! if let Ok(args) = call.function.arguments_as_map() {
155//! println!("Args: {:?}", args);
156//! }
157//! // Execute the function and continue conversation...
158//! }
159//! }
160//! Ok(())
161//! }
162//! ```
163//!
164//! ## Multi-modal Input (Text + Image)
165//!
166//! Both Chat Completions API and Responses API support multi-modal messages.
167//! The same `Content` and `Message` types work with both APIs - serialization
168//! format differences are handled automatically.
169//!
170//! ### Chat Completions API
171//!
172//! ```rust,no_run
173//! use openai_tools::chat::request::ChatCompletion;
174//! use openai_tools::common::{message::{Message, Content}, role::Role, models::ChatModel};
175//!
176//! #[tokio::main]
177//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
178//! let mut chat = ChatCompletion::new();
179//!
180//! let message = Message::from_message_array(
181//! Role::User,
182//! vec![
183//! Content::from_text("What do you see in this image?"),
184//! Content::from_image_url("https://example.com/image.jpg"),
185//! ],
186//! );
187//!
188//! let response = chat
189//! .model(ChatModel::Gpt4oMini)
190//! .messages(vec![message])
191//! .chat()
192//! .await?;
193//!
194//! println!("AI: {}", response.choices[0].message.content.as_ref().unwrap().text.as_ref().unwrap());
195//! Ok(())
196//! }
197//! ```
198//!
199//! ### Responses API
200//!
201//! ```rust,no_run
202//! use openai_tools::responses::request::Responses;
203//! use openai_tools::common::{message::{Message, Content}, role::Role, models::ChatModel};
204//!
205//! #[tokio::main]
206//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
207//! let mut responses = Responses::new();
208//!
209//! responses
210//! .model(ChatModel::Gpt4oMini)
211//! .instructions("You are an image analysis assistant.");
212//!
213//! let message = Message::from_message_array(
214//! Role::User,
215//! vec![
216//! Content::from_text("What do you see in this image?"),
217//! Content::from_image_file("path/to/image.jpg"),
218//! ],
219//! );
220//!
221//! responses.messages(vec![message]);
222//!
223//! let response = responses.complete().await?;
224//! let text = response.output_text().unwrap();
225//! println!("Response: {}", text);
226//! Ok(())
227//! }
228//! ```
229//!
230//! ## Choosing the Right API
231//!
232//! | Use Case | Recommended API | Module |
233//! |----------|-----------------|--------|
234//! | Simple Q&A, chatbot | Chat Completions | [`chat`] |
235//! | Multi-turn assistant with state | Responses + Conversations | [`responses`], [`conversations`] |
236//! | Real-time voice interaction | Realtime | [`realtime`] |
237//! | Full-duplex voice with backend delegation | Live | [`live`] |
238//! | Semantic search, similarity | Embeddings | [`embedding`] |
239//! | Image generation (GPT Image) | Images | [`images`] |
240//! | Speech-to-text, TTS | Audio | [`audio`] |
241//! | Content moderation | Moderations | [`moderations`] |
242//! | Bulk processing (50% off) | Batch | [`batch`] |
243//! | Custom model training | Fine-tuning | [`fine_tuning`] |
244//!
245//! ## Module Structure
246//!
247//! ### Core APIs
248//!
249//! - [`chat`] - Chat Completions API (`/v1/chat/completions`)
250//! - [`chat::request`] - `ChatCompletion` builder
251//! - [`chat::response`] - Response types
252//!
253//! - [`responses`] - Responses API (`/v1/responses`)
254//! - [`responses::request`] - `Responses` builder with CRUD operations
255//! - [`responses::response`] - Response types
256//!
257//! - [`conversations`] - Conversations API (`/v1/conversations`)
258//! - [`conversations::request`] - `Conversations` client
259//! - [`conversations::response`] - Conversation and item types
260//!
261//! - [`embedding`] - Embeddings API (`/v1/embeddings`)
262//! - [`embedding::request`] - `Embedding` builder
263//! - [`embedding::response`] - Vector response types
264//!
265//! - [`realtime`] - Realtime API (WebSocket)
266//! - [`RealtimeClient`](realtime::RealtimeClient) and
267//! [`RealtimeSession`](realtime::RealtimeSession)
268//! - [`realtime::events`] - Client/server event types
269//!
270//! - [`live`] - Live API (WebSocket)
271//! - [`LiveClient`](live::LiveClient) and [`LiveSession`](live::LiveSession)
272//! - [`live::events`] - Client/server event types
273//!
274//! ### Content & Media APIs
275//!
276//! - [`images`] - Images API (`/v1/images`)
277//! - Generate, edit, create variations with the GPT Image models
278//!
279//! - [`videos`] - Videos API (`/v1/videos`)
280//! - Generate, poll, download and remix Sora video clips
281//!
282//! - [`audio`] - Audio API (`/v1/audio`)
283//! - Text-to-speech, transcription, translation
284//!
285//! - [`moderations`] - Moderations API (`/v1/moderations`)
286//! - Content policy violation detection
287//!
288//! ### Management APIs
289//!
290//! - [`models`] - Models API (`/v1/models`)
291//! - List and retrieve available models
292//!
293//! - [`files`] - Files API (`/v1/files`)
294//! - Upload/download files for fine-tuning and batch
295//!
296//! - [`batch`] - Batch API (`/v1/batches`)
297//! - Async bulk processing with 50% cost savings
298//!
299//! - [`fine_tuning`] - Fine-tuning API (`/v1/fine_tuning/jobs`)
300//! - Custom model training and management
301//!
302//! ### Shared Utilities
303//!
304//! - [`common`] - Shared types across all APIs
305//! - [`common::models`] - Type-safe model enums (`ChatModel`, `EmbeddingModel`, etc.)
306//! - [`common::message`] - Message and content structures
307//! - [`common::role`] - User roles (User, Assistant, System, Tool)
308//! - [`common::tool`] - Function calling definitions
309//! - [`common::auth`] - Authentication (OpenAI, Azure, custom)
310//! - [`common::errors`] - Error types
311//! - [`common::structured_output`] - JSON schema utilities
312//!
313//! ## Error Handling
314//!
315//! All operations return `Result<T, OpenAIToolError>`:
316//!
317//! ```rust,no_run
318//! use openai_tools::common::errors::OpenAIToolError;
319//! # use openai_tools::chat::request::ChatCompletion;
320//!
321//! # #[tokio::main]
322//! # async fn main() {
323//! # let mut chat = ChatCompletion::new();
324//! match chat.chat().await {
325//! Ok(response) => {
326//! println!("Success: {:?}", response.choices[0].message.content);
327//! },
328//! // Network/HTTP errors (connection failed, timeout, etc.)
329//! Err(OpenAIToolError::RequestError(e)) => {
330//! eprintln!("Network error: {}", e);
331//! },
332//! // JSON parsing errors (unexpected response format)
333//! Err(OpenAIToolError::SerdeJsonError(e)) => {
334//! eprintln!("JSON parse error: {}", e);
335//! },
336//! // WebSocket errors (Realtime API)
337//! Err(OpenAIToolError::WebSocketError(msg)) => {
338//! eprintln!("WebSocket error: {}", msg);
339//! },
340//! // Realtime API specific errors
341//! Err(OpenAIToolError::RealtimeError { code, message }) => {
342//! eprintln!("Realtime error [{}]: {}", code, message);
343//! },
344//! // Other errors
345//! Err(e) => eprintln!("Error: {}", e),
346//! }
347//! # }
348//! ```
349//!
350//! For API errors (rate limits, invalid requests), check the HTTP response status
351//! in `RequestError`.
352//!
353//! ## Provider Configuration
354//!
355//! This library supports multiple providers: OpenAI, Azure OpenAI, and OpenAI-compatible APIs.
356//!
357//! ### OpenAI (Default)
358//!
359//! ```bash
360//! export OPENAI_API_KEY="sk-..."
361//! ```
362//!
363//! ```rust,no_run
364//! use openai_tools::chat::request::ChatCompletion;
365//!
366//! let chat = ChatCompletion::new(); // Uses OPENAI_API_KEY
367//! ```
368//!
369//! ### Azure OpenAI
370//!
371//! ```bash
372//! export AZURE_OPENAI_API_KEY="..."
373//! export AZURE_OPENAI_BASE_URL="https://my-resource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2024-08-01-preview"
374//! ```
375//!
376//! ```rust,no_run
377//! use openai_tools::chat::request::ChatCompletion;
378//!
379//! // From environment variables
380//! let chat = ChatCompletion::azure().unwrap();
381//!
382//! // Or with explicit URL
383//! let chat = ChatCompletion::with_url(
384//! "https://my-resource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2024-08-01-preview",
385//! "api-key"
386//! );
387//! ```
388//!
389//! ### OpenAI-Compatible APIs (Ollama, vLLM, LocalAI)
390//!
391//! ```rust,no_run
392//! use openai_tools::chat::request::ChatCompletion;
393//!
394//! let chat = ChatCompletion::with_url("http://localhost:11434/v1", "ollama");
395//! ```
396//!
397//! ### Auto-Detect Provider
398//!
399//! ```rust,no_run
400//! use openai_tools::chat::request::ChatCompletion;
401//!
402//! // Uses Azure if AZURE_OPENAI_API_KEY is set, otherwise OpenAI
403//! let chat = ChatCompletion::detect_provider().unwrap();
404//! ```
405//!
406//! ## Type-Safe Model Selection
407//!
408//! All APIs use enum-based model selection for compile-time validation:
409//!
410//! ```rust,no_run
411//! use openai_tools::common::models::{ChatModel, EmbeddingModel, RealtimeModel, FineTuningModel};
412//! use openai_tools::chat::request::ChatCompletion;
413//! use openai_tools::embedding::request::Embedding;
414//!
415//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
416//! // Chat/Responses API
417//! let mut chat = ChatCompletion::new();
418//! chat.model(ChatModel::Gpt4oMini); // Cost-effective
419//! chat.model(ChatModel::Gpt4o); // Most capable
420//! chat.model(ChatModel::O3Mini); // Reasoning model
421//!
422//! // Embedding API
423//! let mut embedding = Embedding::new()?;
424//! embedding.model(EmbeddingModel::TextEmbedding3Small);
425//!
426//! // Custom/fine-tuned models
427//! chat.model(ChatModel::custom("ft:gpt-4o-mini:my-org::abc123"));
428//! # Ok(())
429//! # }
430//! ```
431//!
432
433pub mod audio;
434pub mod batch;
435pub mod chat;
436pub mod common;
437pub mod conversations;
438pub mod embedding;
439pub mod files;
440pub mod fine_tuning;
441pub mod images;
442pub mod live;
443pub mod models;
444pub mod moderations;
445pub mod realtime;
446pub mod responses;
447pub mod videos;