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, 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)
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-v4-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//!
211//! ### Other Providers
212//!
213//! | Provider | Feature Flag | Env Var |
214//! |----------|-------------|---------|
215//! | Amazon Bedrock | `bedrock` | AWS IAM credentials |
216//! | Azure AI Inference | `azure-ai` | `AZURE_AI_API_KEY` |
217//! | OpenRouter | `openrouter` | `OPENROUTER_API_KEY` |
218//!
219//! ## Features
220//!
221//! - Async streaming with backpressure
222//! - Tool/function calling support
223//! - Multimodal input (text, images, audio, video, PDF)
224//! - Generation configuration (temperature, top_p, etc.)
225//! - OpenAI-compatible APIs (Ollama, vLLM, etc.)
226//!
227//! ## OpenRouter Scope Boundary
228//!
229//! `OpenRouterClient` exposes the provider's native surfaces:
230//!
231//! - chat completions
232//! - responses
233//! - model discovery and credits
234//! - provider routing and fallback
235//! - OpenRouter plugins and built-in tools
236//! - exact provider metadata and annotations
237//!
238//! The generic `Llm` adapter exists for agent compatibility and covers text generation,
239//! streaming, reasoning parts, tool/function calling, and OpenRouter request options through
240//! `openrouter::OpenRouterRequestOptions`.
241//!
242//! Use the native OpenRouter APIs whenever you need exact request or response parity, discovery,
243//! or provider-specific features that do not fit the generic `LlmRequest` / `LlmResponse`
244//! shape without information loss.
245//!
246//! For end-to-end agentic validation, see the local `examples/openrouter` crate and the
247//! `adk-model/examples/openrouter_*` binaries.
248
249#[cfg(feature = "anthropic")]
250pub mod anthropic;
251pub(crate) mod attachment;
252#[cfg(feature = "azure-ai")]
253pub mod azure_ai;
254#[cfg(feature = "bedrock")]
255pub mod bedrock;
256/// Curated provider model catalog, lifecycle metadata, and recommended defaults.
257pub mod catalog;
258#[cfg(feature = "deepseek")]
259pub mod deepseek;
260/// Gemini model provider (Google AI Studio and Vertex AI).
261#[cfg(feature = "gemini")]
262pub mod gemini;
263#[cfg(feature = "groq")]
264pub mod groq;
265/// Mock LLM for testing without real API calls.
266pub mod mock;
267#[cfg(feature = "ollama")]
268pub mod ollama;
269#[cfg(feature = "openai")]
270pub mod openai;
271#[cfg(feature = "openai")]
272pub mod openai_compatible;
273#[cfg(feature = "openrouter")]
274pub mod openrouter;
275/// Conversion outcomes for content parts sent to a provider.
276pub mod part_conversion;
277
278/// Canonical provider identifiers and metadata.
279pub mod provider;
280/// Retry logic with exponential backoff for transient provider errors.
281pub mod retry;
282pub mod tool_call_parser;
283#[cfg(any(
284 feature = "openai",
285 feature = "ollama",
286 feature = "deepseek",
287 feature = "groq",
288 feature = "bedrock",
289 feature = "azure-ai"
290))]
291pub(crate) mod tool_result;
292pub mod usage_tracking;
293
294#[cfg(feature = "anthropic")]
295pub use anthropic::AnthropicClient;
296#[cfg(feature = "azure-ai")]
297pub use azure_ai::{AzureAIClient, AzureAIConfig};
298#[cfg(feature = "bedrock")]
299pub use bedrock::{BedrockClient, BedrockConfig};
300#[cfg(feature = "deepseek")]
301pub use deepseek::{DeepSeekClient, DeepSeekConfig};
302#[cfg(feature = "gemini")]
303pub use gemini::GeminiModel;
304#[cfg(feature = "groq")]
305pub use groq::{GroqClient, GroqConfig};
306pub use mock::MockLlm;
307#[cfg(feature = "ollama")]
308pub use ollama::{OllamaConfig, OllamaModel};
309#[cfg(feature = "openai")]
310pub use openai::{AzureConfig, AzureOpenAIClient, OpenAIClient, OpenAIConfig, ReasoningEffort};
311#[cfg(feature = "openai")]
312pub use openai_compatible::{OpenAICompatible, OpenAICompatibleConfig};
313#[cfg(feature = "openrouter")]
314pub use openrouter::{OpenRouterApiMode, OpenRouterClient, OpenRouterConfig};
315pub use provider::ModelProvider;
316pub use retry::RetryConfig;
317pub use retry::ServerRetryHint;