Skip to main content

openai_tools/embedding/
mod.rs

1//! # Embedding Module
2//!
3//! This module provides functionality for interacting with the OpenAI Embeddings API.
4//! It allows you to convert text into numerical vector representations (embeddings)
5//! that capture semantic meaning, enabling various NLP tasks such as semantic search,
6//! clustering, and similarity comparison.
7//!
8//! ## Key Features
9//!
10//! - **Text Embedding Generation**: Convert single or multiple texts into vector embeddings
11//! - **Multiple Input Formats**: Support for single text strings or arrays of texts
12//! - **Flexible Encoding**: Support for both `float` and `base64` encoding formats
13//! - **Various Model Support**: Compatible with OpenAI's embedding models (e.g., `text-embedding-3-small`, `text-embedding-3-large`)
14//! - **Multi-dimensional Output**: Support for 1D, 2D, and 3D embedding vectors
15//!
16//! ## Quick Start
17//!
18//! ```rust,no_run
19//! use openai_tools::embedding::request::Embedding;
20//! use openai_tools::common::models::EmbeddingModel;
21//!
22//! #[tokio::main]
23//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
24//!     // Initialize the embedding client
25//!     let mut embedding = Embedding::new()?;
26//!
27//!     // Configure the model and input text
28//!     embedding
29//!         .model(EmbeddingModel::TextEmbedding3Small)
30//!         .input_text("Hello, world!");
31//!
32//!     // Generate embedding
33//!     let response = embedding.embed().await?;
34//!
35//!     // Access the embedding vector
36//!     let vector = response.data[0].embedding.as_1d().unwrap();
37//!     println!("Embedding dimension: {}", vector.len());
38//!     Ok(())
39//! }
40//! ```
41//!
42//! ## Usage Examples
43//!
44//! ### Single Text Embedding
45//!
46//! ```rust,no_run
47//! use openai_tools::embedding::request::Embedding;
48//! use openai_tools::common::models::EmbeddingModel;
49//!
50//! #[tokio::main]
51//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
52//!     let mut embedding = Embedding::new()?;
53//!
54//!     embedding
55//!         .model(EmbeddingModel::TextEmbedding3Small)
56//!         .input_text("The quick brown fox jumps over the lazy dog.");
57//!
58//!     let response = embedding.embed().await?;
59//!
60//!     // The response contains embedding data
61//!     assert_eq!(response.object, "list");
62//!     assert_eq!(response.data.len(), 1);
63//!
64//!     let vector = response.data[0].embedding.as_1d().unwrap();
65//!     println!("Generated embedding with {} dimensions", vector.len());
66//!     Ok(())
67//! }
68//! ```
69//!
70//! ### Batch Text Embedding
71//!
72//! ```rust,no_run
73//! use openai_tools::embedding::request::Embedding;
74//! use openai_tools::common::models::EmbeddingModel;
75//!
76//! #[tokio::main]
77//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
78//!     let mut embedding = Embedding::new()?;
79//!
80//!     // Embed multiple texts at once
81//!     let texts = vec![
82//!         "Hello, world!",
83//!         "こんにちは,世界!",
84//!         "Bonjour le monde!",
85//!     ];
86//!
87//!     embedding
88//!         .model(EmbeddingModel::TextEmbedding3Small)
89//!         .input_text_array(texts);
90//!
91//!     let response = embedding.embed().await?;
92//!
93//!     // Each input text gets its own embedding
94//!     for (i, data) in response.data.iter().enumerate() {
95//!         let vector = data.embedding.as_1d().unwrap();
96//!         println!("Text {}: {} dimensions", i, vector.len());
97//!     }
98//!     Ok(())
99//! }
100//! ```
101//!
102//! ### Using Different Encoding Formats
103//!
104//! ```rust,no_run
105//! use openai_tools::embedding::request::Embedding;
106//! use openai_tools::common::models::EmbeddingModel;
107//!
108//! #[tokio::main]
109//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
110//!     let mut embedding = Embedding::new()?;
111//!
112//!     embedding
113//!         .model(EmbeddingModel::TextEmbedding3Small)
114//!         .input_text("Sample text for embedding")
115//!         .encoding_format("float"); // or "base64"
116//!
117//!     let response = embedding.embed().await?;
118//!     println!("Model used: {}", response.model);
119//!     println!("Token usage: {:?}", response.usage);
120//!     Ok(())
121//! }
122//! ```
123//!
124//! ## Supported Models
125//!
126//! | Model | Dimensions | Description |
127//! |-------|------------|-------------|
128//! | `text-embedding-3-small` | 1536 | Efficient model for most use cases |
129//! | `text-embedding-3-large` | 3072 | Higher quality embeddings for demanding tasks |
130//! | `text-embedding-ada-002` | 1536 | Legacy model (still supported) |
131//!
132//! ## Response Structure
133//!
134//! The embedding response contains:
135//! - `object`: Always "list" for embedding responses
136//! - `data`: Array of embedding objects, each containing:
137//!   - `object`: Type identifier ("embedding")
138//!   - `embedding`: The vector representation (1D, 2D, or 3D)
139//!   - `index`: Position in the input array
140//! - `model`: The model used for embedding
141//! - `usage`: Token usage information
142
143pub mod request;
144pub mod response;
145
146#[cfg(test)]
147mod tests {
148    use crate::common::models::EmbeddingModel;
149    use crate::embedding::request::Embedding;
150
151    #[test]
152    fn test_embedding_builder_model() {
153        let mut embedding = Embedding::new().expect("Embedding initialization should succeed");
154        embedding.model(EmbeddingModel::TextEmbedding3Small);
155        // Model is set internally, we can verify by serialization
156    }
157
158    #[test]
159    fn test_embedding_builder_input_text() {
160        let mut embedding = Embedding::new().expect("Embedding initialization should succeed");
161        embedding.input_text("Hello, world!");
162        // Input is set internally
163    }
164
165    #[test]
166    fn test_embedding_builder_input_text_array() {
167        let mut embedding = Embedding::new().expect("Embedding initialization should succeed");
168        let texts = vec!["Text 1", "Text 2", "Text 3"];
169        embedding.input_text_array(texts);
170        // Input array is set internally
171    }
172
173    #[test]
174    fn test_embedding_builder_encoding_format_float() {
175        let mut embedding = Embedding::new().expect("Embedding initialization should succeed");
176        embedding.encoding_format("float");
177        // Encoding format is set internally
178    }
179
180    #[test]
181    fn test_embedding_builder_encoding_format_base64() {
182        let mut embedding = Embedding::new().expect("Embedding initialization should succeed");
183        embedding.encoding_format("base64");
184        // Encoding format is set internally
185    }
186
187    #[test]
188    #[should_panic(expected = "encoding_format must be either 'float' or 'base64'")]
189    fn test_embedding_builder_encoding_format_invalid() {
190        let mut embedding = Embedding::new().expect("Embedding initialization should succeed");
191        embedding.encoding_format("invalid"); // Should panic
192    }
193
194    #[test]
195    fn test_embedding_builder_chain() {
196        let mut embedding = Embedding::new().expect("Embedding initialization should succeed");
197        embedding.model(EmbeddingModel::TextEmbedding3Small).input_text("Hello!").encoding_format("float");
198        // Method chaining works
199    }
200}