Gemini - Google AI Studio

Gemini - Google AI Studio

Google AI Studio는 생성형 AI를 구축·사용하기 위한 완전 관리형 AI 개발 플랫폼이에요.

속성 설명
설명 생성형 AI를 구축·사용하기 위한 완전 관리형 AI 개발 플랫폼
LiteLLM 라우트 gemini/
공급자 문서 Google AI Studio
Provider API 엔드포인트 https://generativelanguage.googleapis.com
지원 OpenAI 엔드포인트 /chat/completions, /embeddings, /completions, /videos, /images/edits
Lyria (음악) 비용 맵 & 비고
패스스루 엔드포인트 지원

출처: 문서

본문

Gemini API vs Vertex AI

모델 형식 공급자 인증 필요
gemini/gemini-2.0-flash Gemini API GEMINI_API_KEY (간단한 API 키)
vertex_ai/gemini-2.0-flash Vertex AI GCP 자격 증명 + 프로젝트
gemini-2.0-flash (접두사 없음) Vertex AI GCP 자격 증명 + 프로젝트

API 키(OpenAI처럼)만 쓰고 싶다면 gemini/ 접두사를 사용하세요. 접두사가 없는 모델은 기본적으로 전체 GCP 인증이 필요한 Vertex AI에 라우팅돼요.

API 키

import os

os.environ["GEMINI_API_KEY"] = "your-api-key"

샘플 사용법 (Sample Usage)

from litellm import completion
import os

os.environ['GEMINI_API_KEY'] = ""

response = completion(
    model="gemini/gemini-3.8-flash",
    messages=[{"role": "user", "content": "write code for saying hi from LiteLLM"}]
)

지원되는 OpenAI 파라미터

  • temperature
  • top_p
  • max_tokens
  • max_completion_tokens
  • stream
  • tools
  • tool_choice
  • include_server_side_tool_invocations
  • functions
  • response_format
  • n
  • stop
  • logprobs
  • frequency_penalty
  • modalities
  • reasoning_content
  • audio (TTS 모델 전용)
  • service_tier

Anthropic 파라미터:

  • thinking (anthropic/gemini 모델 전체에서 max budget tokens 설정용)

Thinking / reasoning_content 사용

LiteLLM은 OpenAI의 reasoning_effort를 Gemini의 thinking 파라미터로 변환해요.

비용 최적화: reasoning_effort"none"(OpenAI 표준)을 사용하면 최대 96%까지 비용을 절감할 수 있어요.

참고: Gemini 2.5 Pro 모델에서는 Reasoning을 끌 수 없어요.

from litellm import completion

# Cost-optimized: Use reasoning_effort="none" for best pricing
resp = completion(
    model="gemini/gemini-3.8-flash",
    messages=[{"role": "user", "content": "What is the capital of France?"}],
    reasoning_effort="none",  # Up to 96% cheaper!
)

# Or use other levels: "low", "medium", "high"
resp = completion(
    model="gemini/gemini-3.8-flash",
    messages=[{"role": "user", "content": "What is the capital of France?"}],
    reasoning_effort="low",
)

Proxy config.yaml:

- model_name: gemini-3.8-flash
  litellm_params:
    model: gemini/gemini-3.8-flash
    api_key: os.environ/GEMINI_API_KEY
litellm --config /path/to/config.yaml
curl http://0.0.0.0:4000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <YOUR-...KEY>" \
  -d '{
    "model": "gemini-3.8-flash",
    "messages": [{"role": "user", "content": "What is the capital of France?"}],
    "reasoning_effort": "low"
  }'

Gemini 3 모델용 thinking_level 파라미터

Gemini 3+ 모델(예: gemini-3.1-pro-preview)의 경우 LiteLLM은 reasoning_effort를 thinking_budget 대신 thinking_level 필드에 매핑해요. 지원 레벨은 모델에 따라 달라요: Flash 제품군은 medium도 지원하며, minimal은 3.6 Flash까지 지원해요. 3.7과 3.8 Flash는 minimal을 거부하므로 LiteLLM은 그들에 대해 low를 보내요(비용 맵 항목의 supports_minimal_reasoning_effort: false에 따라). reasoning_effort를 생략하면 LiteLLM은 기본 thinking_level을 보내지 않으므로 요청은 Gemini API 기본값(Gemini 3 Flash는 API에서 기본적으로 high)을 사용해요.

이미지 모델: Gemini 이미지 모델(예: gemini-3-pro-image-preview, gemini-2.0-flash-exp-image-generation)은 thinking_level 파라미터를 지원하지 않아요. LiteLLM은 API 에러를 방지하기 위해 이미지 모델을 thinking 구성에서 자동으로 제외해요.

Gemini 2.5 이하 모델 매핑

reasoning_effort thinking 비고
"none" "budget_tokens": 0, "includeThoughts": false 💰 비용 최적화 권장 - OpenAI 호환, 항상 0
"disable" "budget_tokens": DEFAULT (0), "includeThoughts": false LiteLLM 전용, env var로 설정 가능
"low" "budget_tokens": 1024
"medium" "budget_tokens": 2048
"high" "budget_tokens": 4096

Gemini 3+ 모델 매핑

reasoning_effort thinking_level 비고
"minimal" "minimal" (3.6 이하 Flash / 일부 3.1) 또는 "low" Flash 제품군 ID는 비용 맵 항목이 supports_minimal_reasoning_effort: false(3.7과 3.8 Flash)로 설정하지 않는 한 minimal 사용. 이는 low로 매핑
"low" "low" 단순 지시 따르기나 채팅에 최적
"medium" "medium" 또는 "high" API가 지원하면 "medium", 그 외 "high"
"high" "high" Reasoning 깊이 최대화
"disable" "minimal" (3.6 이하 Flash) 또는 "low" Gemini 3에서 thinking을 완전히 끌 수 없음; 3.7/3.8 Flash는 minimal 거부 → low
"none" "minimal" (3.6 이하 Flash) 또는 "low" Gemini 3에서 thinking을 완전히 끌 수 없음; 3.7/3.8 Flash는 minimal 거부 → low
from litellm import completion

# Use thinking_level for Gemini 3 models
resp = completion(
    model="gemini/gemini-3.1-pro-preview",
    messages=[{"role": "user", "content": "Solve this complex math problem step by step."}],
    reasoning_effort="high",  # Options: "low" or "high"
)

