모델 제공자(클라우드)
ADK-Rust은 adk-model 크레이트를 통해 여러 클라우드 LLM 제공자를 지원합니다. 모든 제공자는 Llm 트레이트를 구현하므로 에이전트에서 서로 교체하여 사용할 수 있습니다.
개요
┌─────────────────────────────────────────────────────────────────────┐
│ Cloud Model Providers │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ • Gemini (Google) ⭐ Default - Multimodal, large context │
│ • OpenAI (GPT-5) 🔥 Popular - Best ecosystem │
│ • Anthropic (Claude) 🧠 Smart - Best reasoning │
│ • DeepSeek 💭 Thinking - Chain-of-thought, cheap │
│ • Groq ⚡ Ultra-Fast - Fastest inference │
│ │
│ For local/offline models, see: │
│ • Ollama → ollama.md │
│ • mistral.rs → mistralrs.md │
│ │
└─────────────────────────────────────────────────────────────────────┘
빠른 비교
| 제공업체 | 최적 용도 | 속도 | 비용 | 주요 기능 |
|---|---|---|---|---|
| Gemini | 일반적인 사용 | ⚡⚡⚡ | 💰 | 멀티모달, 대규모 컨텍스트, 사고 |
| OpenAI | 신뢰성 | ⚡⚡ | 💰💰 | 최고의 생태계 |
| Anthropic | 복잡한 추론 | ⚡⚡ | 💰💰 | 가장 안전하고 신중함 |
| DeepSeek | 사고 연쇄 | ⚡⚡ | 💰 | 사고 모드, 저렴함 |
| Groq | 속도 중시 | ⚡⚡⚡⚡ | 💰 | 가장 빠른 추론 |
1단계: 설치
필요한 공급자를 Cargo.toml에 추가합니다:
[dependencies]
# Pick one or more providers:
adk-model = { version = "2.1.0", features = ["gemini"] } # Google Gemini (default)
adk-model = { version = "2.1.0", features = ["openai"] } # OpenAI GPT-5
adk-model = { version = "2.1.0", features = ["anthropic"] } # Anthropic Claude
adk-model = { version = "2.1.0", features = ["deepseek"] } # DeepSeek
adk-model = { version = "2.1.0", features = ["groq"] } # Groq (ultra-fast)
# Or all cloud providers at once:
adk-model = { version = "2.1.0", features = ["all-providers"] }
2단계: API 키 설정
export GOOGLE_API_KEY="your-key" # Gemini
export OPENAI_API_KEY="your-key" # OpenAI
export ANTHROPIC_API_KEY="your-key" # Anthropic
export DEEPSEEK_API_KEY="your-key" # DeepSeek
export GROQ_API_KEY="your-key" # Groq
스키마 정규화
각 공급자는 요청 시 MCP 도구 스키마를 자동으로 정규화합니다. 별도로 수행할 작업은 없습니다 — 투명하게 작동합니다. 하지만 내부적으로는 다음과 같은 작업이 수행됩니다:
| 제공자 | 스키마 어댑터 | 동작 |
|---|---|---|
| Gemini | GeminiSchemaAdapter | 공격적: $ref을 해결하고, 결합자를 축약하며, 지원되지 않는 키워드를 제거함 |
| OpenAI (엄격) | OpenAiStrictSchemaAdapter | 구조를 유지하고 additionalProperties: false을 추가함 |
| OpenAI | OpenAiSchemaAdapter | 최소한의 안전한 수정 |
| Anthropic | AnthropicSchemaAdapter | 거의 그대로 통과 |
| DeepSeek | GenericSchemaAdapter | 보수적인 안전 변환 |
| Ollama | GenericSchemaAdapter | 보수적인 안전 변환 |
어댑터에 프로그래밍 방식으로 Llm 트레이트를 통해 액세스합니다:
use adk_core::{Llm, SchemaAdapter};
let adapter = model.schema_adapter();
let normalized = adapter.normalize_schema(raw_schema);
전체 문서는 스키마 정규화를 참조하세요.
Gemini (Google) ⭐ 기본값
적합한 용도: 범용 작업, 멀티모달 작업, 대규모 문서
주요 특징:
- 🖼️ 기본 멀티모달 지원(이미지, 동영상, 오디오, PDF)
- 📚 최대 2M 토큰 컨텍스트 창
- 🧠 사고 모드: 사고 서명을 지원하는 수준 기반(Gemini 3) 및 예산 기반(Gemini 2.5)
- 💰 경쟁력 있는 가격
- ⚡ 빠른 추론
전체 작동 예제
use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenvy::dotenv().ok();
let api_key = std::env::var("GOOGLE_API_KEY")?;
let model = GeminiModel::new(&api_key, "gemini-3.7-flash")?;
let agent = LlmAgentBuilder::new("gemini_assistant")
.description("Gemini-powered assistant")
.instruction("You are a helpful assistant powered by Google Gemini. Be concise.")
.model(Arc::new(model))
.build()?;
Launcher::new(Arc::new(agent)).run().await?;
Ok(())
}
사용 가능한 모델
| 모델 | 설명 | 컨텍스트 |
|---|---|---|
gemini-3.7-flash | 기본 균형형 에이전트 모델 | 1M 토큰 |
gemini-3.6-flash | 이전 균형형 세대 | 1M 토큰 |
gemini-3.5-flash-lite | 비용 효율적인 라우팅 및 대규모 작업 | 1M 토큰 |
gemini-3.1-pro-preview | 고급 미리보기 추론 | 2M 토큰 |
사고 모드
Gemini 3 모델은 수준 기반 사고를 지원하는 반면, Gemini 2.5는 예산 기반 사고를 사용합니다. 함수 호출과 함께 사고 모드를 사용할 때 Gemini 2.5+ 및 3.x 모델은 이후 턴에서 추론 컨텍스트를 보존하기 위해 다시 반환해야 하는 thoughtSignature 값을 반환합니다. ADK-Rust가 이를 자동으로 처리합니다 — 서명이 존재하면 직렬화되고, None이면 생략됩니다.
use adk_gemini::{Gemini, ThinkingLevel};
// Gemini 3: level-based thinking
let response = client.generate_content()
.with_user_message("Solve this step by step")
.with_thinking_level(ThinkingLevel::High)
.with_thoughts_included(true)
.execute().await?;
// Gemini 2.5: budget-based thinking
let response = client.generate_content()
.with_user_message("Solve this step by step")
.with_thinking_budget(2048)
.with_thoughts_included(true)
.execute().await?;
출력 예시
👤 User: What's in this image? [uploads photo of a cat]
🤖 Gemini: I can see a fluffy orange tabby cat sitting on a windowsill.
The cat appears to be looking outside, with sunlight illuminating its fur.
It has green eyes and distinctive striped markings typical of tabby cats.
OpenAI (GPT-5) 🔥 인기
적합한 용도: 프로덕션 앱, 안정적인 성능, 폭넓은 기능
주요 특징:
- 🏆 업계 표준
- 🔧 뛰어난 도구/함수 호출
- 📖 최고의 문서 및 생태계
- 🎯 일관되고 예측 가능한 출력
- 📋 JSON 스키마 적용을 통한 구조화된 출력
- 🧠 GPT-5.6 추론 모델을 위한 추론 수준 제어
- 🆕 Responses API — 추론 요약, 기본 제공 도구 및 서버 측 상태를 지원하는
/v1/responses전용 클라이언트
완전한 작동 예시
use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenvy::dotenv().ok();
let api_key = std::env::var("OPENAI_API_KEY")?;
let model = OpenAIClient::new(OpenAIConfig::new(&api_key, "gpt-5.6-terra"))?;
let agent = LlmAgentBuilder::new("openai_assistant")
.description("OpenAI-powered assistant")
.instruction("You are a helpful assistant powered by OpenAI GPT-5. Be concise.")
.model(Arc::new(model))
.build()?;
Launcher::new(Arc::new(agent)).run().await?;
Ok(())
}
구조화된 출력(JSON 스키마)
OpenAI는 output_schema를 통해 보장된 JSON 출력을 지원합니다. ADK-Rust는 이를 OpenAI의 response_format API에 자동으로 연결합니다.
use adk_rust::prelude::*;
use serde_json::json;
use std::sync::Arc;
let model = OpenAIClient::new(OpenAIConfig::new(&api_key, "gpt-5.6-terra"))?;
let agent = LlmAgentBuilder::new("data_extractor")
.model(Arc::new(model))
.instruction("Extract person information from the text.")
.output_schema(json!({
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "number" },
"email": { "type": "string" }
},
"required": ["name", "age"]
}))
.build()?;
// Response is guaranteed to be valid JSON matching the schema
중첩된 객체와 함께 엄격한 모드를 사용하려면 각 수준에 additionalProperties: false를 포함하세요.
.output_schema(json!({
"type": "object",
"properties": {
"title": { "type": "string" },
"metadata": {
"type": "object",
"properties": {
"author": { "type": "string" },
"tags": { "type": "array", "items": { "type": "string" } }
},
"required": ["author"],
"additionalProperties": false // Required for nested objects
}
},
"required": ["title", "metadata"],
"additionalProperties": false // Auto-injected at root level
}))
추론 수준
OpenAI 추론 모델의 경우 모델이 적용하는 추론 수준을 제어할 수 있습니다.
use adk_model::openai::{OpenAIClient, OpenAIConfig, OpenAIReasoningEffort};
let config = OpenAIConfig::new(&api_key, "gpt-5.6-terra");
let model = OpenAIClient::new_with_reasoning_effort(
config,
OpenAIReasoningEffort::XHigh,
)?;
전체 어휘는 None, Minimal, Low, Medium, High, XHigh,
및 Max이며, 사용 가능 여부는 모델과 API에 따라 달라집니다. GPT-5.6 Chat Completions는
최대 XHigh까지 지원하며, Max에는 OpenAIResponsesClient을 사용하세요. 기존의
3값 ReasoningEffort API은 이전 버전과의 호환성을 위해 계속 사용할 수 있습니다.
OpenAI-호환 로컬 APIs
로컬 서버(Ollama, vLLM, LM Studio)에 연결하려면 OpenAIConfig::compatible()을 사용하세요.
// Ollama exposes OpenAI-compatible API at /v1
let config = OpenAIConfig::compatible(
"not-needed", // API key (ignored by Ollama)
"http://localhost:11434/v1", // Base URL
"llama3.2" // Model name
);
let model = OpenAIClient::new(config)?;
참고: 구조화된 출력(
output_schema)을 사용하려면 백엔드 지원이 필요합니다. 네이티브 OpenAI는 이를 완전히 지원하지만, 로컬 서버는 지원이 제한적일 수 있습니다.
OpenAI-호환 엔드포인트를 통한 Gemini
Gemini 모델은 https://generativelanguage.googleapis.com/v1beta/openai의 OpenAI Chat Completions 와이어 형식을 통해
접근할 수 있습니다. openai 기능에 포함된
OpenAICompatibleConfig::gemini(...) 프리셋을 GEMINI_API_KEY와 함께 사용하면, 다른 모든 프로바이더에 사용하는 것과 동일한
OpenAI-호환 클라이언트를 통해 Gemini를 실행할 수 있습니다.
use adk_model::openai_compatible::{OpenAICompatible, OpenAICompatibleConfig};
let api_key = std::env::var("GEMINI_API_KEY")?;
let model = OpenAICompatible::new(
OpenAICompatibleConfig::gemini(api_key, "gemini-3.5-flash"),
)?;
이 경로는 채팅, 스트리밍, 함수 호출, 구조화된 출력 및
추론 수준(OpenAI의 reasoning_effort는 Gemini의 사고
수준/예산에 매핑됨)을 지원합니다. include_thoughts을 사용하는 thinking_config이나
cached_content 같은 Gemini 전용 옵션은 요청의
extensions["openai"]["extra_body"]["google"] 맵을 통해 전달되며, 클라이언트는 이를
요청 본문에 변경 없이 병합합니다.
GeminiModel대신 이를 사용해야 하는 경우: 네이티브 Gemini 기능 (서버 측 도구, Interactions API, 네이티브ThinkingConfig, 멀티모달 중심의 사용 편의성)이 필요하다면GeminiModel를 우선 사용하세요. 프로바이더 전반에서 단일하고 통일된 클라이언트를 사용하려는 경우에는 OpenAI-호환 프리셋을 사용하세요.
예시(GEMINI_API_KEY 또는 GOOGLE_API_KEY 필요):
# Direct client: chat, reasoning effort, extra_body thinking, streaming,
# function calling, structured output.
cargo run -p adk-model --features openai --example gemini_openai_compat
# The same compat client driving a normal LlmAgent in a Runner.
# (Lives in adk-agent: it exercises the agent layer, which sits above adk-model.)
cargo run -p adk-agent --example gemini_openai_compat_agent
레거시 추론 수준 API
기존의 3단계 ReasoningEffort API는 호환성을 위해 계속 사용할 수 있습니다.
use adk_model::openai::{OpenAIClient, OpenAIConfig, ReasoningEffort};
let config = OpenAIConfig::new(&api_key, "gpt-5")
.with_reasoning_effort(ReasoningEffort::High);
let model = OpenAIClient::new(config)?;
사용 가능한 수준: Low(가장 빠름), Medium(균형 잡힘), High(가장 철저함).
사용 가능한 모델
| 모델 | 설명 | 컨텍스트 |
|---|---|---|
gpt-5.6-terra | 프로덕션 에이전트를 위한 균형 잡힌 기본 모델 | 256K 토큰 |
gpt-5.6-sol | 최고급 추론 및 코딩 | 256K 토큰 |
gpt-5.6-luna | 비용 효율적인 대규모 작업 부하 | 128K 토큰 |
gpt-5.6 | 플래그십 별칭 | 256K 토큰 |
예시 출력
👤 User: Write a haiku about Rust programming
🤖 GPT-5: Memory so safe,
Ownership guards every byte—
Compiler, my friend.
Anthropic (Claude) 🧠 스마트
적합한 용도: 복잡한 추론, 안전이 중요한 앱, 긴 문서
주요 특징:
- 🧠 탁월한 추론 능력
- 🛡️ 안전성에 가장 중점을 둠
- 📚 200K 토큰 컨텍스트
- ✍️ 뛰어난 글쓰기 품질
완전한 작동 예제
use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenvy::dotenv().ok();
let api_key = std::env::var("ANTHROPIC_API_KEY")?;
let model = AnthropicClient::new(AnthropicConfig::new(&api_key, "claude-sonnet-5"))?;
let agent = LlmAgentBuilder::new("anthropic_assistant")
.description("Anthropic-powered assistant")
.instruction("You are a helpful assistant powered by Anthropic Claude. Be concise and thoughtful.")
.model(Arc::new(model))
.build()?;
Launcher::new(Arc::new(agent)).run().await?;
Ok(())
}
사용 가능한 모델
| 모델 | 설명 | 컨텍스트 |
|---|---|---|
claude-sonnet-5 | 균형 잡힌 지능과 비용 (기본값) | 1M 토큰 |
claude-opus-5 | 플래그십 성능 | 1M 토큰 |
claude-fable-5 | 프리미엄 창작 및 장문 작업 | 1M 토큰 |
claude-haiku-4-5 | 비용 효율적인 이전 세대 | 200K 토큰 |
예시 출력
👤 User: Explain quantum entanglement to a 10-year-old
🤖 Claude: Imagine you have two magic coins. When you flip them, they always
land the same way - both heads or both tails - even if one coin is on Earth
and the other is on the Moon! Scientists call this "entanglement." The coins
are connected in a special way that we can't see, like invisible best friends
who always make the same choice at the exact same time.
DeepSeek 💭 사고
적합한 용도: 복잡한 문제 해결, 수학, 코딩, 추론 작업
주요 특징:
- 💭 사고 모드 - 사고 과정 표시
- 💰 GPT-4보다 매우 비용 효율적(10배 저렴)
- 🔄 반복되는 접두사를 위한 컨텍스트 캐싱
- 🧮 수학 및 코딩에 강함
완전한 작동 예제
use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenvy::dotenv().ok();
let api_key = std::env::var("DEEPSEEK_API_KEY")?;
// Standard chat model
let model = DeepSeekClient::chat(&api_key)?;
// OR: Reasoning model with thinking mode
// let model = DeepSeekClient::reasoner(&api_key)?;
let agent = LlmAgentBuilder::new("deepseek_assistant")
.description("DeepSeek-powered assistant")
.instruction("You are a helpful assistant powered by DeepSeek. Be concise.")
.model(Arc::new(model))
.build()?;
Launcher::new(Arc::new(agent)).run().await?;
Ok(())
}
사용 가능한 모델
| 모델 | 설명 | 특수 기능 |
|---|---|---|
deepseek-v4-flash | 현재 기본값 | 빠른 범용 에이전트 |
deepseek-v4-pro | 고급 추론 | 복잡한 에이전트 작업 |
추론기(사고 모드 포함) 예시 출력
👤 User: What's 17 × 23?
🤖 DeepSeek: <thinking>
Let me break this down:
17 × 23 = 17 × (20 + 3)
= 17 × 20 + 17 × 3
= 340 + 51
= 391
</thinking>
The answer is 391.
Groq ⚡ 초고속
최적의 용도: 실시간 애플리케이션, 챗봇, 속도가 중요한 작업
주요 특징:
- ⚡ 가장 빠른 추론 - 경쟁 제품보다 10배 빠름
- 🔧 LPU(Language Processing Unit) 기술
- 💰 경쟁력 있는 가격
- 🦙 LLaMA, Mixtral, Gemma 모델 실행
완전히 작동하는 예제
use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenvy::dotenv().ok();
let api_key = std::env::var("GROQ_API_KEY")?;
let model = GroqClient::new(GroqConfig::gpt_oss_120b(&api_key))?;
let agent = LlmAgentBuilder::new("groq_assistant")
.description("Groq-powered assistant")
.instruction("You are a helpful assistant powered by Groq. Be concise and fast.")
.model(Arc::new(model))
.build()?;
Launcher::new(Arc::new(agent)).run().await?;
Ok(())
}
사용 가능한 모델
| 모델 | 메서드 | 설명 |
|---|---|---|
openai/gpt-oss-120b | GroqClient::new(GroqConfig::gpt_oss_120b(key)) | 현재 프로덕션 기본값 |
openai/gpt-oss-20b | GroqClient::new(GroqConfig::new(key, "openai/gpt-oss-20b")) | 더 저렴한 GPT-OSS 모델 |
| 모든 모델 | GroqClient::new(GroqConfig::new(key, "model")) | 사용자 지정 모델 |
예시 출력
👤 User: Quick! Name 5 programming languages
🤖 Groq (in 0.2 seconds):
1. Rust
2. Python
3. JavaScript
4. Go
5. TypeScript
제공자 전환
모든 제공자는 동일한 Llm 트레이트를 구현하므로 전환이 쉽습니다.
use adk_agent::LlmAgentBuilder;
use std::sync::Arc;
// Just change the model - everything else stays the same!
let model: Arc<dyn adk_core::Llm> = Arc::new(
// Pick one:
// GeminiModel::new(&api_key, "gemini-3.7-flash")?
// OpenAIClient::new(OpenAIConfig::new(&api_key, "gpt-5.6-terra"))?
// AnthropicClient::new(AnthropicConfig::new(&api_key, "claude-sonnet-5"))?
// DeepSeekClient::chat(&api_key)?
// GroqClient::new(GroqConfig::gpt_oss_120b(&api_key))?
);
let agent = LlmAgentBuilder::new("assistant")
.instruction("You are a helpful assistant.")
.model(model)
.build()?;
예시
cargo-adk를 사용하여 검증된 0.8 종속성으로 제공자별 프로젝트를 생성합니다.
cargo adk new gemini_agent --provider gemini
cargo adk new openai_agent --template openai
cargo adk new anthropic_agent --provider anthropic
생성된 프로젝트는 scripts/check-cargo-adk-templates.sh에 의해 CI에서 컴파일됩니다. 전체 예시 모음은 adk-playground 저장소에서 관리됩니다.
관련 항목
- Ollama (로컬) - Ollama를 사용하여 모델을 로컬에서 실행
- 로컬 모델 (mistral.rs) - 네이티브 Rust 추론
- LlmAgent - 에이전트에서 모델 사용
- 함수 도구 - 에이전트에 도구 추가
이전: ← 실시간 에이전트 | 다음: Ollama (로컬) →
제공자가 전달할 수 없는 콘텐츠는 어떻게 처리되는가
Content은 단일 제공자 전송 방식이 허용하는 것보다 더 많은 내용을 표현할 수 있으므로, 각 어댑터는 나머지 내용을 어떻게 처리할지 결정해야 합니다. 이제 이러한 결정은 보이지 않게 적용되는 대신 기록됩니다. 모든 부분은 다음과 같이 분류됩니다:
| 처리 방식 | 의미 |
|---|---|
Converted | 동등한 네이티브 형식으로 제공자에게 전달됨 |
Downgraded | 정보 손실이 더 큰 형식으로 전달됨 — 모델이 읽을 수 있지만 가져올 수는 없는 설명 텍스트로 렌더링된 파일 참조 |
Omitted | 전혀 전달되지 않음 |
다운그레이드와 생략은 기록될 때 tracing 경고를 발생시키며, 어느 쪽도 조용히 처리되지 않도록 파트 종류, MIME 유형 및 이유를 명시합니다.
요청을 전송하기 전에 결과를 확인하려면:
use adk_core::{Content, Part};
use adk_model::bedrock::convert::report_for_contents;
let content = Content {
role: "user".to_string(),
parts: vec![Part::inline_data("audio/wav", vec![0u8; 16])],
};
let report = report_for_contents(std::slice::from_ref(&content));
for omission in report.omitted_parts() {
println!("{} was dropped: {}", omission.kind, omission.detail);
}
모델이 전혀 보지 못한 자료에 대한 응답을 받는 대신, 불완전한 상태로 모델에 도달할 요청을 거부하려면:
use adk_core::{Content, Part};
use adk_model::bedrock::convert::report_for_contents;
let content = Content {
role: "user".to_string(),
parts: vec![Part::inline_data("video/mp4", vec![0u8; 16])],
};
if let Some(error) = report_for_contents(std::slice::from_ref(&content)).into_error() {
return Err(error);
}
into_error은 생략만 다룹니다. 다운그레이드는 여전히 모델에 도달하며, 이를 거부하면 문서화된 텍스트 대체 처리를 거부하게 됩니다.
참고: 원장에는 설계상 모든 항목이 기록됩니다. 기록된 처리 결과 없이 어댑터를 벗어나는 모든 파트(향후 변경으로 추가된 파트 포함)는 명시적인 "기록된 이유 없음"과 함께 생략으로 기록되며,
adk-model/tests/part_conversion_matrix_tests.rs는 해당 항목에서 실패합니다.
Bedrock Converse 지원 범위
| 부분 | 처리 방식 |
|---|---|
| 텍스트, FunctionCall, FunctionResponse, 사고 | Converted |
JPEG의 InlineData, PNG, GIF, WebP | 이미지 블록으로서의 Converted |
지원되는 문서 유형(PDF 등)의 InlineData | 문서 블록으로서의 Converted |
오디오, 비디오 또는 임의의 바이너리가 포함된 InlineData | Omitted |
이미지 또는 지원되는 문서용 FileData | 텍스트로 변환하는 Downgraded — Converse는 임의의 URLs가 아닌 S3 URIs을 사용합니다 |
그 밖의 모든 유형용 FileData | Omitted |
ServerToolCall, ServerToolResponse | Omitted — Gemini 전용 |
EmbeddedResource 텍스트 또는 지원되는 유형의 blob | Converted |
지원되지 않는 유형의 EmbeddedResource blob | Omitted |