모델 제공자(클라우드)

ADK-Rust는 adk-model crate를 통해 여러 클라우드 LLM 제공자를 지원합니다. 모든 제공자는 Llm trait를 구현하므로, 에이전트에서 서로 교체하여 사용할 수 있습니다.

개요

┌─────────────────────────────────────────────────────────────────────┐
│                     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일반 사용⚡⚡⚡💰멀티모달, 큰 컨텍스트, thinking
OpenAI신뢰성⚡⚡💰💰최고의 생태계
Anthropic복잡한 추론⚡⚡💰💰가장 안전하고, 가장 신중함
DeepSeekChain-of-thought⚡⚡💰생각 모드, 저렴함
Groq속도 중요한⚡⚡⚡⚡💰가장 빠른 추론

1단계: 설치

필요한 provider를 Cargo.toml에 추가하세요:

[dependencies]
# Pick one or more providers:
adk-model = { version = "2.0.0", features = ["gemini"] }        # Google Gemini (default)
adk-model = { version = "2.0.0", features = ["openai"] }        # OpenAI GPT-5
adk-model = { version = "2.0.0", features = ["anthropic"] }     # Anthropic Claude
adk-model = { version = "2.0.0", features = ["deepseek"] }      # DeepSeek
adk-model = { version = "2.0.0", features = ["groq"] }          # Groq (ultra-fast)

# Or all cloud providers at once:
adk-model = { version = "2.0.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

스키마 정규화

각 provider는 요청 시점에 MCP tool schema를 자동으로 정규화합니다. 별도로 할 일은 없습니다 — 투명하게 작동합니다. 하지만 내부에서 일어나는 일은 다음과 같습니다:

제공자스키마 어댑터동작
GeminiGeminiSchemaAdapter공격적: $ref를 해석하고, 결합기를 축소하며, 지원되지 않는 키워드를 제거함
OpenAI (엄격)OpenAiStrictSchemaAdapter구조를 보존하고, additionalProperties: false를 추가함
OpenAIOpenAiSchemaAdapter최소한의 안전 수정
AnthropicAnthropicSchemaAdapter거의 그대로 통과
DeepSeekGenericSchemaAdapter보수적인 안전 변환
OllamaGenericSchemaAdapter보수적인 안전 변환

어댑터는 Llm trait를 통해 프로그램적으로 접근할 수 있습니다:

use adk_core::{Llm, SchemaAdapter};

let adapter = model.schema_adapter();
let normalized = adapter.normalize_schema(raw_schema);

전체 문서는 Schema Normalization를 참조하세요.


Gemini (Google) ⭐ 기본

적합한 용도: 범용, 멀티모달 작업, 대용량 문서

주요 특징:

  • 🖼️ 네이티브 멀티모달(이미지, 비디오, 오디오, PDF)
  • 📚 최대 2M 토큰 컨텍스트 윈도우
  • 🧠 Thinking mode: 레벨 기반(Gemini 3) 및 예산 기반(Gemini 2.5), thought signatures 포함
  • 💰 경쟁력 있는 가격
  • ⚡ 빠른 추론

완전한 동작 예제

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-2.5-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.1-pro-preview복잡한 에이전트 워크플로를 위한 가장 강력한 추론2M tokens
gemini-3-flash-preview코드와 에이전트를 위해 빠르고 효율적임1M tokens
gemini-3.1-flash-lite-preview가장 저렴하고 가장 빠른 라우팅과 대량 작업1M tokens
gemini-2.5-pro고급 추론 및 멀티모달1M tokens
gemini-2.5-flash속도와 성능의 균형 (권장)1M tokens

사고 모드

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.

최적 용도: 프로덕션 앱, 안정적인 성능, 폭넓은 기능

주요 특징:

  • 🏆 업계 표준
  • 🔧 뛰어난 도구/함수 호출
  • 📖 최고의 문서 & 생태계
  • 🎯 일관되고 예측 가능한 출력
  • 📋 JSON 스키마 강제 적용이 있는 구조화된 출력
  • 🧠 o1/o3 추론 모델을 위한 Reasoning effort 제어
  • 🆕 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-mini"))?;

    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-mini"))?;

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
}))