# Low thinking level for faster, simpler tasks
resp = completion(
    model="gemini/gemini-3.1-pro-preview",
    messages=[{"role": "user", "content": "What is the weather today?"}],
    reasoning_effort="low",  # Minimizes latency and cost
)
curl http://0.0.0.0:4000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <YOUR-...KEY>" \
  -d '{
    "model": "gemini-3.1-pro-preview",
    "messages": [{"role": "user", "content": "Solve this complex problem."}],
    "reasoning_effort": "high"
  }'

예상 응답

ModelResponse(
    id='chatcmpl-c542d76d-f675-4e87-8e5f-05855f5d0f5e',
    created=1740470510,
    model='gemini-3.8-flash',
    object='chat.completion',
    system_fingerprint=None,
    choices=[
        Choices(
            finish_reason='stop',
            index=0,
            message=Message(
                content="The capital of France is Paris.",
                role='assistant',
                tool_calls=None,
                function_call=None,
                reasoning_content='The capital of France is Paris. This is a very straightforward factual question.'
            ),
        )
    ],
    usage=Usage(
        completion_tokens=68,
        prompt_tokens=42,
        total_tokens=110,
        ...
    )
)

Gemini 3 모델 온도 권장 사항

Gemini 3 모델에서 LiteLLM은 temperature를 기본적으로 1.0으로 설정하며 이 기본값을 유지할 것을 강력히 권장해요. temperature < 1.0으로 설정하면:

  • 무한 루프
  • 열화된 reasoning 성능
  • 복잡한 태스크 실패

LiteLLM은 Gemini 3+ 모델에서 temperature가 지정되지 않으면 자동으로 1.0을 설정해요.

Gemini 모델에 thinking 전달

Anthropic 스타일 thinking 파라미터도 Gemini 모델에 전달할 수 있어요. 이는 Gemini의 thinkingConfig 파라미터로 변환돼요.

SDK:

response = litellm.completion(
    model="gemini/gemini-3.8-flash",
    messages=[{"role": "user", "content": "What is the capital of France?"}],
    thinking={"type": "enabled", "budget_tokens": 1024},
)

Proxy:

curl http://0.0.0.0:4000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ***" \
  -d '{
    "model": "gemini/gemini-3.8-flash",
    "messages": [{"role": "user", "content": "What is the capital of France?"}],
    "thinking": {"type": "enabled", "budget_tokens": 1024}
  }'

Gemini 3+ 모델의 경우 LiteLLM은 이제 기본적으로 provider 기본값을 따르며 Anthropic 스타일 thinking={"type":"enabled","budget_tokens":...}을 전달할 때 thinkingLevel을 강제하지 않아요. 기존 LiteLLM 동작(Pro는 thinkingLevel="low", Flash는 "minimal" 강제)을 원하면 litellm.enable_gemini_default_thinking_level_low = True를 활성화하세요.

service_tier 사용

LiteLLM은 OpenAI의 service_tier 파라미터를 Gemini로 전파하고, 응답 헤더(x-gemini-service-tier)에서도 이를 추출해 model_response.service_tier에 넣어요.

OpenAI service_tier Gemini service_tier 비고
"auto" "priority" priority가 Gemini에서 폴백되므로 "auto"를 "priority"로 매핑
"flex" "flex" 직접 매핑
"priority" "priority" 직접 매핑
"default" "standard" "default"를 "standard"로 매핑
그 외 다른 값 그대로 전달 (소문자화) 값은 대소문자 구분 없이 소문자로 정규화

응답에서 LiteLLM은 Gemini API용으로 "standard"를 "default"로 다시 매핑해요.

Text-to-Speech (TTS) 오디오 출력

LiteLLM은 OpenAI 호환 audio 파라미터 형식을 사용해 오디오 응답을 생성할 수 있는 Gemini TTS 모델을 지원해요.

지원 모델

LiteLLM은 오디오 기능이 있는 Gemini TTS 모델(예: gemini-2.5-flash-preview-tts, gemini-2.5-pro-preview-tts)을 지원해요. 전체 TTS 모델과 음성 목록은 공식 Gemini TTS 문서를 참고하세요.

제한 사항

⚠️ 중요 제한:

  • Gemini TTS 모델은 pcm16 오디오 형식만 지원
  • TTS 모델에 스트리밍 지원 아직 추가되지 않음
  • TTS 요청에는 modalities 파라미터를 ['audio']로 설정해야 함
from litellm import completion
import os

os.environ['GEMINI_API_KEY'] = "your-api-key"

response = completion(
    model="gemini/gemini-2.5-flash-preview-tts",
    messages=[{"role": "user", "content": "Say hello in a friendly voice"}],
    modalities=["audio"],  # Required for TTS models
    audio={
        "voice": "Kore",
        "format": "pcm16"  # Required: must be "pcm16"
    }
)
print(response)

Proxy config.yaml:

model_list:
  - model_name: gemini-tts-flash
    litellm_params:
      model: gemini/gemini-2.5-flash-preview-tts
      api_key: os.environ/GEMINI_API_KEY
  - model_name: gemini-tts-pro
    litellm_params:
      model: gemini/gemini-2.5-pro-preview-tts
      api_key: os.environ/GEMINI_API_KEY
litellm --config /path/to/config.yaml
curl http://0.0.0.0:4000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <YOUR-...KEY>" \
  -d '{
    "model": "gemini-tts-flash",
    "messages": [{"role": "user", "content": "Say hello in a friendly voice"}],
    "modalities": ["audio"],
    "audio": { "voice": "Kore", "format": "pcm16" }
  }'

고급 사용법:

response = completion(
    model="gemini/gemini-2.5-pro-preview-tts",
    messages=[
        {"role": "system", "content": "You are a helpful assistant that speaks clearly."},
        {"role": "user", "content": "Explain quantum computing in simple terms"}
    ],
    modalities=["audio"],
    audio={
        "voice": "Charon",
        "format": "pcm16"
    },
    temperature=0.7,
    max_tokens=150
)

오디오 전사 (Speech-to-Text)

LiteLLM은 /v1/audio/transcriptions에서 gemini-3.5-transcribe를, /v1/realtime에서 gemini-3.5-transcribe-live를 지원해요. API 키 대신 Vertex AI를 쓰려면 Vertex AI Audio Transcription 문서를 참고하세요.

from litellm import transcription
import os

os.environ["GEMINI_API_KEY"] = "your-api-key"
audio_file = open("speech.wav", "rb")

response = transcription(
    model="gemini/gemini-3.5-transcribe",
    file=audio_file,
    response_format="verbose_json",
    timestamp_granularities=["word"],
)
print(response.text)
print(response.words)  # word-level timestamps

Proxy config.yaml:

model_list:
  - model_name: gemini-3.5-transcribe
    litellm_params:
      model: gemini/gemini-3.5-transcribe
      api_key: os.environ/GEMINI_API_KEY
