반응형
LLM을 여러 개 쓰다 보면 이런 문제가 생겨요.
# Claude 쓸 때
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "안녕"}]
)
text = response.content[0].text # 이렇게 꺼냄
# GPT 쓸 때 → SDK 다르고, 응답 형식 다름
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-5.4",
messages=[{"role": "user", "content": "안녕"}]
)
text = response.choices[0].message.content # 이렇게 꺼냄
# Gemini → 또 다른 방식
# Ollama → 또 다른 방식
# Azure → 또 다른 방식
모델마다 SDK 따로, 응답 형식 따로, 에러 처리 따로예요.
LiteLLM은 이걸 전부 OpenAI 형식으로 통일해줘요.
import litellm
# Claude
response = litellm.completion(
model="claude-sonnet-4-6",
messages=[{"role": "user", "content": "안녕"}]
)
# GPT → 코드 한 줄도 안 바꿈
response = litellm.completion(
model="gpt-5.4",
messages=[{"role": "user", "content": "안녕"}]
)
# 응답 꺼내는 방법도 동일
text = response.choices[0].message.content
LiteLLM이 뭔가
BerriAI가 만든 오픈소스 Python SDK이자 프록시 서버예요.
GitHub 스타: 20,000+
라이선스: MIT
지원 모델: 100개+ LLM
Claude, GPT, Gemini, Llama, Mistral,
Ollama, Azure, Bedrock, HuggingFace...
두 가지 방식으로 사용해요:
1. Python SDK: 코드에 직접 임포트해서 사용
2. Proxy 서버: 팀 전체가 하나의 엔드포인트로 사용
1. Python SDK 사용법
설치
pip install litellm
# 특정 프로바이더 추가
pip install litellm[anthropic]
pip install litellm[openai]
pip install 'litellm[all]' # 전부
기본 사용
import litellm
import os
# API 키 설정
os.environ["ANTHROPIC_API_KEY"] = "sk-ant-xxxxx"
os.environ["OPENAI_API_KEY"] = "sk-xxxxx"
os.environ["GEMINI_API_KEY"] = "AIzaxxx"
# Claude
response = litellm.completion(
model="claude-sonnet-4-6",
messages=[{"role": "user", "content": "파이썬 퀵소트 구현해줘"}]
)
print(response.choices[0].message.content)
# GPT → 동일한 코드
response = litellm.completion(
model="gpt-5.4-mini",
messages=[{"role": "user", "content": "파이썬 퀵소트 구현해줘"}]
)
print(response.choices[0].message.content)
# Gemini → 동일한 코드
response = litellm.completion(
model="gemini/gemini-3.1-flash",
messages=[{"role": "user", "content": "파이썬 퀵소트 구현해줘"}]
)
print(response.choices[0].message.content)
# 로컬 Ollama → 동일한 코드
response = litellm.completion(
model="ollama/llama4",
messages=[{"role": "user", "content": "파이썬 퀵소트 구현해줘"}]
)
print(response.choices[0].message.content)
비동기 사용
import litellm
import asyncio
async def ask(model: str, question: str) -> str:
response = await litellm.acompletion(
model=model,
messages=[{"role": "user", "content": question}]
)
return response.choices[0].message.content
# 여러 모델 동시 호출
async def compare_models(question: str):
models = [
"claude-sonnet-4-6",
"gpt-5.4-mini",
"gemini/gemini-3.1-flash",
]
tasks = [ask(m, question) for m in models]
results = await asyncio.gather(*tasks)
for model, result in zip(models, results):
print(f"\n[{model}]\n{result}")
asyncio.run(compare_models("파이썬 GIL이 뭔가요?"))
스트리밍
response = litellm.completion(
model="claude-sonnet-4-6",
messages=[{"role": "user", "content": "긴 글 써줘"}],
stream=True
)
for chunk in response:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
비용 추적
import litellm
response = litellm.completion(
model="claude-sonnet-4-6",
messages=[{"role": "user", "content": "안녕"}]
)
# 토큰 사용량
print(response.usage.prompt_tokens) # 입력 토큰
print(response.usage.completion_tokens) # 출력 토큰
print(response.usage.total_tokens) # 합계
# 비용 계산
cost = litellm.completion_cost(completion_response=response)
print(f"비용: ${cost:.6f}")
2. Router — 폴백 + 로드밸런싱
Router는 여러 모델을 묶어서 자동으로 관리해줘요.
자동 폴백
Claude가 죽으면 GPT로, GPT도 죽으면 Gemini로 자동 전환해요.
from litellm import Router
router = Router(
model_list=[
{
"model_name": "my-claude",
"litellm_params": {
"model": "claude-sonnet-4-6",
"api_key": "sk-ant-xxxxx",
}
},
{
"model_name": "my-gpt",
"litellm_params": {
"model": "gpt-5.4-mini",
"api_key": "sk-xxxxx",
}
},
{
"model_name": "my-gemini",
"litellm_params": {
"model": "gemini/gemini-3.1-flash",
"api_key": "AIzaxxx",
}
},
],
# 폴백 설정
fallbacks=[
{"my-claude": ["my-gpt", "my-gemini"]}
],
# 재시도 설정
num_retries=3,
timeout=30,
# 레이트 리밋 폴백
context_window_fallbacks=[
{"my-claude": ["my-gemini"]} # 컨텍스트 초과 시 Gemini로
]
)
# 사용 — 폴백은 자동으로 처리됨
response = router.completion(
model="my-claude",
messages=[{"role": "user", "content": "안녕"}]
)
print(response.choices[0].message.content)
로드밸런싱
같은 모델을 여러 API 키로 분산해서 레이트 리밋 회피해요.
router = Router(
model_list=[
# Claude를 3개 키로 분산
{
"model_name": "claude",
"litellm_params": {
"model": "claude-sonnet-4-6",
"api_key": "sk-ant-key1",
}
},
{
"model_name": "claude",
"litellm_params": {
"model": "claude-sonnet-4-6",
"api_key": "sk-ant-key2",
}
},
{
"model_name": "claude",
"litellm_params": {
"model": "claude-sonnet-4-6",
"api_key": "sk-ant-key3",
}
},
],
# 라우팅 전략
routing_strategy="least-busy", # 가장 덜 바쁜 키로
# 옵션: "simple-shuffle", "usage-based-routing", "latency-based-routing"
)
# 자동으로 3개 키 중 하나로 분산
response = router.completion(
model="claude",
messages=[{"role": "user", "content": "안녕"}]
)
3. Proxy 서버 — 팀 전체 LLM 게이트웨이
Proxy는 팀 전체가 하나의 엔드포인트로 모든 LLM을 쓸 수 있게 해줘요.
팀원 A (Python) ──→
팀원 B (Node.js) ──→ LiteLLM Proxy ──→ Claude/GPT/Gemini
팀원 C (cURL) ──→
외부 서비스 ──→
config.yaml 작성
# litellm_config.yaml
model_list:
- model_name: claude-fast # 팀 내부에서 쓰는 이름
litellm_params:
model: claude-haiku-4-5 # 실제 모델
api_key: sk-ant-xxxxx
- model_name: claude-smart
litellm_params:
model: claude-sonnet-4-6
api_key: sk-ant-xxxxx
- model_name: gpt-cheap
litellm_params:
model: gpt-5.4-mini
api_key: sk-xxxxx
- model_name: gpt-smart
litellm_params:
model: gpt-5.4
api_key: sk-xxxxx
- model_name: local
litellm_params:
model: ollama/llama4
api_base: http://localhost:11434
litellm_settings:
# 폴백 설정
fallbacks:
- claude-smart: [gpt-smart]
- claude-fast: [gpt-cheap, local]
# 재시도
num_retries: 3
router_settings:
routing_strategy: least-busy
Proxy 서버 실행
# pip로 실행
pip install litellm[proxy]
litellm --config litellm_config.yaml --port 4000
# Docker로 실행 (권장)
docker run \
-v $(pwd)/litellm_config.yaml:/app/config.yaml \
-p 4000:4000 \
ghcr.io/berriai/litellm:main-latest \
--config /app/config.yaml
팀원들이 쓰는 방법
Proxy가 뜨면 OpenAI SDK로 그냥 쓰면 돼요. 코드 변경 없음.
# Python — base_url만 바꾸면 됨
from openai import OpenAI
client = OpenAI(
api_key="sk-1234", # Proxy 가상 키 (아무 값)
base_url="http://localhost:4000" # Proxy URL
)
response = client.chat.completions.create(
model="claude-smart", # config.yaml에 정의한 이름
messages=[{"role": "user", "content": "안녕"}]
)
print(response.choices[0].message.content)
// JavaScript
import OpenAI from "openai";
const client = new OpenAI({
apiKey: "sk-1234",
baseURL: "http://localhost:4000",
});
const response = await client.chat.completions.create({
model: "claude-smart",
messages: [{ role: "user", content: "안녕" }],
});
# cURL
curl http://localhost:4000/chat/completions \
-H "Authorization: Bearer sk-1234" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-smart",
"messages": [{"role": "user", "content": "안녕"}]
}'
가상 키로 팀별 접근 제어
# 가상 키 발급 (팀원별 또는 프로젝트별)
curl http://localhost:4000/key/generate \
-H "Authorization: Bearer sk-admin" \
-d '{
"key_alias": "team-backend",
"models": ["claude-smart", "claude-fast"],
"max_budget": 50, # 월 $50 한도
"budget_duration": "1mo"
}'
# 응답: {"key": "sk-backend-xxxxx", ...}
팀원에게 sk-backend-xxxxx 키 배포하면 Claude만 쓸 수 있고, 월 $50 넘으면 자동 차단돼요.
4. 실전 활용 패턴
패턴 1 — 작업별 모델 라우팅
from litellm import Router
router = Router(model_list=[...])
def smart_route(task_type: str, prompt: str) -> str:
"""작업 유형에 따라 최적 모델 자동 선택"""
model_map = {
"coding": "claude-smart", # 코딩은 Claude
"summary": "gpt-cheap", # 요약은 저렴한 GPT
"analysis": "claude-smart", # 분석도 Claude
"translate": "gpt-cheap", # 번역은 저렴하게
"creative": "claude-smart", # 창작은 Claude
}
model = model_map.get(task_type, "claude-fast")
response = router.completion(
model=model,
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
# 사용
code = smart_route("coding", "파이썬 퀵소트 구현해줘")
summary = smart_route("summary", "이 문서 요약해줘: ...")
패턴 2 — 비용 모니터링
import litellm
total_cost = 0
def tracked_completion(model: str, messages: list) -> str:
response = litellm.completion(model=model, messages=messages)
cost = litellm.completion_cost(completion_response=response)
global total_cost
total_cost += cost
print(f"[{model}] ${cost:.6f} (누적: ${total_cost:.4f})")
return response.choices[0].message.content
# 사용
result = tracked_completion(
"claude-sonnet-4-6",
[{"role": "user", "content": "안녕"}]
)
# 출력: [claude-sonnet-4-6] $0.000045 (누적: $0.0001)
패턴 3 — 기존 코드 마이그레이션
OpenAI SDK 쓰던 코드를 LiteLLM으로 전환할 때예요.
# Before: OpenAI SDK 직접 사용
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-5.4",
messages=[{"role": "user", "content": "안녕"}]
)
# After: LiteLLM으로 전환 (응답 형식 동일)
import litellm
response = litellm.completion(
model="claude-sonnet-4-6", # 모델만 바꿈
messages=[{"role": "user", "content": "안녕"}]
)
# 응답 꺼내는 방식 동일
text = response.choices[0].message.content
OpenRouter vs LiteLLM 최종 비교
OpenRouter:
✅ 설정 없음 (가입하고 바로)
✅ 200개+ 모델
✅ 무료 모델 있음
❌ 내 데이터가 OpenRouter 서버 통과
❌ 직접 API보다 5~10% 비쌈
→ 개인 프로젝트, 프로토타입
LiteLLM:
✅ 데이터 내 서버에서만 처리
✅ 직접 API 가격 그대로
✅ 팀 접근 제어, 예산 관리
✅ 완전한 커스터마이징
❌ 서버 직접 운영
❌ 초기 설정 필요
→ 기업, 팀 단위, 보안 중요한 환경
반응형
'AI Development' 카테고리의 다른 글
| Claude Code가 멍청해진 이유 — Anthropic이 직접 밝힌 3가지 원인과 수정 내역 (0) | 2026.04.24 |
|---|---|
| Continue.dev 완전 가이드 — GitHub Copilot 대신 쓰는 무료 오픈소스 AI 코딩 어시스턴트 (0) | 2026.04.23 |
| LLM 추상화 레이어 — 48시간마다 새 모델이 나오는 시대에 살아남는 법 (1) | 2026.04.23 |
| GitHub Copilot Agent Mode 실전 가이드 — VS Code에서 자율 코딩 에이전트 쓰는 법 (0) | 2026.04.21 |
| markitdown-ocr 플러그인 — 스캔 PDF, 이미지 속 텍스트까지 뽑아내는 법 (0) | 2026.04.21 |