Reasoning Effort (o1, o3 모델)

OpenAI 추론 모델의 경우, 모델이 적용하는 추론 노력을 제어합니다:

use adk_model::openai::{OpenAIClient, OpenAIConfig, ReasoningEffort};

let config = OpenAIConfig::new(&api_key, "o3-mini")
    .with_reasoning_effort(ReasoningEffort::High);
let model = OpenAIClient::new(config)?;

사용 가능한 수준: Low, Medium, High. 더 높은 노력은 지연 시간과 토큰 비용을 늘리는 대신 더 철저한 추론을 생성합니다.

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 모델은 다음 위치의 OpenAI Chat Completions 와이어 형식을 통해 접근할 수 있습니다: https://generativelanguage.googleapis.com/v1beta/openai. 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"),
)?;

이 경로는 채팅, 스트리밍, 함수 호출, 구조화된 출력, 그리고 reasoning effort(OpenAI의 reasoning_effort는 Gemini 사고 수준/예산에 매핑됨)를 지원합니다. Gemini 전용 옵션 — 예를 들어 thinking_configinclude_thoughts, 또는 cached_content — 은 요청의 extensions["openai"]["extra_body"]["google"] 맵을 통해 전달되며, 클라이언트는 이를 요청 본문에 그대로 병합합니다.

이것을 GeminiModel 대신 언제 사용할까: 서버 측 도구, Interactions API, 네이티브 ThinkingConfig, 멀티모달 우선 사용성 같은 네이티브 Gemini 기능이 필요하다면 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

Reasoning Effort (o1, o3 모델)

ReasoningEffort으로 모델이 적용하는 추론 노력을 제어합니다:

use adk_model::openai::{OpenAIClient, OpenAIConfig, ReasoningEffort};

let config = OpenAIConfig::new(&api_key, "o3-mini")
    .with_reasoning_effort(ReasoningEffort::High);
let model = OpenAIClient::new(config)?;

사용 가능한 수준: Low(가장 빠름), Medium(균형형), High(가장 철저함).

사용 가능한 모델

모델설명컨텍스트
gpt-5적응형 사고를 갖춘 최첨단 통합 모델256K 토큰
gpt-5-mini대부분의 작업에 적합한 효율적인 버전(권장)128K 토큰
gpt-5-nano최저 비용 라우팅 및 분류128K 토큰
gpt-4.1레거시 GPT-4.1 배포를 위한 안정적인 프로덕션 모델1M 토큰

예시 출력

👤 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-4-6"))?;

    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-opus-4-7가장 성능이 뛰어난 GA 모델, 적응형 사고만 지원100만 토큰
claude-opus-4-6복잡한 자율 작업을 위한 이전 플래그십100만 토큰
claude-sonnet-4-6균형 잡힌 지능과 비용(권장)1M 토큰
claude-haiku-4-5-20251001대규모 작업 부하에 매우 효율적200K 토큰
claude-opus-4-20250514확장된 사고를 갖춘 하이브리드 모델200K 토큰
claude-sonnet-4-20250514확장된 사고를 갖춘 균형형 모델1M 토큰

예제 출력

👤 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 💭 사고

적합한 용도: 복잡한 문제 해결, 수학, 코딩, 추론 작업