litellm --config config.yaml
curl http://0.0.0.0:4000/v1/audio/transcriptions \
  -H "Authorization: Bearer ***" \
  -F [email protected] \
  -F model=gemini-3.5-transcribe \
  -F response_format=verbose_json \
  -F "timestamp_granularities[]=word"

지원 파라미터: language, response_format, timestamp_granularities. 단어 타임스탬프 요청은 기본 Interactions API 호출에서 화자 분리(diarization)도 활성화해요. srtvtt 응답 형식은 Gemini의 단어 타임스탬프에서 LiteLLM이 합성하므로 text는 자막 문서를 담고, Gemini가 타임스탬프를 반환하지 않으면 text는 일반 전사로 폴백해요.

/v1/realtime 실시간 전사

gemini-3.5-transcribe-live는 Realtime websocket 위에서 실행돼요. input_audio_buffer.append로 pcm16 오디오를 스트리밍하고 conversation.item.input_audio_transcription.completed 이벤트에서 전사본을 읽어요. Gemini Live API는 전사 세션에 대한 토큰 사용량을 보고하지 않으므로, LiteLLM은 스트리밍된 오디오 길이로 Google의 공식 추정 요율을 사용해 사용량(및 지출)을 추정해요.

import asyncio
import json
import websockets

async def main():
    async with websockets.connect(
        "ws://0.0.0.0:4000/v1/realtime?model=gemini-3.5-transcribe-live",
        additional_headers={"Authorization": "Bearer sk-<your-litellm-api-key>"},
    ) as ws:
        await ws.send(json.dumps({"type": "input_audio_buffer.append", "audio": "<base64 pcm16 audio>"}))
        async for message in ws:
            event = json.loads(message)
            if event.get("type") == "conversation.item.input_audio_transcription.completed":
                print(event["transcript"], event.get("usage"))

asyncio.run(main())

Gemini 전용 파라미터 전달

Response schema (응답 스키마)

LiteLLM은 Google AI Studio의 Gemini 모델에 response_schema 파라미터를 지원해요.

from litellm import completion
import json
import os

os.environ['GEMINI_API_KEY'] = ""
messages = [
    {
        "role": "user",
        "content": "List 5 popular cookie recipes."
    }
]
response_schema = {
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "recipe_name": {
                "type": "string",
            },
        },
        "required": ["recipe_name"],
    },
}

completion(
    model="gemini/gemini-3.1-pro-preview",
    messages=messages,
    response_format={"type": "json_object", "response_schema": response_schema}  # 👈 KEY CHANGE
)
print(json.loads(completion.choices[0].message.content))

Proxy config.yaml:

model_list:
  - model_name: gemini-3.1-pro-preview
    litellm_params:
      model: gemini/gemini-3.1-pro-preview
      api_key: os.environ/GEMINI_API_KEY
$ litellm --config /path/to/config.yaml
curl -X POST 'http://0.0.0.0:4000/chat/completions' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer ***" \
  -d '{
    "model": "gemini-3.1-pro-preview",
    "messages": [
      {
        "role": "user",
        "content": "List 5 popular cookie recipes."
      }
    ],
    "response_format": {"type": "json_object", "response_schema": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "recipe_name": {
            "type": "string",
          },
        },
        "required": ["recipe_name"],
      },
    }}
  }'

스키마 검증: response_schema를 검증하려면 enforce_validation: true를 설정하세요. LiteLLM이 스키마에 대해 응답을 검증하고, 응답이 일치하지 않으면 JSONSchemaValidationError를 발생시켜요. JSONSchemaValidationError는 openai.APIError를 상속하며 e.raw_response로 원시 응답에 접근할 수 있어요.

from litellm import completion, JSONSchemaValidationError

try:
    completion(
        model="gemini/gemini-3.1-pro-preview",
        messages=messages,
        response_format={
            "type": "json_object",
            "response_schema": response_schema,
            "enforce_validation": true  # 👈 KEY CHANGE
        }
    )
except JSONSchemaValidationError as e:
    print("Raw Response: {}".format(e.raw_response))
    raise e

GenerationConfig 파라미터

topK 같은 추가 GenerationConfig 파라미터를 전달하려면 호출의 요청 본문에 그냥 넣으면 LiteLLM이 요청 본문의 키-값 쌍으로 그대로 전달해요.

from litellm import completion
import json
import os

os.environ['GEMINI_API_KEY'] = ""
messages = [
    {"role": "user", "content": "List 5 popular cookie recipes."}
]

completion(
    model="gemini/gemini-3.1-pro-preview",
    messages=messages,
    topK=1  # 👈 KEY CHANGE
)
print(json.loads(completion.choices[0].message.content))

안전 설정 지정 (Safety Settings)

특정 사용 사례에서 기본값과 다른 안전 설정을 전달해야 할 수 있어요. safety_settings 인자를 completion 또는 acompletion에 전달하면 됩니다.

response = completion(
    model="gemini/gemini-3.8-flash",
    messages=[{"role": "user", "content": "write code for saying hi from LiteLLM"}],
    safety_settings=[
        {
            "category": "HARM_CATEGORY_HARASSMENT",
            "threshold": "BLOCK_NONE",
        },
        {
            "category": "HARM_CATEGORY_HATE_SPEECH",
            "threshold": "BLOCK_NONE",
        },
        {
            "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
            "threshold": "BLOCK_NONE",
        },
        {
            "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
            "threshold": "BLOCK_NONE",
        },
    ]
)

Tool Calling

from litellm import completion
import os

os.environ["GEMINI_API_KEY"] = ".."

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Get the current weather in a given location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA",
                    },
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                },
                "required": ["location"],
            },
        },
    }
]

messages = [{"role": "user", "content": "What's the weather like in Boston today?"}]

response = completion(
    model="gemini/gemini-3.8-flash",
    messages=messages,
    tools=tools,
)

# Add any assertions, here to check response args
print(response)
assert isinstance(response.choices[0].message.tool_calls[0].function.name, str)
assert isinstance(
    response.choices[0].message.tool_calls[0].function.arguments, str
)

Google Search Tool

from litellm import completion
import os

os.environ["GEMINI_API_KEY"] = ".."
tools = [{"googleSearch": {}}]  # 👈 ADD GOOGLE SEARCH

response = completion(
    model="gemini/gemini-3.8-flash",
    messages=[{"role": "user", "content": "What is the weather in San Francisco?"}],
    tools=tools,
)
print(response)

Proxy config.yaml:

