adk_model/lib.rs
1//! # adk-model
2#![allow(clippy::result_large_err)]
3#![deny(missing_docs)]
4//!
5//! LLM model integrations for ADK (Gemini, OpenAI, OpenRouter, Anthropic, DeepSeek, Groq,
6//! Ollama, Fireworks AI, Together AI, Mistral AI, Perplexity, Cerebras, SambaNova, Amazon
7//! Bedrock, Azure AI Inference).
8//!
9//! ## Overview
10//!
11//! This crate provides LLM implementations for ADK agents. Currently supports:
12//!
13//! - [`GeminiModel`] - Google's Gemini models (3 Pro, 2.5 Flash, etc.)
14//! - `OpenAIClient` - OpenAI models (GPT-5, GPT-5-mini, o3, etc.) — requires `openai` feature
15//! - `AzureOpenAIClient` - Azure OpenAI Service — requires `openai` feature
16//! - `OpenAICompatible` - Any OpenAI-compatible API (xAI, Fireworks, Together, Mistral, Perplexity, Cerebras, SambaNova, OrcaRouter, or custom) — requires `openai` feature, use `OpenAICompatibleConfig` presets
17//! - `AnthropicClient` - Anthropic Claude models — requires `anthropic` feature
18//! - `DeepSeekClient` - DeepSeek models — requires `deepseek` feature
19//! - `GroqClient` - Groq ultra-fast inference — requires `groq` feature
20//! - `OpenRouterClient` - OpenRouter-native chat, responses, and discovery APIs — requires `openrouter` feature
21//! - `OllamaModel` - Local LLMs via Ollama — requires `ollama` feature
22//! - `BedrockClient` - Amazon Bedrock via AWS SDK — requires `bedrock` feature
23//! - `AzureAIClient` - Azure AI Inference endpoints — requires `azure-ai` feature
24//! - [`MockLlm`] - Mock LLM for testing
25//!
26//! ## Quick Start
27//!
28//! ### Gemini
29//!
30//! ```rust,no_run
31//! use adk_model::GeminiModel;
32//! use std::sync::Arc;
33//!
34//! let api_key = std::env::var("GOOGLE_API_KEY").unwrap();
35//! let model = GeminiModel::new(&api_key, "gemini-2.5-flash").unwrap();
36//! ```
37//!
38//! ### OpenAI
39//!
40//! ```rust,ignore
41//! use adk_model::openai::{OpenAIClient, OpenAIConfig};
42//!
43//! let model = OpenAIClient::new(OpenAIConfig::new(
44//! std::env::var("OPENAI_API_KEY").unwrap(),
45//! "gpt-5-mini",
46//! )).unwrap();
47//! ```
48//!
49//! ### OpenRouter
50//!
51//! ```rust,ignore
52//! use adk_core::{Content, Llm, LlmRequest};
53//! use adk_model::openrouter::{OpenRouterClient, OpenRouterConfig};
54//! use futures::StreamExt;
55//!
56//! let client = OpenRouterClient::new(
57//! OpenRouterConfig::new(
58//! std::env::var("OPENROUTER_API_KEY").unwrap(),
59//! "openai/gpt-4.1-mini",
60//! )
61//! .with_http_referer("https://github.com/zavora-ai/adk-rust")
62//! .with_title("ADK-Rust"),
63//! ).unwrap();
64//!
65//! let request = LlmRequest::new(
66//! "openai/gpt-4.1-mini",
67//! vec![Content::new("user").with_text("Reply in one short sentence.")],
68//! );
69//!
70//! # tokio_test::block_on(async {
71//! let mut stream = client.generate_content(request, true).await.unwrap();
72//! while let Some(item) = stream.next().await {
73//! let _response = item.unwrap();
74//! }
75//! # });
76//! ```
77//!
78//! Native OpenRouter APIs such as model discovery, credits, routing configuration, plugins, and
79//! exact Responses payload access remain available on `OpenRouterClient` itself.
80//!
81//! ### Anthropic
82//!
83//! ```rust,ignore
84//! use adk_model::anthropic::{AnthropicClient, AnthropicConfig};
85//!
86//! let model = AnthropicClient::new(AnthropicConfig::new(
87//! std::env::var("ANTHROPIC_API_KEY").unwrap(),
88//! "claude-sonnet-4-5-20250929",
89//! )).unwrap();
90//! ```
91//!
92//! ### DeepSeek
93//!
94//! ```rust,ignore
95//! use adk_model::deepseek::{DeepSeekClient, DeepSeekConfig};
96//!
97//! // Chat model
98//! let chat = DeepSeekClient::chat(std::env::var("DEEPSEEK_API_KEY").unwrap()).unwrap();
99//!
100//! // Reasoner with thinking mode
101//! let reasoner = DeepSeekClient::reasoner(std::env::var("DEEPSEEK_API_KEY").unwrap()).unwrap();
102//! ```
103//!
104//! ### OpenAI-Compatible Providers (Fireworks, Together, Mistral, Perplexity, Cerebras, SambaNova, xAI, OrcaRouter)
105//!
106//! All OpenAI-compatible providers use `OpenAICompatible` with provider presets:
107//!
108//! ```rust,ignore
109//! use adk_model::openai_compatible::{OpenAICompatible, OpenAICompatibleConfig};
110//!
111//! // Fireworks AI
112//! let model = OpenAICompatible::new(OpenAICompatibleConfig::fireworks(
113//! std::env::var("FIREWORKS_API_KEY").unwrap(),
114//! "accounts/fireworks/models/llama-v3p1-8b-instruct",
115//! )).unwrap();
116//!
117//! // Together AI
118//! let model = OpenAICompatible::new(OpenAICompatibleConfig::together(
119//! std::env::var("TOGETHER_API_KEY").unwrap(),
120//! "meta-llama/Llama-3.3-70B-Instruct-Turbo",
121//! )).unwrap();
122//!
123//! // Or any custom OpenAI-compatible endpoint
124//! let model = OpenAICompatible::new(
125//! OpenAICompatibleConfig::new("your-api-key", "your-model")
126//! .with_base_url("https://your-endpoint.com/v1")
127//! .with_provider_name("my-provider"),
128//! ).unwrap();
129//! ```
130//!
131//! ### Amazon Bedrock
132//!
133//! ```rust,ignore
134//! use adk_model::bedrock::{BedrockClient, BedrockConfig};
135//!
136//! // Uses AWS IAM credentials from the environment (no API key needed)
137//! let config = BedrockConfig::new("us-east-1", "anthropic.claude-sonnet-4-20250514-v1:0");
138//! let model = BedrockClient::new(config).await.unwrap();
139//! ```
140//!
141//! ### Azure AI Inference
142//!
143//! ```rust,ignore
144//! use adk_model::azure_ai::{AzureAIClient, AzureAIConfig};
145//!
146//! let model = AzureAIClient::new(AzureAIConfig::new(
147//! "https://my-endpoint.eastus.inference.ai.azure.com",
148//! std::env::var("AZURE_AI_API_KEY").unwrap(),
149//! "meta-llama-3.1-8b-instruct",
150//! )).unwrap();
151//! ```
152//!
153//! ### Ollama (Local)
154//!
155//! ```rust,ignore
156//! use adk_model::ollama::{OllamaModel, OllamaConfig};
157//!
158//! // Default: localhost:11434
159//! let model = OllamaModel::new(OllamaConfig::new("llama3.2")).unwrap();
160//! ```
161//!
162//! ## Supported Models
163//!
164//! ### Gemini
165//! | Model | Description |
166//! |-------|-------------|
167//! | `gemini-3.7-flash` | Current balanced default (1M context) |
168//! | `gemini-3.6-flash` | Previous balanced generation (1M context) |
169//! | `gemini-3.5-flash-lite` | Cost-efficient high-volume model (1M context) |
170//!
171//! ### OpenAI
172//! | Model | Description |
173//! |-------|-------------|
174//! | `gpt-5.6-terra` | Balanced default for agents |
175//! | `gpt-5.6-sol` | Flagship reasoning and coding |
176//! | `gpt-5.6-luna` | Cost-efficient high-volume model |
177//!
178//! ### Anthropic
179//! | Model | Description |
180//! |-------|-------------|
181//! | `claude-sonnet-5` | Balanced default |
182//! | `claude-opus-5` | Flagship capability |
183//! | `claude-fable-5` | Premium creative and long-form work |
184//!
185//! ### DeepSeek
186//! | Model | Description |
187//! |-------|-------------|
188//! | `deepseek-flash` | Fast balanced default |
189//! | `deepseek-v4-pro` | Advanced reasoning |
190//!
191//! ### Groq
192//! | Model | Description |
193//! |-------|-------------|
194//! | `openai/gpt-oss-120b` | Production default via Groq LPU |
195//! | `openai/gpt-oss-20b` | Lower-latency economy model |
196//!
197//! ### OpenAI-Compatible Providers (via `openai` feature)
198//!
199//! Use `OpenAICompatibleConfig` presets — one client, one feature flag:
200//!
201//! | Provider | Preset | Env Var |
202//! |----------|--------|---------|
203//! | Fireworks AI | `OpenAICompatibleConfig::fireworks()` | `FIREWORKS_API_KEY` |
204//! | Together AI | `OpenAICompatibleConfig::together()` | `TOGETHER_API_KEY` |
205//! | Mistral AI | `OpenAICompatibleConfig::mistral()` | `MISTRAL_API_KEY` |
206//! | Perplexity | `OpenAICompatibleConfig::perplexity()` | `PERPLEXITY_API_KEY` |
207//! | Cerebras | `OpenAICompatibleConfig::cerebras()` | `CEREBRAS_API_KEY` |
208//! | SambaNova | `OpenAICompatibleConfig::sambanova()` | `SAMBANOVA_API_KEY` |
209//! | xAI (Grok) | `OpenAICompatibleConfig::xai()` | `XAI_API_KEY` |
210//! | OrcaRouter | `OpenAICompatibleConfig::orcarouter()` | `ORCAROUTER_API_KEY` |
211//!
212//! ### Other Providers
213//!
214//! | Provider | Feature Flag | Env Var |
215//! |----------|-------------|---------|
216//! | Amazon Bedrock | `bedrock` | AWS IAM credentials |
217//! | Azure AI Inference | `azure-ai` | `AZURE_AI_API_KEY` |
218//! | OpenRouter | `openrouter` | `OPENROUTER_API_KEY` |
219//!
220//! ## Features
221//!
222//! - Async streaming with backpressure
223//! - Tool/function calling support
224//! - Multimodal input (text, images, audio, video, PDF)
225//! - Generation configuration (temperature, top_p, etc.)
226//! - OpenAI-compatible APIs (Ollama, vLLM, etc.)
227//!
228//! ## OpenRouter Scope Boundary
229//!
230//! `OpenRouterClient` exposes the provider's native surfaces:
231//!
232//! - chat completions
233//! - responses
234//! - model discovery and credits
235//! - provider routing and fallback
236//! - OpenRouter plugins and built-in tools
237//! - exact provider metadata and annotations
238//!
239//! The generic `Llm` adapter exists for agent compatibility and covers text generation,
240//! streaming, reasoning parts, tool/function calling, and OpenRouter request options through
241//! `openrouter::OpenRouterRequestOptions`.
242//!
243//! Use the native OpenRouter APIs whenever you need exact request or response parity, discovery,
244//! or provider-specific features that do not fit the generic `LlmRequest` / `LlmResponse`
245//! shape without information loss.
246//!
247//! For end-to-end agentic validation, see the local `examples/openrouter` crate and the
248//! `adk-model/examples/openrouter_*` binaries.
249
250#[cfg(feature = "anthropic")]
251pub mod anthropic;
252pub(crate) mod attachment;
253#[cfg(feature = "azure-ai")]
254pub mod azure_ai;
255#[cfg(feature = "bedrock")]
256pub mod bedrock;
257/// Curated provider model catalog, lifecycle metadata, and recommended defaults.
258pub mod catalog;
259#[cfg(feature = "deepseek")]
260pub mod deepseek;
261/// Gemini model provider (Google AI Studio and Vertex AI).
262#[cfg(feature = "gemini")]
263pub mod gemini;
264#[cfg(feature = "groq")]
265pub mod groq;
266/// Mock LLM for testing without real API calls.
267pub mod mock;
268#[cfg(feature = "ollama")]
269pub mod ollama;
270#[cfg(feature = "openai")]
271pub mod openai;
272#[cfg(feature = "openai")]
273pub mod openai_compatible;
274#[cfg(feature = "opencode")]
275pub mod opencode;
276#[cfg(feature = "openrouter")]
277pub mod openrouter;
278/// Conversion outcomes for content parts sent to a provider.
279pub mod part_conversion;
280
281/// Canonical provider identifiers and metadata.
282pub mod provider;
283/// Retry logic with exponential backoff for transient provider errors.
284pub mod retry;
285#[cfg(any(feature = "openai", feature = "deepseek", feature = "azure-ai"))]
286mod sse;
287#[cfg(any(
288 feature = "openai",
289 feature = "anthropic",
290 feature = "deepseek",
291 feature = "groq",
292 feature = "bedrock",
293 feature = "azure-ai"
294))]
295pub(crate) mod tool_args;
296pub mod tool_call_parser;
297#[cfg(any(
298 feature = "openai",
299 feature = "ollama",
300 feature = "deepseek",
301 feature = "groq",
302 feature = "bedrock",
303 feature = "azure-ai"
304))]
305pub(crate) mod tool_result;
306pub mod usage_tracking;
307
308#[cfg(feature = "anthropic")]
309pub use anthropic::AnthropicClient;
310#[cfg(feature = "azure-ai")]
311pub use azure_ai::{AzureAIClient, AzureAIConfig};
312#[cfg(feature = "bedrock")]
313pub use bedrock::{BedrockClient, BedrockConfig};
314#[cfg(feature = "deepseek")]
315pub use deepseek::{DeepSeekClient, DeepSeekConfig};
316#[cfg(feature = "gemini")]
317pub use gemini::GeminiModel;
318#[cfg(feature = "groq")]
319pub use groq::{GroqClient, GroqConfig};
320pub use mock::MockLlm;
321#[cfg(feature = "ollama")]
322pub use ollama::{OllamaConfig, OllamaModel};
323#[cfg(feature = "openai")]
324pub use openai::{AzureConfig, AzureOpenAIClient, OpenAIClient, OpenAIConfig, ReasoningEffort};
325#[cfg(feature = "openai")]
326pub use openai_compatible::{OpenAICompatible, OpenAICompatibleConfig, ReasoningReplayField};
327#[cfg(feature = "opencode")]
328pub use opencode::{OpenCodeApi, OpenCodeClient, OpenCodeConfig, OpenCodeService};
329#[cfg(feature = "openrouter")]
330pub use openrouter::{OpenRouterApiMode, OpenRouterClient, OpenRouterConfig};
331pub use provider::ModelProvider;
332pub use retry::RetryConfig;
333pub use retry::ServerRetryHint;