Skip to main content

oai_sdk/
lib.rs

1// Copyright 2026 Cloudflavor GmbH
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6
7// http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! # Library Name Note
16//!
17//! This library is published as `ollama-api-rs` on crates.io.
18//! Users should write `use oai_sdk::{ModelClient, ChatRequest, Message};`
19//!
20//! # Features
21//!
22//! - **Async/await support** - Built on top of Tokio for efficient async operations
23//! - **Easy configuration** - Simple client setup with `ModelClient::builder()`
24//! - **Streaming responses** - Real-time streaming for both chat and generation
25//! - **Full Ollama API compatibility** - Complete coverage of all Ollama API endpoints
26//! - **Modular design** - Separate modules for chat, generate, embed, and model operations
27//! - **Comprehensive error handling** - Custom error types with detailed context
28//! - **Tool calling** - Support for function/tool calling in chat completions
29//! - **Structured outputs** - JSON schema validation support for responses
30//! - **Model lifecycle management** - Load/unload models programmatically
31//! - **Blob management** - Push and check model blobs
32//! - **Batch embeddings** - Efficient batch processing for embeddings
33//!
34//! # Examples
35//!
36//! ## Basic Chat Completion
37//!
38//! ```no_run
39//! use oai_sdk::{ModelClient, ChatRequest, Message};
40//!
41//! #[tokio::main]
42//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
43//!     let client = ModelClient::builder()
44//!         .base_url("http://localhost:11434")
45//!         .build()?;
46//!
47//!     let request = ChatRequest {
48//!         model: "llama3.1:8b".to_string(),
49//!         messages: vec![Message::user("Why is the sky blue?")],
50//!         stream: false,
51//!         ..Default::default()
52//!     };
53//!
54//!     let response = client.chat(request).await?;
55//!     println!("{}", response.message.content);
56//!
57//!     Ok(())
58//! }
59//! ```
60//!
61//! ## Streaming Chat
62//!
63//! ```no_run
64//! use oai_sdk::{ModelClient, ChatRequest, Message};
65//! use tokio_stream::StreamExt;
66//!
67//! #[tokio::main]
68//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
69//!     let client = ModelClient::builder()
70//!         .base_url("http://localhost:11434")
71//!         .build()?;
72//!
73//!     let request = ChatRequest {
74//!         model: "llama3.1:8b".to_string(),
75//!         messages: vec![Message::user("Write a story about Rust")],
76//!         stream: true,
77//!         ..Default::default()
78//!     };
79//!
80//!     let mut stream = client.chat_stream(request).await?;
81//!     while let Some(result) = stream.next().await {
82//!         match result {
83//!             Ok(response) => print!("{}", response.message.content),
84//!             Err(e) => eprintln!("Error: {}", e),
85//!         }
86//!     }
87//!
88//!     Ok(())
89//! }
90//! ```
91//!
92//! ## Text Generation
93//!
94//! ```no_run
95//! use oai_sdk::{ModelClient, GenerateRequest};
96//!
97//! #[tokio::main]
98//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
99//!     let client = ModelClient::builder()
100//!         .base_url("http://localhost:11434")
101//!         .build()?;
102//!
103//!     let request = GenerateRequest {
104//!         model: "llama3.1:8b".to_string(),
105//!         prompt: "Why is the sky blue?".to_string(),
106//!         ..Default::default()
107//!     };
108//!
109//!     let response = client.generate(request).await?;
110//!     println!("{}", response.response);
111//!
112//!     Ok(())
113//! }
114//! ```
115//!
116//! ## Embeddings
117//!
118//! ```no_run
119//! use oai_sdk::{ModelClient, EmbedRequest, EmbedInput};
120//!
121//! #[tokio::main]
122//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
123//!     let client = ModelClient::builder()
124//!         .base_url("http://localhost:11434")
125//!         .build()?;
126//!
127//!     let request = EmbedRequest {
128//!         model: "llama3:8b".to_string(),
129//!         input: EmbedInput::Single("Hello, world!".to_string()),
130//!         truncate: Some(true),
131//!         ..Default::default()
132//!     };
133//!
134//!     let response = client.embed(request).await?;
135//!     println!("Embeddings: {:?}", response.embeddings);
136//!
137//!     Ok(())
138//! }
139//! ```
140//!
141//! ## Tool Calling
142//!
143//! ```no_run
144//! use oai_sdk::{ModelClient, ChatRequest, Message, Tool, ToolFunction};
145//! use serde_json::json;
146//!
147//! #[tokio::main]
148//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
149//!     let client = ModelClient::builder()
150//!         .base_url("http://localhost:11434")
151//!         .build()?;
152//!
153//!     let tools = vec![
154//!         Tool {
155//!             tool_type: "function".to_string(),
156//!             function: ToolFunction {
157//!                 name: "get_current_weather".to_string(),
158//!                 description: "Get the current weather for a location".to_string(),
159//!                 parameters: json!({
160//!                     "type": "object",
161//!                     "properties": {
162//!                         "location": {
163//!                             "type": "string",
164//!                             "description": "The location to get the weather for"
165//!                         },
166//!                         "format": {
167//!                             "type": "string",
168//!                             "enum": ["celsius", "fahrenheit"]
169//!                         }
170//!                     },
171//!                     "required": ["location", "format"]
172//!                 }),
173//!             }
174//!         }
175//!     ];
176//!
177//!     let request = ChatRequest {
178//!         model: "llama3.1:8b".to_string(),
179//!         messages: vec![Message::user("What is the weather in Tokyo?")],
180//!         tools: Some(tools),
181//!         ..Default::default()
182//!     };
183//!
184//!     let response = client.chat(request).await?;
185//!     if let Some(tool_calls) = response.message.tool_calls {
186//!         for tool_call in tool_calls {
187//!             println!("Tool call: {}", tool_call.function.name);
188//!         }
189//!     }
190//!
191//!     Ok(())
192//! }
193//! ```
194//!
195//! ## Model Management
196//!
197//! ```no_run
198//! use oai_sdk::{ModelClient, ShowModelRequest, CopyModelRequest, DeleteModelRequest};
199//!
200//! #[tokio::main]
201//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
202//!     let client = ModelClient::builder()
203//!         .base_url("http://localhost:11434")
204//!         .build()?;
205//!
206//!     let models = client.list_models().await?;
207//!     for model in models {
208//!         println!("Model: {}", model.name);
209//!     }
210//!
211//!     let request = ShowModelRequest {
212//!         model: "llama3.1:8b".to_string(),
213//!         verbose: Some(true),
214//!     };
215//!     let info = client.show_model(request).await?;
216//!     println!("Model info: {:?}", info);
217//!
218//!     let copy_req = CopyModelRequest {
219//!         source: "llama3.1:8b".to_string(),
220//!         destination: "llama3-backup".to_string(),
221//!     };
222//!     client.copy_model(copy_req).await?;
223//!
224//!     let delete_req = DeleteModelRequest {
225//!         model: "llama3-backup".to_string(),
226//!     };
227//!     client.delete_model(delete_req).await?;
228//!
229//!     Ok(())
230//! }
231//! ```
232//!
233//! ## OpenAI-Compatible Endpoints
234//!
235//! ```no_run
236//! use oai_sdk::{ModelClient, ChatCompletionsRequest, ChatMessage};
237//!
238//! #[tokio::main]
239//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
240//!     let client = ModelClient::builder()
241//!         .base_url("http://localhost:11434")
242//!         .build()?;
243//!
244//!     let request = ChatCompletionsRequest {
245//!         model: "llama3.1:8b".to_string(),
246//!         messages: vec![ChatMessage::user("Why is the sky blue?")],
247//!         stream: Some(false),
248//!         ..Default::default()
249//!     };
250//!
251//!     let response = client.chat_completions(request).await?;
252//!     println!("{}", response.choices[0].message.content);
253//!
254//!     Ok(())
255//! }
256//! ```
257//!
258//! ## Model Lifecycle (requires `local` feature)
259//!
260//! ```no_run
261//! # #[cfg(feature = "local")]
262//! # {
263//! use oai_sdk::ModelClient;
264//!
265//! # #[tokio::main]
266//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
267//!     let client = ModelClient::builder()
268//!         .base_url("http://localhost:11434")
269//!         .build()?;
270//!
271//!     client.load_model("llama3.1:8b").await?;
272//!     println!("Model loaded");
273//!
274//!     client.unload_model("llama3.1:8b").await?;
275//!     println!("Model unloaded");
276//!
277//!     Ok(())
278//! # }
279//! # }
280//! ```
281//!
282//! ## API Modules
283//!
284//! - [`chat`](crate::chat) - Chat completion with streaming and tool support
285//! - [`generate`](crate::generate) - Text generation with streaming support
286//! - [`embed`](crate::embed) - Single and batch embeddings
287//! - [`model`](crate::model) - Model management (CRUD, pull, push, running models)
288//! - [`openai`](crate::openai) - OpenAI-compatible endpoints (chat, embeddings, responses)
289//! - [`client`](crate::client) - Core client, blob management, model lifecycle
290//! - [`error`](crate::error) - Error types and handling
291
292mod chat;
293mod client;
294mod embed;
295mod error;
296mod generate;
297mod model;
298mod openai;
299
300pub use chat::{
301    ChatRequest, ChatResponse, Format, Message, Tool, ToolCall, ToolCallFunction, ToolFunction,
302};
303pub use client::{ModelClient, ModelClientBuilder};
304pub use embed::{EmbedInput, EmbedRequest, EmbedResponse, EmbeddingsRequest, EmbeddingsResponse};
305pub use error::{OllamaError, Result};
306pub use generate::{GenerateRequest, GenerateResponse};
307pub use model::{
308    CopyModelRequest, CreateModelRequest, DeleteModelRequest, License, ListModelsResponse,
309    ListRunningModelsResponse, ModelDetails, ModelInfo, PullModelRequest, PushModelRequest,
310    RunningModel, ShowModelRequest, ShowModelResponse, StatusResponse, VersionResponse,
311};
312pub use openai::{
313    ChatCompletionsRequest, ChatCompletionsResponse, ChatMessage, OpenAIEmbedding,
314    OpenAIEmbeddingsInput, OpenAIEmbeddingsRequest, OpenAIEmbeddingsResponse, ResponsesRequest,
315    ResponsesResponse,
316};