model_list:
  - model_name: gemini-3.8-flash
    litellm_params:
      model: gemini/gemini-3.8-flash
      api_key: os.environ/GEMINI_API_KEY
$ litellm --config /path/to/config.yaml
curl -X POST 'http://0.0.0.0:4000/chat/completions' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer ***" \
  -d '{
    "model": "gemini-3.8-flash",
    "messages": [{"role": "user", "content": "What is the weather in San Francisco?"}],
    "tools": [{"googleSearch": {}}]
  }'

Context Circulation (서버 측 도구 조합)

Context circulation을 통해 Gemini 3+ 모델은 같은 요청에서 Google Search 같은 내장 도구와 사용자 지정 함수를 결합할 수 있어요. 없으면 둘 다 사용하려 하면 Gemini가 에러를 반환해요. 활성화하면 Gemini가 Google Search를 서버 측에서 실행하고, 그러한 결과를 사용해 사용자 지정 함수를 호출할지 결정하며, 전체 추론 체인을 반환해요.

동작 방식:

  1. include_server_side_tool_invocations=True와 함께 Google Search 및 함수 도구를 전달
  2. Gemini가 서버 측 도구를 내부적으로 실행하고 functionCall 파트와 함께 toolCall/toolResponse 파트를 반환
  3. LiteLLM이 서버 측 호출을 provider_specific_fields["server_side_tool_invocations"]로 추출
  4. 후속 턴에는 대화 히스토리에 전체 assistant 메시지를 포함하면 LiteLLM이 서버 측 파트를 자동으로 재주입

참고:

  • Context circulation은 Gemini 3+ 모델 필요
  • 서버 측 도구 호출(toolCall/toolResponse)은 tool_calls에 포함되지 않음. 이미 Google이 실행했기 때문이며 provider_specific_fields["server_side_tool_invocations"]에 있음
  • 다중 턴 일관성을 위해 thought_signatures가 서버 측 호출과 함께 자동 보존됨
from litellm import completion

response = completion(
    model="gemini/gemini-3.8-flash",
    messages=[{"role": "user", "content": "What's the weather in Buenos Aires? If it's raining, schedule a meeting."}],
    tools=[
        {"type": "web_search_preview"},  # Google Search (server-side)
        {
            "type": "function",
            "function": {
                "name": "schedule_meeting",
                "description": "Schedule a meeting",
                "parameters": {
                    "type": "object",
                    "properties": {"reason": {"type": "string"}},
                    "required": ["reason"],
                },
            },
        },
    ],
    include_server_side_tool_invocations=True,
)

msg = response.choices[0].message

# Server-side tool results are in provider_specific_fields
psf = msg.provider_specific_fields or {}
for invocation in psf.get("server_side_tool_invocations", []):
    print(invocation["tool_type"])  # e.g. "GOOGLE_SEARCH_WEB"
    print(invocation["id"])
    print(invocation["args"])  # e.g. {"queries": ["weather Buenos Aires"]}
    print(invocation["response"])  # Search results from Google

# For multi-turn: just append the full message to history
messages.append(msg)
messages.append({"role": "user", "content": "Thanks!"})

# LiteLLM automatically re-injects the server-side parts + thought signatures
response2 = completion(
    model="gemini/gemini-3.8-flash",
    messages=messages,
    tools=tools,
    include_server_side_tool_invocations=True,
)

Proxy config.yaml:

model_list:
  - model_name: gemini-3.8-flash
    litellm_params:
      model: gemini/gemini-3.8-flash
      api_key: os.environ/GEMINI_API_KEY
$ litellm --config /path/to/config.yaml
curl -X POST 'http://0.0.0.0:4000/chat/completions' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer ***" \
  -d '{
    "model": "gemini-3.8-flash",
    "messages": [{"role": "user", "content": "What is the weather in Buenos Aires?"}],
    "tools": [
      {"type": "web_search_preview"},
      {"type": "function", "function": {
        "name": "schedule_meeting",
        "description": "Schedule a meeting",
        "parameters": {"type": "object", "properties": {"reason": {"type": "string"}}}
      }}
    ],
    "include_server_side_tool_invocations": true
  }'

URL Context

from litellm import completion
import os

os.environ["GEMINI_API_KEY"] = ".."

# 👇 ADD URL CONTEXT
tools = [{"urlContext": {}}]

response = completion(
    model="gemini/gemini-3.8-flash",
    messages=[{"role": "user", "content": "Summarize this document: https://ai.google.dev/gemini-api/docs/models"}],
    tools=tools,
)
print(response)

# Access URL context metadata
url_context_metadata = response.model_extra['vertex_ai_url_context_metadata']
urlMetadata = url_context_metadata[0]['urlMetadata'][0]
print(f"Retrieved URL: {urlMetadata['retrievedUrl']}")
print(f"Retrieval Status: {urlMetadata['urlRetrievalStatus']}")

Proxy config.yaml:

model_list:
  - model_name: gemini-3.8-flash
    litellm_params:
      model: gemini/gemini-3.8-flash
      api_key: os.environ/GEMINI_API_KEY
$ litellm --config /path/to/config.yaml
curl -X POST 'http://0.0.0.0:4000/chat/completions' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer <YOUR-...KEY>" \
  -d '{
    "model": "gemini-3.8-flash",
    "messages": [{"role": "user", "content": "Summarize this document: https://ai.google.dev/gemini-api/docs/models"}],
    "tools": [{"urlContext": {}}]
  }'

Google Search Retrieval

from litellm import completion
import os

os.environ["GEMINI_API_KEY"] = ".."
tools = [{"googleSearch": {}}]  # 👈 ADD GOOGLE SEARCH

response = completion(
    model="gemini/gemini-3.8-flash",
    messages=[{"role": "user", "content": "What is the weather in San Francisco?"}],
    tools=tools,
)
print(response)

Code Execution Tool

from litellm import completion
import os

os.environ["GEMINI_API_KEY"] = ".."
tools = [{"codeExecution": {}}]  # 👈 ADD CODE EXECUTION

response = completion(
    model="gemini/gemini-3.8-flash",
    messages=[{"role": "user", "content": "What is the weather in San Francisco?"}],
    tools=tools,
)
print(response)

Proxy config.yaml:

model_list:
  - model_name: gemini-3.8-flash
    litellm_params:
      model: gemini/gemini-3.8-flash
      api_key: os.environ/GEMINI_API_KEY
$ litellm --config /path/to/config.yaml
curl -X POST 'http://0.0.0.0:4000/chat/completions' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer ***" \
  -d '{
    "model": "gemini-3.8-flash",
    "messages": [{"role": "user", "content": "What is the weather in San Francisco?"}],
    "tools": [{"codeExecution": {}}]
  }'

