Skip to main content

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;