1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! # otari
//!
//! A unified Rust SDK for interacting with LLMs via the Otari gateway.
//!
//! This library provides a single, consistent interface to interact with
//! the [Otari gateway](https://github.com/mozilla-ai/otari-sdk-rust), a FastAPI-based
//! proxy that exposes an OpenAI-compatible API and routes requests to multiple
//! upstream LLM providers.
//!
//! ## Features
//!
//! - **Unified API**: Single interface for all models through the gateway
//! - **Streaming support**: Real-time token streaming with async streams
//! - **Tool calling**: Function/tool calling with automatic format conversion
//! - **Image support**: Send images to vision-capable models
//! - **Extended thinking**: Support for reasoning features
//! - **Reranking**: Document reranking support
//! - **Batch operations**: Create, retrieve, cancel, and list batch jobs
//! - **Moderation**: Content moderation via the gateway
//! - **Type-safe**: Strong Rust types with serde serialization
//!
//! ## Quick Start
//!
//! ```rust,no_run
//! use otari::{completion, Message, CompletionOptions};
//!
//! #[tokio::main]
//! async fn main() -> otari::Result<()> {
//! let messages = vec![Message::user("Hello, how are you?")];
//!
//! let response = completion(
//! "openai:gpt-4o-mini",
//! messages,
//! CompletionOptions::with_api_key("your-api-key")
//! .api_base("http://localhost:8000"),
//! ).await?;
//!
//! println!("{}", response.content().unwrap_or_default());
//! Ok(())
//! }
//! ```
//!
//! ## Streaming
//!
//! ```rust,no_run
//! use otari::{completion_stream, Message, CompletionOptions, ChunkAccumulator};
//! use futures::StreamExt;
//!
//! # async fn example() -> otari::Result<()> {
//! let messages = vec![Message::user("Tell me a story")];
//!
//! let mut stream = completion_stream(
//! "openai:gpt-4o-mini",
//! messages,
//! CompletionOptions::with_api_key("your-api-key")
//! .api_base("http://localhost:8000"),
//! ).await?;
//!
//! let mut accumulator = ChunkAccumulator::new();
//! while let Some(chunk) = stream.next().await {
//! let chunk = chunk?;
//! if let Some(content) = chunk.content() {
//! print!("{}", content);
//! }
//! accumulator.add(&chunk);
//! }
//!
//! // Access accumulated data
//! println!("\nFull response: {}", accumulator.content);
//! # Ok(())
//! # }
//! ```
//!
//! ## Tool Calling
//!
//! ```rust,no_run
//! use otari::{completion, Message, CompletionOptions, Tool, ToolChoice};
//! use serde_json::json;
//!
//! # async fn example() -> otari::Result<()> {
//! let weather_tool = Tool::function("get_weather", "Get the current weather")
//! .parameters(json!({
//! "type": "object",
//! "properties": {
//! "location": {
//! "type": "string",
//! "description": "City name"
//! }
//! },
//! "required": ["location"]
//! }))
//! .build();
//!
//! let messages = vec![Message::user("What's the weather in Paris?")];
//! let options = CompletionOptions::with_api_key("your-api-key")
//! .api_base("http://localhost:8000")
//! .tools(vec![weather_tool])
//! .tool_choice(ToolChoice::auto());
//!
//! let response = completion("openai:gpt-4o-mini", messages, options).await?;
//!
//! if let Some(tool_calls) = &response.choices[0].message.tool_calls {
//! for call in tool_calls {
//! println!("Function: {}, Args: {}", call.function.name, call.function.arguments);
//! }
//! }
//! # Ok(())
//! # }
//! ```
//!
//! ## Environment Variables
//!
//! - `OTARI_API_KEY`: API key for the Otari gateway
//! - `OTARI_API_BASE`: Base URL of the Otari gateway
// Re-export main types for convenience
pub use ;
pub use Otari;
pub use Config;
pub use ;
pub use ;