Computer Use Tool

from litellm import completion
import os

os.environ["GEMINI_API_KEY"] = "your-api-key"

# Computer Use tool with browser environment
tools = [
    {
        "type": "computer_use",
        "environment": "browser",  # optional: "browser" or "unspecified"
        "excluded_predefined_functions": ["drag_and_drop"]  # optional
    }
]

messages = [
    {
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": "Navigate to google.com and search for 'LiteLLM'"
            },
            {
                "type": "image_url",
                "image_url": {
                    "url": "data:image/png;base64,..."  # screenshot of current browser state
                }
            }
        ]
    }
]

response = completion(
    model="gemini/gemini-2.5-computer-use-preview-10-2025",
    messages=messages,
    tools=tools,
)
print(response)

# Handling tool responses with screenshots
# When the model makes a tool call, send the response back with a screenshot:
if response.choices[0].message.tool_calls:
    tool_call = response.choices[0].message.tool_calls[0]
    # Add assistant message with tool call
    messages.append(response.choices[0].message.model_dump())
    # Add tool response with screenshot
    messages.append({
        "role": "tool",
        "tool_call_id": tool_call.id,
        "content": [
            {
                "type": "text",
                "text": '{"url": "https://example.com", "status": "completed"}'
            },
            {
                "type": "input_image",
                "image_url": "data:image/png;base64,..."  # New screenshot after action (Can send an image url as well, litellm handles the conversion)
            }
        ]
    })
    # Continue conversation with updated screenshot
    response = completion(
        model="gemini/gemini-2.5-computer-use-preview-10-2025",
        messages=messages,
        tools=tools,
    )

Proxy config.yaml:

model_list:
  - model_name: gemini-computer-use
    litellm_params:
      model: gemini/gemini-2.5-computer-use-preview-10-2025
      api_key: os.environ/GEMINI_API_KEY
litellm --config /path/to/config.yaml
curl http://0.0.0.0:4000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ***" \
  -d '{
    "model": "gemini-computer-use",
    "messages": [
      {
        "role": "user",
        "content": [
          { "type": "text", "text": "Click on the search button" },
          { "type": "image_url", "image_url": { "url": "data:image/png;base64,..." } }
        ]
      }
    ],
    "tools": [
      { "type": "computer_use", "environment": "browser" }
    ]
  }'

도구 응답 형식: Computer Use 도구 호출에 응답할 때 URL과 스크린샷을 포함해요:

{
  "role": "tool",
  "tool_call_id": "call_abc123",
  "content": [
    { "type": "text", "text": "{\"url\": \"https://example.com\", \"status\": \"completed\"}" },
    { "type": "input_image", "image_url": "data:image/png;base64,..." }
  ]
}

환경 매핑

LiteLLM 입력 Gemini API 값
"browser" ENVIRONMENT_BROWSER
"unspecified" ENVIRONMENT_UNSPECIFIED
ENVIRONMENT_BROWSER ENVIRONMENT_BROWSER (패스스루)
ENVIRONMENT_UNSPECIFIED ENVIRONMENT_UNSPECIFIED (패스스루)

Thought Signatures

Thought signatures는 대화의 특정 턴에 대한 모델 내부 추론 과정의 암호화된 표현이에요. 후속 요청에서 thought signatures를 모델에 다시 전달하면 이전 생각의 컨텍스트를 제공해 일관된 추론을 유지할 수 있어요. 특히 여러 도구 호출에서 컨텍스트를 유지해야 하는 다중 턴 function calling 시나리오에서 중요해요.

Thought Signatures 동작 방식

  • 서명이 있는 함수 호출: Gemini가 function call을 반환할 때 응답에 thought_signature 포함
  • 보존: LiteLLM이 tool call의 provider_specific_fields에서 thought signatures를 자동 추출·저장
  • 대화 히스토리 반환: tool call이 있는 assistant 메시지를 후속 요청에 포함하면 LiteLLM이 Gemini에 thought signatures를 자동 보존·반환
  • 병렬 함수 호출: 병렬 집합의 첫 번째 함수 호출만 thought signature를 가짐
  • 순차 함수 호출: 다단계 시퀀스의 각 함수 호출은 자체 서명을 가짐

Thought Signatures 활성화

thought signatures를 얻으려면 thinking/reasoning을 활성화해야 해요.

from litellm import completion

response = completion(
    model="gemini/gemini-3.8-flash",
    messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
    tools=[...],
    reasoning_effort="low",  # Enable thinking to get thought signatures
)
curl http://localhost:4000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ***" \
  -d '{
    "model": "gemini-3.8-flash",
    "messages": [{"role": "user", "content": "What's the weather in Tokyo?"}],
    "tools": [...],
    "reasoning_effort": "low"
  }'

thought signatures가 포함된 응답

{
  "choices": [{
    "message": {
      "role": "assistant",
      "tool_calls": [{
        "id": "call_abc123",
        "type": "function",
        "function": {
          "name": "get_current_temperature",
          "arguments": "{\"location\": \"London\"}"
        },
        "index": 0,
        "provider_specific_fields": {
          "thought_signature": "CpcHAdHtim9+q4rstcbvQC0ic4x1/vqQlCJWgE+UZ6dTLYGHMMBkF/AxqL5UmP6SY46uYC8t4BTFiXG5zkw6EMJ...=="
        }
      }]
    }
  }]
}

thought signatures가 포함된 다중 턴 function calling

from openai import OpenAI
import json

client = OpenAI(api_key="sk-<your-litellm-api-key>", base_url="http://localhost:4000")

def get_current_temperature(location: str) -> dict:
    """Gets the current weather temperature for a given location."""
    return {"temperature": 30, "unit": "celsius"}

def set_thermostat_temperature(temperature: int) -> dict:
    """Sets the thermostat to a desired temperature."""
    return {"status": "success"}

get_weather_declaration = {
    "name": "get_current_temperature",
    "description": "Gets the current weather temperature for a given location.",
    "parameters": {"type": "object", "properties": {"location": {"type": "string"}}, "required": ["location"]},
}
set_thermostat_declaration = {
    "name": "set_thermostat_temperature",
    "description": "Sets the thermostat to a desired temperature.",
    "parameters": {"type": "object", "properties": {"temperature": {"type": "integer"}}, "required": ["temperature"]},
}

# Initial request
messages = [
    {"role": "user", "content": "If it's too hot or too cold in London, set the thermostat to a comfortable level."}
]
response = client.chat.completions.create(
    model="gemini-3.8-flash",
    messages=messages,
    tools=[get_weather_declaration, set_thermostat_declaration],
    reasoning_effort="low"
)