주요 특징:

  • 💭 사고 모드 - chain-of-thought 추론을 표시
  • 💰 매우 비용 효율적임 (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-r1-0528최신 추론 모델향상된 사고 깊이
deepseek-r1고급 추론o1과 동등함
deepseek-v3.1최신 671B MoE 모델일반 작업
deepseek-chat671B MoE 모델 (V3)범용, 저렴함
deepseek-vl2비전-언어 모델멀티모달

예제 출력(Reasoner with Thinking Mode)

👤 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::llama70b(&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(())
}

사용 가능한 모델

모델메서드설명
llama-4-scoutGroqClient::new(GroqConfig::new(key, "llama-4-scout"))Llama 4 Scout (17Bx16E)
llama-3.2-90b-text-previewGroqClient::new(GroqConfig::new(key, "llama-3.2-90b-text-preview"))대형 텍스트 모델
llama-3.1-70b-versatileGroqClient::llama70b()다목적 대형 모델
llama-3.1-8b-instantGroqClient::llama8b()가장 빠름
mixtral-8x7b-32768GroqClient::mixtral()균형이 좋음
모든 모델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 trait를 구현하므로, 전환은 쉽습니다:

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-2.5-flash")?
    // OpenAIClient::new(OpenAIConfig::new(&api_key, "gpt-5-mini"))?
    // AnthropicClient::new(AnthropicConfig::new(&api_key, "claude-sonnet-4-6"))?
    // DeepSeekClient::chat(&api_key)?
    // GroqClient::llama70b(&api_key)?
);

let agent = LlmAgentBuilder::new("assistant")
    .instruction("You are a helpful assistant.")
    .model(model)
    .build()?;

예제

검증된 0.8 의존성을 사용하는 제공자별 프로젝트를 생성하려면 cargo-adk를 사용하세요:

cargo adk new gemini_agent --provider gemini
cargo adk new openai_agent --template openai
cargo adk new anthropic_agent --provider anthropic

생성된 프로젝트는 CI에서 scripts/check-cargo-adk-templates.sh에 의해 컴파일됩니다. 전체 예제 갤러리는 이 사이트에 포함된 ADK-Rust Playground에서 탐색하고 실행할 수 있습니다.



이전: ← Realtime Agents | 다음: Ollama (Local) →

제공자가 전달할 수 없는 content는 어떻게 되나

Content는 단일 provider transport가 허용하는 것보다 더 많은 것을 표현할 수 있으므로, 각 adapter는 나머지를 어떻게 처리할지 결정해야 합니다. 이러한 결정은 이제 보이지 않게 적용되는 대신 기록됩니다. 모든 부분은 다음과 같이 분류됩니다:

배치의미
Converted제공자에게 동등한 네이티브 형식으로 전달됨
Downgraded더 손실이 큰 형식으로 전달됨 — 모델이 읽을 수는 있지만 가져올 수는 없는 설명 텍스트로 렌더링된 파일 참조
Omitted전혀 전달되지 않음

다운그레이드와 누락은 기록될 때 tracing 경고를 발생시키며, part 종류, MIME type, 그리고 이유를 명시하므로 어느 쪽도 조용히 넘어가지 않습니다.

요청을 전송하기 전에 결과를 확인하려면:

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는 누락만 다룹니다. 다운그레이드는 여전히 모델에 도달하며, 이를 거부하면 문서화된 텍스트 대체 경로를 거부하게 됩니다.

참고: ledger는 구성상 완전합니다. 어댑터를 떠날 때 기록된 운명이 없는 모든 part — 미래의 변경으로 추가된 것까지 포함해 — 는 명시적인 "기록된 이유 없음"과 함께 누락으로 기록되며, adk-model/tests/part_conversion_matrix_tests.rs 가 이를 실패로 처리합니다.

Bedrock Converse 범위

부분처리 상태
텍스트, FunctionCall, FunctionResponse, ThinkingConverted
InlineData with JPEG, PNG, GIF, WebPConverted as an image block
InlineData 지원되는 문서 유형(PDF 등)과 함께문서 블록으로서 Converted
InlineData 오디오, 비디오 또는 임의의 바이너리와 함께Omitted
이미지 또는 지원되는 문서에 대해 FileData텍스트로 Downgraded — Converse는 임의의 URLs가 아니라 S3 URIs를 사용함
다른 모든 유형에 대해 FileDataOmitted
ServerToolCall, ServerToolResponseOmitted — Gemini 전용
EmbeddedResource 텍스트, 또는 지원되는 유형의 blobConverted
EmbeddedResource 지원되지 않는 유형의 blobOmitted