LiteLLM (Phần 1) — Điều Gì Xảy Ra Khi OpenAI Không Còn Là Lựa Chọn Duy Nhất?
1. Bài Toán Đặt Ra
Hai năm trước, việc tích hợp AI vào sản phẩm là một quyết định khá đơn giản: chọn OpenAI, lấy API key, gọi vài endpoint, xong. Cả tổ chức dùng chung một provider, một SDK, một cách tính chi phí. Kiến trúc gọn gàng vì lựa chọn cũng gọn gàng. Hiện nay bức tranh đó đã thay đổi . Thị trường mô hình ngôn ngữ giờ đây không còn một "người thắng cuộc" duy nhất, mà là một hệ sinh thái nơi mỗi mô hình có thế mạnh riêng, mức giá riêng, và tốc độ tiến hóa riêng. Một mô hình dẫn đầu hôm nay có thể bị vượt qua sau ba tháng; một mô hình đắt đỏ cho tác vụ này lại là lựa chọn lãng phí cho tác vụ khác. Hệ quả tất yếu: các tổ chức trưởng thành không còn cược tất cả vào một nhà cung cấp, mà vận hành một danh mục (portfolio) nhiều mô hình giống như cách một quỹ đầu tư đa dạng hóa danh mục để tối ưu rủi ro và lợi nhuận. Việc chọn nhiều mô hình xuất phát từ những lý do kinh tế và kỹ thuật rất cụ thể:
- Tối ưu chi phí theo tác vụ: Dùng mô hình flagship đắt tiền để phân loại email là lãng phí. Một mô hình nhỏ, nhanh, rẻ làm việc đó tốt hơn nhiều lần về mặt chi phí.
- Tối ưu chất lượng theo tác vụ: Ngược lại, với bài toán reasoning phức tạp hay phân tích tài liệu dài, mô hình mạnh nhất sẽ tiết kiệm nhiều giờ sửa lỗi về sau.
- Tránh phụ thuộc một nhà cung cấp (vendor lock-in): Phụ thuộc hoàn toàn vào một provider đồng nghĩa với việc chấp nhận mọi đợt tăng giá, mọi thay đổi điều khoản, và mọi sự cố downtime của họ.
- Yêu cầu chủ quyền dữ liệu: Một số dữ liệu như hồ sơ khách hàng, tài liệu pháp lý, bí mật kinh doanh đơn giản là không được phép rời khỏi hạ tầng nội bộ, buộc phải dùng mô hình tự host.
Đa dạng hóa mô hình mang lại lợi ích rõ ràng, nhưng nó cũng âm thầm tạo ra một lớp phức tạp mà nhiều đội ngũ chỉ nhận ra khi đã quá muộn. Vấn đề không nằm ở chỗ "gọi được nhiều mô hình" . Vấn đề nằm ở chỗ quản lý và vận hành chúng
- Mỗi provider có một SDK riêng, với cú pháp, kiểu dữ liệu trả về và cơ chế streaming khác nhau.
- Mỗi provider có một cách báo lỗi và rate limit riêng, nghĩa là logic retry phải viết lại cho từng cái.
- Mỗi provider có một bảng giá và đơn vị tính token riêng, khiến việc tổng hợp chi phí rất phức tạp.
- Mỗi provider có độ tin cậy khác nhau theo thời gian, provider tốt nhất hôm nay có thể downtime vào đúng giờ cao điểm ngày mai.
Khi một tổ chức có bốn provider, đó là bốn SDK, bốn cách xử lý lỗi, bốn cách tính chi phí phải duy trì song song. Logic này thường bị nhúng rải rác khắp codebase, lặp lại ở mỗi service, và mỗi khi muốn thêm một provider mới hay đổi cách routing, kỹ sư phải sửa ở hàng chục nơi. Đây chính là điểm đau kỹ thuật đầu tiên. Nếu chỉ dừng ở vấn đề SDK, ta đã có thể giải quyết bằng một lớp abstraction đơn giản. Tuy nhiên, khi AI lan rộng từ một dự án thử nghiệm thành hạ tầng dùng chung cho cả tổ chức hoặc những dự án lớn những câu hỏi quản trị mới là thứ thực sự khiến các lãnh đạo kỹ thuật mất ngủ:
- Kiểm soát chi phí: Khi 10 team cùng gọi AI song song mà không có giới hạn, hóa đơn cuối tháng có thể vượt ngân sách gấp nhiều lần. Làm sao đặt budget cho từng team, từng dự án, và chặn lại trước khi vượt trần?
- Đảm bảo tính sẵn sàng (uptime): Khi một provider gặp sự cố vào đúng giờ cao điểm, toàn bộ tính năng AI có nên sập theo không? Làm sao để hệ thống tự động chuyển sang phương án dự phòng mà người dùng không hề hay biết?
- Truy vết và tuân thủ (audit & compliance): Với các tiêu chuẩn như SOC 2, GDPR, ISO 27001, tổ chức phải chứng minh được ai đã gọi cái gì, khi nào, và kết quả ra sao. Làm sao ghi lại toàn bộ traffic AI một cách đầy đủ và đáng tin cậy?
- Bảo vệ dữ liệu nhạy cảm: Một nhân viên có thể vô tình dán số CCCD, số tài khoản ngân hàng, hay thông tin khách hàng vào prompt rồi gửi thẳng lên cloud. Làm sao phát hiện và chặn điều đó trước khi dữ liệu rời khỏi tổ chức?
Những câu hỏi này không thể giải quyết bằng việc nhúng thêm code vào từng ứng dụng, chúng đòi hỏi một tầng hạ tầng tập trung, đứng giữa ứng dụng và các nhà cung cấp mô hình, nơi mọi request đều đi qua và đều được kiểm soát. Đây chính là lý do LiteLLM ra đời
2. LiteLLM Là Gì?
LiteLLM là một dự án mã nguồn mở (MIT license) do BerriAI phát triển, cung cấp một API thống nhất tương thích OpenAI để gọi hơn 100+ LLM providers. Nói cách khác: bạn viết code một lần theo cú pháp OpenAI, LiteLLM lo việc dịch sang Anthropic, Gemini, AWS Bedrock, Azure, Vertex AI, Cohere, Ollama, vLLM, hay bất kỳ provider nào khác trong danh sách hỗ trợ. Quan trọng hơn là LiteLLM cung cấp toàn bộ hạ tầng cần thiết để chạy một LLM Gateway ở quy mô doanh nghiệp: virtual keys, budget tracking, rate limiting, caching, load balancing, fallback, và observability tất cả tích hợp sẵn, không cần viết thêm.
Theo bài viết "A gentle introduction to LiteLLM" trên Medium (MITB For All), điểm hấp dẫn nhất của LiteLLM nằm ở triết lý "zero code change" và "OpenAI as the lingua franca" đó là
- OpenAI SDK đã là chuẩn de-facto: Mọi framework AI hiện đại (LangChain, LlamaIndex, Haystack, Autogen, AutoGPT) đều hỗ trợ OpenAI-compatible endpoint. LiteLLM tận dụng điều đó nên khi bạn dùng bất kỳ framework nào, miễn nó nói được OpenAI là chạy với LiteLLM.
- Migration: Ứng dụng đang dùng OpenAI thật chỉ cần đổi
base_urllà chuyển hết sang LiteLLM, không sửa code logic. - Cộng đồng và tốc độ phát triển: Repository LiteLLM trên GitHub có hơn 20K stars và release liên tục, provider mới ra đời thường có hỗ trợ trong vòng vài ngày.
2.1 Một số các tính năng
| Tính năng | Mô tả ngắn |
|---|---|
| Unified API | Một cú pháp duy nhất cho 100+ providers, format response luôn theo OpenAI |
| Proxy Server | HTTP server độc lập, dùng được từ mọi ngôn ngữ (không chỉ Python) |
| Router & Load Balancing | 6 chiến lược: simple-shuffle, least-busy, latency-based, usage-based, cost-based... |
| Automatic Fallback | Tự chuyển sang model dự phòng khi gặp lỗi (timeout, rate limit, content policy) |
| Caching | Exact cache + Semantic cache với Redis/Qdrant; DualCache (L1 in-memory + L2 Redis) |
| Virtual Keys | Cấp key riêng cho từng team/app với budget, rate limit, model whitelist |
| Multi-Tenant | Phân cấp Organization → Team → Key với budget và quota riêng biệt |
| Spend Tracking | Theo dõi chi phí theo từng key, user, team, model — lưu trong PostgreSQL |
| Observability | Tích hợp sẵn 20+ platforms: Langfuse, Prometheus, OpenTelemetry, Datadog, MLflow... |
| Guardrails | Hỗ trợ content filtering, PII masking qua plugin (presidio, lakera, aporia...) |
| Streaming | Hỗ trợ streaming response đồng nhất, kể cả khi provider gốc có cú pháp khác |
3. Hai Chế Độ Vận Hành: SDK và Proxy
Một điểm gây nhầm lẫn cho người mới: LiteLLM có hai cách dùng hoàn toàn khác nhau, và lựa chọn giữa chúng quyết định toàn bộ kiến trúc về sau.
3.1 Chế độ SDK: Thư viện Python
┌─────────────────────────────────────┐
│ Python Application │
│ ┌───────────────────────────────┐ │
│ │ import litellm │ │
│ │ litellm.completion(...) │ │
│ └──────────┬────────────────────┘ │
└─────────────┼───────────────────────┘
│ HTTP trực tiếp
▼
OpenAI / Anthropic / Gemini / ...
Bạn pip install litellm rồi gọi litellm.completion() ngay trong code Python. Đơn giản, ít overhead. Nhưng:
- Phù hợp cho: prototype, script nhỏ, notebook, ứng dụng Python đơn lẻ
- Không phù hợp khi: nhiều team cùng dùng, cần audit tập trung, không phải Python, cần quản lý chi phí
3.2 Chế độ Proxy: HTTP gateway độc lập
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Python App │ │ Node.js App │ │ Go Service │
│ (OpenAI SDK) │ │ (OpenAI SDK) │ │ (any HTTP) │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
│ │ │
└──────────┬─────────┴───────────────┬────┘
▼
┌──────────────────────────┐
│ LiteLLM Proxy Server │
│ Auth · Cache · Router │
│ Budget · Logging · ... │
└──────────┬───────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
OpenAI API Anthropic API Local Ollama
LiteLLM chạy như một HTTP server riêng biệt (mặc định port 4000). Mọi app đều gọi vào proxy như đang gọi OpenAI. Đây là chế độ phù hợp cho hệ thống lớn vì:
- Đa ngôn ngữ: Bất kỳ app HTTP nào cũng dùng được
- Tập trung: Một điểm để cấu hình routing, budget, logging
- Cô lập credentials: App chỉ cần virtual key, không bao giờ biết key thật của provider
- Observability: Mọi request đều đi qua proxy nên trace được hết
4. Kiến Trúc và Các Thành Phần Cốt Lõi
Kiến trúc tham chiếu của một LiteLLM Proxy ở quy mô production:
┌─────────────────────────────────────────────────────────────┐
│ CLIENT APPLICATIONS │
└────────────────────────────┬────────────────────────────────┘
│ HTTPS (OpenAI-compatible)
┌────────────────────────────▼────────────────────────────────┐
│ LITELLM PROXY SERVER (cluster N pods) │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 1. Authentication Layer │ │
│ │ ├─ Validate virtual key │ │
│ │ ├─ Check key/team/user budget │ │
│ │ └─ Apply rate limits (RPM/TPM) │ │
│ └────────────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 2. Cache Lookup │ │
│ │ ├─ L1: In-memory exact match │ │
│ │ ├─ L2: Redis exact match │ │
│ │ └─ Semantic cache (Redis vector / Qdrant) │ │
│ └────────────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 3. Router │ │
│ │ ├─ Pick deployment by strategy │ │
│ │ ├─ Skip deployments in cooldown │ │
│ │ └─ Handle fallback chain │ │
│ └────────────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 4. Provider Call + Retry │ │
│ └────────────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 5. Post-Call: Update spend, fire callbacks, cache │ │
│ └────────────────────────────────────────────────────────┘ │
└─────────┬────────────────┬──────────────────┬───────────────┘
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼─────────┐
│ Redis │ │ PostgreSQL │ │ Callbacks │
│ (Cache + │ │ (Keys, │ │ (Langfuse, │
│ shared │ │ Teams, │ │ Prometheus, │
│ state) │ │ Spend) │ │ Datadog...) │
└─────────────┘ └─────────────┘ └────────────────┘
│
▼
┌───────────────────────────────────────────────────────┐
│ LLM PROVIDERS │
│ OpenAI · Anthropic · Gemini · Bedrock · Azure · │
│ Ollama · vLLM · Vertex AI · Cohere · ... │
└───────────────────────────────────────────────────────┘
Hai thành phần state quan trọng cần hiểu rõ:
- PostgreSQL: Lưu virtual keys, teams, spend logs, budget state. Đây là single source of truth — LiteLLM không dùng MySQL vì lý do về tính chính xác trong cập nhật budget dưới tải cao (xem FAQ chính thức của LiteLLM).
- Redis: Lưu cache responses và shared state cho rate limiting/cooldown. Khi có nhiều pod LiteLLM, Redis là thứ cho phép chúng "nói chuyện" với nhau về việc deployment nào đang trong cooldown, budget nào sắp cạn. Hai service này được tách riêng có chủ đích: PostgreSQL ưu tiên tính toàn vẹn (ACID), Redis ưu tiên tốc độ. Trộn lẫn chức năng của hai cái sẽ phá vỡ một trong hai mục tiêu.
5. Cài Đặt và Thiết Lập
5.1 Yêu cầu hệ thống
- Python 3.9+ (khuyến nghị 3.11)
- PostgreSQL 14+ (bắt buộc cho proxy production — không dùng SQLite)
- Redis 6+ (khuyến nghị, không bắt buộc tuyệt đối nhưng thực tế là cần)
5.2 Cài đặt
# Cài thư viện cơ bản (chỉ SDK)
pip install litellm
# Cài thêm dependencies cho Proxy
pip install 'litellm[proxy]'
# Kiểm tra
litellm --version
Với Docker — cách khuyến nghị cho production:
docker pull ghcr.io/berriai/litellm:main-latest
# Hoặc dùng image stable
docker pull ghcr.io/berriai/litellm-database:main-latest
5.3 Biến môi trường cơ bản
# .env
# API keys của các provider thực
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GEMINI_API_KEY=AIza...
# Master key cho LiteLLM Proxy — chỉ dùng cho admin
# Format: phải bắt đầu bằng "sk-"
LITELLM_MASTER_KEY=sk-master-very-secret-string
# Salt key dùng để mã hóa các giá trị nhạy cảm trong DB
LITELLM_SALT_KEY=sk-salt-very-secret-string
# Database
DATABASE_URL=postgresql://user:password@host:5432/litellm
# Redis (tùy chọn nhưng khuyến nghị)
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your-password
Lưu ý quan trọng về key:
LITELLM_MASTER_KEYcó toàn quyền admin — chỉ dùng nó để tạo virtual key cho từng team/app, không bao giờ dùng trực tiếp trong ứng dụng. Đây là sai lầm phổ biến nhất theo bài viết "LiteLLM Virtual Keys Best Practices" trên Success Knocks.
6. Demo 1: Gọi Đa Provider Với Một Cú Pháp Duy Nhất
Đây là demo đơn giản nhất nhưng cho thấy ngay sức mạnh của LiteLLM — cùng một đoạn code, chỉ đổi tên model:
# demo_unified_api.py
import litellm
import os
from dotenv import load_dotenv
load_dotenv()
def ask(model: str, question: str) -> dict:
"""Gọi bất kỳ provider nào với cùng một interface."""
response = litellm.completion(
model=model,
messages=[
{"role": "system", "content": "Trả lời ngắn gọn trong 2 câu."},
{"role": "user", "content": question}
],
max_tokens=150,
temperature=0.3,
)
return {
"answer": response.choices[0].message.content,
"model": response.model,
"tokens": response.usage.total_tokens,
"cost": litellm.completion_cost(completion_response=response),
}
def main():
question = "Load balancing là gì, giải thích trong 2 câu?"
providers = [
"openai/gpt-4o",
"anthropic/claude-sonnet-4-20250514",
"gemini/gemini-2.0-flash",
]
print(f" {question}\n" + "="*70)
for model in providers:
try:
result = ask(model, question)
print(f"\n {result['model']}")
print(f" {result['answer']}")
print(f" ${result['cost']:.6f} | {result['tokens']} tokens")
except Exception as e:
print(f"\n {model}: {e}")
print("\n" + "="*70)
if __name__ == "__main__":
main()
Output mẫu:
Load balancing là gì, giải thích trong 2 câu?
======================================================================
gpt-4o-2024-11-20
Load balancing là kỹ thuật phân phối các yêu cầu mạng đến nhiều
máy chủ nhằm tối ưu hóa hiệu suất và đảm bảo tính sẵn sàng.
$0.000245 | 87 tokens
claude-sonnet-4-20250514
Load balancing là việc phân phối lưu lượng truy cập đều giữa
nhiều server backend để tránh quá tải và tăng độ tin cậy.
$0.000312 | 92 tokens
gemini-2.0-flash
Load balancing phân tán traffic đến nhiều servers giúp hệ thống
xử lý nhiều requests và tránh single point of failure.
$0.000089 | 78 tokens
======================================================================
Cùng một hàm ask(), ba provider khác nhau, không cần if-else xử lý từng SDK riêng. Đây mới chỉ là bước "abstraction" sức mạnh thực sự đến khi ta đưa LiteLLM lên chế độ Proxy.
7. Demo 2: Khởi Động LiteLLM Proxy Server
7.1 Tạo file cấu hình tối thiểu
# litellm_config.yaml
model_list:
- model_name: gpt-4o
litellm_params:
model: openai/gpt-4o
api_key: os.environ/OPENAI_API_KEY
- model_name: claude-sonnet
litellm_params:
model: anthropic/claude-sonnet-4-20250514
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: gemini-flash
litellm_params:
model: gemini/gemini-2.0-flash
api_key: os.environ/GEMINI_API_KEY
# Load-balanced group: 3 entries cùng tên "smart-model"
# → LiteLLM tự phân phối traffic giữa chúng
- model_name: smart-model
litellm_params:
model: openai/gpt-4o
api_key: os.environ/OPENAI_API_KEY
- model_name: smart-model
litellm_params:
model: anthropic/claude-sonnet-4-20250514
api_key: os.environ/ANTHROPIC_API_KEY
# Fallback đơn giản
litellm_settings:
fallbacks:
- gpt-4o: ["claude-sonnet", "gemini-flash"]
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY
7.2 Khởi động proxy
litellm --config litellm_config.yaml --port 4000
# Sẽ thấy log:
# INFO: Started server process [12345]
# INFO: Uvicorn running on http://0.0.0.0:4000
# INFO: LiteLLM Proxy: Loaded 5 models
Kiểm tra server đã sẵn sàng:
# Health check
curl http://localhost:4000/health/readiness
# {"status": "ok", "db": "connected", "cache": "redis"}
# Xem các model đang active
curl http://localhost:4000/models \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
7.3 Gọi proxy từ client
Không cần thay đổi code OpenAI đang có — chỉ đổi base_url:
# client.py
from openai import OpenAI
client = OpenAI(
api_key=os.environ["LITELLM_MASTER_KEY"], # Tạm dùng master cho demo
base_url="http://localhost:4000/v1", # Trỏ về LiteLLM
)
# Mọi thứ còn lại giống hệt OpenAI gốc
response = client.chat.completions.create(
model="smart-model", # Load-balanced group đã định nghĩa
messages=[
{"role": "user", "content": "Microservices là gì?"}
],
)
print(response.choices[0].message.content)
print(f"Provider thực tế đã xử lý: {response.model}")
Bạn có thể chạy lại lệnh 5 lần và sẽ thấy response.model thay đổi giữa gpt-4o-2024-11-20 và claude-sonnet-4-20250514 đó chính là load balancing đang hoạt động.
8. Demo 3: Virtual Keys và Quản Lý Chi Phí Cơ Bản
Trong production, không bao giờ chia sẻ master key cho ứng dụng. Thay vào đó, tạo virtual key riêng cho từng team/app với budget và quyền hạn cụ thể.
8.1 Tạo virtual key cho team
curl -X POST http://localhost:4000/key/generate \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"key_alias": "team-marketing-prod",
"max_budget": 100,
"budget_duration": "30d",
"tpm_limit": 200000,
"rpm_limit": 100,
"models": ["gpt-4o", "gemini-flash"],
"metadata": {
"team": "Marketing",
"owner": "tran.thi.b@company.com",
"env": "production"
}
}'
Phản hồi:
{
"key": "sk-ls-mkt-AbCdEf123XyZ...",
"key_name": "sk-ls-...XyZ",
"expires": null,
"max_budget": 100,
"budget_duration": "30d",
"budget_reset_at": "2026-06-30T00:00:00Z",
"tpm_limit": 200000,
"rpm_limit": 100,
"models": ["gpt-4o", "gemini-flash"]
}
Lúc này team Marketing có một "thẻ tín dụng AI" riêng của họ:
- Budget cứng $100/tháng — vượt sẽ bị chặn
- Chỉ được gọi
gpt-4ovàgemini-flash - Tối đa 100 requests/phút và 200K tokens/phút
- Tự động reset budget sau 30 ngày
8.2 Team dùng key của họ
client = OpenAI(
api_key="sk-ls-mkt-AbCdEf123XyZ...", # Key riêng của team
base_url="http://litellm-proxy:4000/v1"
)
# Nếu thử gọi model không nằm trong whitelist
response = client.chat.completions.create(
model="claude-sonnet", # Không có trong whitelist của key
messages=[...]
)
# → Lỗi: "Model 'claude-sonnet' not allowed for this key"
8.3 Theo dõi chi phí
# Xem thông tin và spend hiện tại của key
curl http://localhost:4000/key/info?key=sk-ls-mkt-AbCdEf123XyZ... \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
{
"key_name": "sk-ls-...XyZ",
"spend": 23.45,
"max_budget": 100,
"budget_reset_at": "2026-06-30T00:00:00Z",
"models": ["gpt-4o", "gemini-flash"],
"metadata": {"team": "Marketing", "env": "production"}
}
Tài Liệu Tham Khảo — Phần 1
- LiteLLM Documentation — Getting Started
- LiteLLM GitHub Repository (MIT License)
- LiteLLM Supported Providers — danh sách 100+ providers
- LiteLLM Virtual Keys
- A gentle introduction to LiteLLM — MITB For All / Medium
- LiteLLM Virtual Keys Best Practices — Success Knocks
- Deploying LiteLLM proxy with per-team budgets — Stack Harbor
- LiteLLM Fallback Configuration — Markaicode
- Build Production AI Agents With LiteLLM — Owain Lewis Newsletter
→ Tiếp tục với Phần 2: Triển Khai Nâng Cao
All rights reserved