# Append the assistant's message (includes thought signatures automatically)
messages.append(response.choices[0].message)

# Execute tool calls and append results
for tool_call in response.choices[0].message.tool_calls:
    if tool_call.function.name == "get_current_temperature":
        result = get_current_temperature(**json.loads(tool_call.function.arguments))
        messages.append({"role": "tool", "content": json.dumps(result), "tool_call_id": tool_call.id})

# Second request - thought signatures are automatically preserved
response2 = client.chat.completions.create(
    model="gemini-3.8-flash",
    messages=messages,
    tools=[get_weather_declaration, set_thermostat_declaration],
    reasoning_effort="low"
)
print(response2.choices[0].message.content)

중요 참고 사항

  • 자동 처리: LiteLLM은 Gemini 응답에서 thought signatures를 자동 추출하고 대화 히스토리에 assistant 메시지를 포함할 때 보존해요. 수동 추출·관리가 필요 없어요.
  • 병렬 함수 호출: 모델이 병렬 함수 호출을 하면 첫 번째 함수 호출만 thought signature를 갖고, 이후 병렬 호출은 갖지 않아요.
  • 순차 함수 호출: 다단계 function calling에서 각 단계의 첫 함수 호출은 보존해야 할 자체 thought signature를 가져요.
  • 컨텍스트 필수: thought signatures는 function calling이 있는 다중 턴 대화에서 추론 컨텍스트를 유지하는 데 필수예요. 없으면 모델이 이전 추론의 컨텍스트를 잃을 수 있어요.
  • 형식: thought signatures는 응답의 tool call provider_specific_fields.thought_signature에 저장되고, assistant 메시지를 대화 히스토리에 추가할 때 자동 포함돼요.
  • Chat Completions 클라이언트: 이전 assistant 메시지를 그대로 포함할지 제어할 수 없는 chat completions 클라이언트(예: langchain의 ChatOpenAI)에서는 LiteLLM이 tool call id(call_123__thought__<thought-signature>)에 thought signature를 추가해 보존하고, Gemini로의 outbound 요청을 보내기 전에 다시 추출해요.

JSON Mode

from litellm import completion
import json
import os

os.environ['GEMINI_API_KEY'] = ""
messages = [
    {"role": "user", "content": "List 5 popular cookie recipes."}
]

completion(
    model="gemini/gemini-3.1-pro-preview",
    messages=messages,
    response_format={"type": "json_object"}  # 👈 KEY CHANGE
)
print(json.loads(completion.choices[0].message.content))

Proxy config.yaml:

model_list:
  - model_name: gemini-3.1-pro-preview
    litellm_params:
      model: gemini/gemini-3.1-pro-preview
      api_key: os.environ/GEMINI_API_KEY
$ litellm --config /path/to/config.yaml
curl -X POST 'http://0.0.0.0:4000/chat/completions' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer ***" \
  -d '{
    "model": "gemini-3.1-pro-preview",
    "messages": [
      {"role": "user", "content": "List 5 popular cookie recipes."}
    ],
    "response_format": {"type": "json_object"}
  }'

Gemini-Pro-Vision

LiteLLM은 url로 전달되는 다음 이미지 유형을 지원해요:

from litellm import completion

messages = [
    {
        "role": "user",
        "content": [
            {
                "type": "image_url",
                "image_url": {
                    "url": "https://example.com/chart.png",
                    "detail": "high"  # High resolution for detailed chart analysis
                }
            },
            {
                "type": "text",
                "text": "Analyze this chart"
            },
            {
                "type": "image_url",
                "image_url": {
                    "url": "https://example.com/icon.png",
                    "detail": "low"  # Low resolution for simple icon
                }
            }
        ]
    }
]

# Works with both Gemini 2.x and 3+
response = completion(
    model="gemini/gemini-3.8-flash",  # or gemini-3.1-pro-preview
    messages=messages,
)

미디어 해상도 제어 (이미지 & 비디오)

LiteLLM은 Gemini 모델 사용 시 OpenAI의 detail 파라미터를 지원해요. 동작은 Gemini 버전에 따라 달라요:

Gemini 버전 해상도 제어 동작
Gemini 3+ 파트별 각 이미지/비디오가 자체 detail 설정 가능
Gemini 2.x (2.0, 2.5) 전역 모든 이미지의 가장 높은 detail이 generationConfig의 mediaResolution으로 전역 적용

지원 detail 값:

  • "low" — MEDIA_RESOLUTION_LOW (이미지 280 토큰, 비디오 프레임당 70 토큰)
  • "medium" — MEDIA_RESOLUTION_MEDIUM
  • "high" — MEDIA_RESOLUTION_HIGH (이미지 1120 토큰)
  • "ultra_high" — MEDIA_RESOLUTION_ULTRA_HIGH
  • "auto" 또는 None — 모델이 최적 해상도 결정 (media_resolution 미설정)

Gemini 3+ 파트별 해상도: 각 이미지/비디오는 자체 detail 설정이 가능해 혼합 해상도 요청(예: 고해상도 차트 + 저해상도 아이콘)이 가능해요. 이는 image_url과 file 콘텐츠 유형 모두에서 동작해요. Gemini 2.x 전역 해상도: 여러 이미지가 다른 detail 값을 가지면 LiteLLM이 가장 높은 해상도를 찾아 generationConfig의 mediaResolution으로 전역 적용해요(예: 한 이미지가 "low", 다른 것이 "high"면 모든 이미지가 "high" 사용).

비디오 메타데이터 제어

Gemini 3+ 모델에서 LiteLLM은 video_metadata 필드를 통해 세밀한 비디오 처리 제어를 지원해요. 프레임 추출 속도와 비디오 분석 시간 범위를 지정할 수 있어요.

지원 video_metadata 파라미터:

파라미터 타입 설명 예시
fps Number 프레임 추출 속도 (초당 프레임) 5
start_offset String 비디오 클립 처리 시작 시간 "10s"
end_offset String 비디오 클립 처리 종료 시간 "60s"

참고: LiteLLM은 스네이크 케이스 필드 이름을 Gemini API용으로 camelCase로 자동 변환해요: start_offset → startOffset, end_offset → endOffset, fps는 그대로 유지.

⚠️ Gemini 3+ 전용: 이 기능은 Gemini 3.0 이상 모델에서만 사용 가능해요. video_metadata는 비디오 파일용으로 설계되었지만 다른 미디어 유형의 에러 처리는 Vertex AI API에 위임돼요. gs://, https://, base64 인코딩 비디오 파일에서 동작해요.

from litellm import completion

response = completion(
    model="gemini/gemini-3.1-pro-preview",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Analyze this video clip"},
                {
                    "type": "file",
                    "file": {
                        "file_id": "gs://my-bucket/video.mp4",
                        "format": "video/mp4",
                        "video_metadata": {
                            "fps": 5,  # Extract 5 frames per second
                            "start_offset": "10s",  # Start from 10 seconds
                            "end_offset": "60s"  # End at 60 seconds
                        }
                    }
                }
            ]
        }
    ]
)
print(response.choices[0].message.content)

샘플 사용법 (비전)

import os
import litellm
from dotenv import load_dotenv

# Load the environment variables from .env file
load_dotenv()
os.environ["GEMINI_API_KEY"] = os.getenv('GEMINI_API_KEY')

prompt = 'Describe the image in a few sentences.'
# Note: You can pass here the URL or Path of image directly.
image_url = 'https://storage.googleapis.com/github-repo/img/gemini/intro/landmark3.jpg'

# Create the messages payload according to the documentation
messages = [
    {
        "role": "user",
        "content": [
            {"type": "text", "text": prompt},
            {"type": "image_url", "image_url": {"url": image_url}}
        ]
    }
]

# Make the API call to Gemini model
response = litellm.completion(
    model="gemini/gemini-3.1-pro-preview",
    messages=messages,
)

# Extract the response content
content = response.get('choices', [{}])[0].get('message', {}).get('content')

# Print the result
print(content)

gemini-robotics-er-1.5-preview 사용법

from openai import OpenAI
import os
import base64
import json
import re

client = OpenAI(base_url="http://0.0.0.0:4000", api_key="sk-<your-litellm-api-key>")
base64_image = base64.b64encode(open("closeup-object-on-table-many-260nw-1216144471.webp", "rb").read()).decode()

tools = [{"codeExecution": {}}]

response = client.chat.completions.create(
    model="gemini/gemini-robotics-er-1.5-preview",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": "Point to no more than 10 items in the image. The label returned should be an identifying name for the object detected. The answer should follow the json format: [{\"point\": [y, x], \"label\": <label1>}, ...]. The points are in [y, x] format normalized to 0-1000."
                },
                {
                    "type": "image_url",
                    "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}
                }
            ]
        }
    ],
    tools=tools
)

# Extract JSON from markdown code block if present
content = response.choices[0].message.content
match = re.search(r'```json\s*(.*?)\s*```', content, re.DOTALL)
if match:
    json_str = match.group(1)
else:
    json_str = content
try:
    data = json.loads(json_str)
    print(json.dumps(data, indent=2))
except Exception as e:
    print("Error parsing response as JSON:", e)
    print("Response content:", content)

PDF / 비디오 등 파일 사용

인라인 데이터 (예: 오디오 스트림)

LiteLLM은 OpenAI 형식을 따르며 인코딩된 base64 문자열로 인라인 데이터 전송을 받아요. 형식은 아래와 같아요:

data:<mime_type>;base64,<encoded_data>

LITELLM 호출:

import litellm
from pathlib import Path
import base64
import os

os.environ["GEMINI_API_KEY"] = ""
litellm.set_verbose = True  # 👈 See Raw call

audio_bytes = Path("speech_vertex.mp3").read_bytes()
encoded_data = base64.b64encode(audio_bytes).decode("utf-8")
print("Audio Bytes = {}".format(audio_bytes))

model = "gemini/gemini-3.8-flash"
response = litellm.completion(
    model=model,
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Please summarize the audio."},
                {
                    "type": "file",
                    "file": {
                        "file_data": "data:audio/mp3;base64,{}".format(encoded_data),  # 👈 SET MIME_TYPE + DATA
                    },
                },
            ],
        }
    ],
)

등가 GOOGLE API 호출:

# Initialize a Gemini model appropriate for your use case.
model = genai.GenerativeModel('models/gemini-3.8-flash')

# Create the prompt.
prompt = "Please summarize the audio."

# Load the samplesmall.mp3 file into a Python Blob object containing the audio
# file's bytes and then pass the prompt and the audio to Gemini.
response = model.generate_content([
    prompt,
    {
        "mime_type": "audio/mp3",
        "data": pathlib.Path('samplesmall.mp3').read_bytes()
    }
])

# Output Gemini's response to the prompt and the inline audio.
print(response.text)

https:// 파일

import litellm
import os

os.environ["GEMINI_API_KEY"] = ""
litellm.set_verbose = True  # 👈 See Raw call

model = "gemini/gemini-3.8-flash"
response = litellm.completion(
    model=model,
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Please summarize the file."},
                {
                    "type": "file",
                    "file": {
                        "file_id": "https://storage...",  # 👈 SET THE IMG URL
                        "format": "application/pdf"  # OPTIONAL
                    },
                },
            ],
        }
    ],
)

gs:// 파일

import litellm
import os

os.environ["GEMINI_API_KEY"] = ""
litellm.set_verbose = True  # 👈 See Raw call

model = "gemini/gemini-3.8-flash"
response = litellm.completion(
    model=model,
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Please summarize the file."},
                {
                    "type": "file",
                    "file": {
                        "file_id": "gs://storage...",  # 👈 SET THE IMG URL
                        "format": "application/pdf"  # OPTIONAL
                    },
                },
            ],
        }
    ],
)

Chat 모델

모든 Gemini 모델을 지원해요. litellm 요청 시 model=gemini/<any-model-on-gemini> 접두사로 설정하기만 하면 돼요.

모델 이름 함수 호출 필수 OS 변수
gemini-pro completion(model='gemini/gemini-pro', messages) os.environ['GEMINI_API_KEY']
gemini-1.5-pro-latest completion(model='gemini/gemini-1.5-pro-latest', messages) os.environ['GEMINI_API_KEY']
gemini-2.0-flash completion(model='gemini/gemini-2.0-flash', messages) os.environ['GEMINI_API_KEY']
gemini-2.0-flash-exp completion(model='gemini/gemini-2.0-flash-exp', messages) os.environ['GEMINI_API_KEY']
gemini-2.0-flash-lite-preview-02-05 completion(model='gemini/gemini-2.0-flash-lite-preview-02-05', messages) os.environ['GEMINI_API_KEY']
gemini-2.5-flash-preview-09-2025 completion(model='gemini/gemini-2.5-flash-preview-09-2025', messages) os.environ['GEMINI_API_KEY']
gemini-2.5-flash-lite-preview-09-2025 completion(model='gemini/gemini-2.5-flash-lite-preview-09-2025', messages) os.environ['GEMINI_API_KEY']
gemini-3.1-flash-lite-preview completion(model='gemini/gemini-3.1-flash-lite-preview', messages) os.environ['GEMINI_API_KEY']
gemini-flash-latest completion(model='gemini/gemini-flash-latest', messages) os.environ['GEMINI_API_KEY']
gemini-flash-lite-latest completion(model='gemini/gemini-flash-lite-latest', messages) os.environ['GEMINI_API_KEY']

Context Caching

Google AI Studio context caching은 메시지 콘텐츠 블록에서 "cache_control": {"type": "ephemeral"}로 지원돼요.

{
    {
        "role": "system",
        "content": ...,
        "cache_control": {"type": "ephemeral"}  # 👈 KEY CHANGE
    },
    ...
}

Custom TTL 지원

ttl 파라미터로 캐시된 콘텐츠의 사용자 지정 Time-To-Live(TTL)를 지정할 수 있어요.

TTL 형식 요구사항:

  • 초를 나타내는 's'로 끝나는 문자열이어야 함
  • 양수(소수 가능)를 포함해야 함
  • 예시: "3600s"(1시간), "7200s"(2시간), "1800s"(30분), "1.5s"(1.5초)

TTL 동작:

  • 여러 캐시된 메시지가 다른 TTL을 가지면 첫 번째 유효 TTL이 사용됨
  • 잘못된 TTL 형식은 무시되고 cache는 Google 기본 만료 시간 사용
  • TTL을 지정하지 않으면 Google 기본 캐시 만료(약 1시간) 적용
{
    {
        "role": "system",
        "content": ...,
        "cache_control": {
            "type": "ephemeral",
            "ttl": "3600s"  # 👈 Cache for 1 hour
        }
    },
    ...
}

Architecture의 raw 요청:

curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent?key=$GOOGLE_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "contents": [
      {
        "parts":[ { "text": "Please summarize this transcript" } ],
        "role": "user"
      },
    ],
    "cachedContent": "'$CACHE_NAME'"
  }'

참고:

  • Gemini Context Caching은 연속적인 메시지 블록 한 개만 캐시할 수 있어요.
  • cache_control을 포함한 비연속 블록이 여러 개면 첫 번째 연속 블록이 사용돼요 (Gemini 형식의 /cachedContent로 전송).

예시 사용법 (SDK)

from litellm import completion

for _ in range(2):
    resp = completion(
        model="gemini/gemini-3.1-pro-preview",
        messages=[
            # System Message
            {
                "role": "system",
                "content": [
                    {
                        "type": "text",
                        "text": "Here is the full text of a complex legal agreement" * 4000,
                        "cache_control": {"type": "ephemeral"},  # 👈 KEY CHANGE
                    }
                ],
            },
            # marked for caching with the cache_control parameter, so that this checkpoint can read from the previous cache.
            {
                "role": "user",
                "content": [
                    {
                        "type": "text",
                        "text": "What are the key terms and conditions in this agreement?",
                        "cache_control": {"type": "ephemeral"},
                    }
                ],
            }
        ]
    )
    print(resp.usage)  # 👈 2nd usage block will be less, since cached tokens used

사용자 지정 TTL (SDK)

from litellm import completion

# Cache for 2 hours (7200 seconds)
resp = completion(
    model="gemini/gemini-3.1-pro-preview",
    messages=[
        {
            "role": "system",
            "content": [
                {
                    "type": "text",
                    "text": "Here is the full text of a complex legal agreement" * 4000,
                    "cache_control": {
                        "type": "ephemeral",
                        "ttl": "7200s"  # 👈 Cache for 2 hours
                    },
                }
            ],
        },
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": "What are the key terms and conditions in this agreement?",
                    "cache_control": {
                        "type": "ephemeral",
                        "ttl": "3600s"  # 👈 This TTL will be ignored (first one is used)
                    },
                }
            ],
        }
    ]
)
print(resp.usage)

Proxy config.yaml:

model_list:
  - model_name: gemini-3.1-pro-preview
    litellm_params:
      model: gemini/gemini-3.1-pro-preview
      api_key: os.environ/GEMINI_API_KEY
litellm --config /path/to/config.yaml

Curl:

curl --location 'http://0.0.0.0:4000/chat/completions' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "gemini-3.1-pro-preview",
    "messages": [
      {
        "role": "system",
        "content": [
          {
            "type": "text",
            "text": "Here is the full text of a complex legal agreement" * 4000,
            "cache_control": {"type": "ephemeral"}
          }
        ],
      },
      {
        "role": "user",
        "content": [
          {
            "type": "text",
            "text": "What are the key terms and conditions in this agreement?",
            "cache_control": {"type": "ephemeral"}
          }
        ],
      }
    ],
  }'

OpenAI Python SDK:

import openai

client = openai.AsyncOpenAI(
    api_key="anything",  # litellm proxy api key
    base_url="http://0.0.0.0:4000"  # litellm proxy base url
)

response = await client.chat.completions.create(
    model="gemini-3.1-pro-preview",
    messages=[
        {
            "role": "system",
            "content": [
                {
                    "type": "text",
                    "text": "Here is the full text of a complex legal agreement" * 4000,
                    "cache_control": {"type": "ephemeral"},  # 👈 KEY CHANGE
                }
            ],
        },
        {
            "role": "user",
            "content": "what are the key terms and conditions in this agreement?",
        },
    ]
)

이미지 생성 (Image Generation)

from litellm import completion

response = completion(
    model="gemini/gemini-2.0-flash-exp-image-generation",
    messages=[{"role": "user", "content": "Generate an image of a cat"}],
    modalities=["image", "text"],
)
assert response.choices[0].message.content is not None  # "data:image/png;base64,e4rr.."

Proxy config.yaml:

model_list:
  - model_name: gemini-2.0-flash-exp-image-generation
    litellm_params:
      model: gemini/gemini-2.0-flash-exp-image-generation
      api_key: os.environ/GEMINI_API_KEY
litellm --config /path/to/config.yaml
curl -L -X POST 'http://localhost:4000/v1/chat/completions' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer ***" \
  -d '{
    "model": "gemini-2.0-flash-exp-image-generation",
    "messages": [{"role": "user", "content": "Generate an image of a cat"}],
    "modalities": ["image", "text"]
  }'

사용량 세부 사항:

{
  "completion_tokens_details": {
    "reasoning_tokens": 225,
    "text_tokens": 0,
    "image_tokens": 1120
  }
}

더 알아보기 (Learn more)