LiteLLM proxy trên VPS: caching + budget control cho team AI

Chia sẻ bài viết

Mục lục
TL;DR
  • LiteLLM là proxy gateway hợp nhất 100+ LLM (OpenAI, Anthropic, Gemini, Bedrock, local Ollama) qua chuẩn OpenAI API.
  • Self-host trên 1 VPS, cấp virtual key cho từng nhân viên, đặt budget tháng, theo dõi cost theo team.
  • Bật cache Redis tiết kiệm 20-60% token cho prompt lặp, đặc biệt khi RAG hỏi câu giống nhau.
  • Audit log đầy đủ: prompt, response, latency, cost - debug và compliance dễ hơn nhiều so với gọi trực tiếp.
  • Tích hợp dễ với LangChain, LlamaIndex, Continue, Cursor, Open WebUI nhờ tương thích OpenAI SDK.

Team AI 10 người đang xài 5 provider: OpenAI cho ChatGPT API, Anthropic cho Claude code, Google cho Gemini Pro multimodal, Together.ai cho Llama 3, Ollama local cho task private. Mỗi provider có 1 SDK riêng, 1 billing dashboard riêng, 1 cách quản lý API key riêng. Cuối tháng kế toán hỏi "team mình tiêu hết bao nhiêu cho AI?", trưởng nhóm phải mở 5 tab, cộng tay vào Google Sheet. Một developer làm lộ API key OpenAI trên Github, mất 800 USD chỉ trong 12 tiếng vì bị scan rồi quay miner.

Giải pháp: thay vì để developer giữ raw API key của từng nhà cung cấp, đặt 1 gateway nội bộ làm chốt chặn. Mọi request gọi LLM đều đi qua đó. Gateway giữ key thật, dev chỉ nhận virtual key. Gateway log mọi prompt, đếm token, áp budget, kèm cache. Đó chính là LiteLLM. Bài này hướng dẫn deploy LiteLLM proxy production trên 1 VPS, từ docker compose đến virtual key, cache, budget, alert.

Vì sao cần proxy gateway LLM thay vì gọi trực tiếp?

Gọi trực tiếp OpenAI/Anthropic là OK với 1 lập trình viên. Nhưng khi team 5+ người, các vấn đề nảy sinh:

  • Key sprawl: mỗi dev xin 1 key, không ai biết key nào của ai, leak Github thì khó truy.
  • Cost không nhìn thấy: dashboard provider chỉ show tổng, không biết dev nào ăn nhiều.
  • Vendor lock-in: code import openai client, đổi sang Anthropic là phải sửa 100 file.
  • Lặp prompt phí token: RAG nhiều khi hỏi cùng câu, không cache thì trả tiền lần nào cũng như lần đầu.
  • Fallback yếu: OpenAI down, app im. Không tự switch sang Anthropic được vì SDK khác.
  • Audit khó: không biết user nào hỏi gì lúc nào, có vi phạm policy không.

LiteLLM giải quyết cả 6 vấn đề trên trong 1 binary. Triết lý: 1 endpoint thống nhất theo chuẩn OpenAI, đứng giữa mọi client và mọi provider. Mọi tính năng enterprise (key, budget, cache, log, fallback) là middleware ghép vào.

Yêu cầu VPS và stack

LiteLLM proxy nhẹ, chủ yếu IO-bound, không train model. Yêu cầu thực tế:

Quy mô teamRAMvCPUSSDBandwidth
1-5 dev2 GB2 vCPU20 GB100 Mbps đủ
5-30 dev / 1 chatbot4 GB2-4 vCPU40 GB200 Mbps
30+ dev / production app8 GB4 vCPU80 GB500 Mbps
+ Embedding heavy16 GB6 vCPU160 GB1 Gbps

Stack đề xuất: AlmaLinux 9 hoặc Ubuntu 24, Docker + Compose, Postgres lưu key + log + spend, Redis cache. Đặt sau Caddy/Nginx có TLS Let's Encrypt. Domain riêng llm.your-domain.com.

Docker Compose cho LiteLLM stack đầy đủ

services:
  litellm:
    image: ghcr.io/berriai/litellm:main-stable
    container_name: litellm
    restart: unless-stopped
    ports:
      - "127.0.0.1:4000:4000"
    volumes:
      - ./config.yaml:/app/config.yaml
    environment:
      LITELLM_MASTER_KEY: sk-master-PLEASE-GENERATE-LONG-RANDOM
      DATABASE_URL: postgresql://litellm:strong-pw@postgres:5432/litellm
      STORE_MODEL_IN_DB: "True"
      OPENAI_API_KEY: ${OPENAI_API_KEY}
      ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
      GEMINI_API_KEY: ${GEMINI_API_KEY}
      TOGETHER_API_KEY: ${TOGETHER_API_KEY}
    command: --config /app/config.yaml --port 4000 --num_workers 4
    depends_on: [postgres, redis]
    networks: [llm]

  postgres:
    image: postgres:16-alpine
    container_name: litellm-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: litellm
      POSTGRES_USER: litellm
      POSTGRES_PASSWORD: strong-pw
    volumes:
      - ./postgres:/var/lib/postgresql/data
    networks: [llm]

  redis:
    image: redis:7-alpine
    container_name: litellm-redis
    restart: unless-stopped
    command: redis-server --requirepass strong-redis-pw --maxmemory 512mb --maxmemory-policy allkeys-lru
    volumes:
      - ./redis:/data
    networks: [llm]

networks:
  llm:
    name: llm

File .env trong cùng thư mục chứa các API key thật. File này KHÔNG commit vào git, chỉ ở VPS:

OPENAI_API_KEY=sk-proj-...
ANTHROPIC_API_KEY=sk-ant-...
GEMINI_API_KEY=AIza...
TOGETHER_API_KEY=...

File config.yaml: khai báo model và routing

model_list:
  - model_name: gpt-4o
    litellm_params:
      model: openai/gpt-4o
      api_key: os.environ/OPENAI_API_KEY

  - model_name: claude-opus
    litellm_params:
      model: anthropic/claude-opus-4-5
      api_key: os.environ/ANTHROPIC_API_KEY

  - model_name: claude-sonnet
    litellm_params:
      model: anthropic/claude-sonnet-4-5
      api_key: os.environ/ANTHROPIC_API_KEY

  - model_name: gemini-pro
    litellm_params:
      model: gemini/gemini-2.5-pro
      api_key: os.environ/GEMINI_API_KEY

  - model_name: llama-70b
    litellm_params:
      model: together_ai/meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo
      api_key: os.environ/TOGETHER_API_KEY

  - model_name: smart
    litellm_params:
      model: openai/gpt-4o
      api_key: os.environ/OPENAI_API_KEY
    fallbacks:
      - claude-sonnet
      - gemini-pro

router_settings:
  routing_strategy: latency-based-routing
  redis_host: redis
  redis_port: 6379
  redis_password: strong-redis-pw
  fallbacks:
    - { gpt-4o: [claude-sonnet, gemini-pro] }

litellm_settings:
  drop_params: true
  set_verbose: false
  cache: true
  cache_params:
    type: redis
    host: redis
    port: 6379
    password: strong-redis-pw
    ttl: 3600

general_settings:
  master_key: os.environ/LITELLM_MASTER_KEY
  database_url: os.environ/DATABASE_URL
  enforce_user_param: true
  alerting: ["slack"]
  alerting_threshold: 30

Chạy docker compose up -d. Đợi 30 giây cho Postgres init, sau đó test thử bằng curl đến http://127.0.0.1:4000/v1/chat/completions với header Authorization là master key.

Đặt Caddy trước LiteLLM

Không expose port 4000 ra Internet. Đặt Caddy front-end, tự lấy cert Let's Encrypt. File /etc/caddy/Caddyfile:

llm.your-domain.com {
  reverse_proxy 127.0.0.1:4000 {
    flush_interval -1
    transport http {
      response_header_timeout 300s
    }
  }
  encode gzip
}

flush_interval -1 quan trọng để streaming response (SSE) không bị buffer, user thấy text chảy ra real-time. response_header_timeout 300s tránh ngắt request dài (LLM trả lời 1 bài luận có thể mất 60s+).

Tạo virtual key cho từng nhân viên

Master key chỉ admin biết. Mỗi nhân viên nhận 1 virtual key riêng, kèm budget, model whitelist, rate limit. Gọi API admin:

curl https://llm.your-domain.com/key/generate 
  -H "Authorization: Bearer sk-master-..." 
  -H "Content-Type: application/json" 
  -d '{
    "user_id": "[email protected]",
    "team_id": "team-backend",
    "models": ["gpt-4o", "claude-sonnet", "smart"],
    "max_budget": 50,
    "budget_duration": "30d",
    "rpm_limit": 60,
    "tpm_limit": 100000,
    "metadata": {"role": "backend-dev"}
  }'

Response trả về {"key": "sk-..."}. Bạn gửi key này cho nhân viên duy. Họ set vào biến môi trường OPENAI_API_KEYOPENAI_BASE_URL=https://llm.your-domain.com/v1. Code Python/JS không cần đổi gì, vẫn import openai client như cũ.

Đặt budget theo team và alert vượt mức

Tạo team trước, rồi cấp key thuộc team đó. Team có budget tổng:

curl https://llm.your-domain.com/team/new 
  -H "Authorization: Bearer sk-master-..." 
  -H "Content-Type: application/json" 
  -d '{
    "team_id": "team-backend",
    "team_alias": "Backend Team",
    "max_budget": 500,
    "budget_duration": "30d",
    "rpm_limit": 600,
    "tpm_limit": 1000000
  }'

Khi team chi 30% (mặc định alerting_threshold), Slack/Telegram nhận thông báo. Khi vượt 100%, key bị reject với 429. Admin có thể nâng budget ngay từ UI /ui mà không cần restart container.

Cache: tiết kiệm 20-60% token

Cache Redis hash theo (model + messages + temperature + max_tokens). Request có nội dung giống y hệt trả từ cache, không tốn token, latency dưới 10ms. Áp dụng cực tốt với:

  • Chatbot RAG: nhiều user hỏi câu giống nhau, cache giúp giảm cost mạnh.
  • Embedding: cùng đoạn text cho ra cùng vector, cache 24h là tiết kiệm rõ rệt.
  • Few-shot prompt template với input cố định: cache hit rate có thể đạt 70%.
  • Tool detection bằng LLM: prompt phân loại intent ít biến đổi, cache hit cao.

Bật/tắt cache per request bằng header x-litellm-cache: false, hữu ích khi cần response mới. Tracking cache hit rate qua endpoint /cache/ping và bảng LiteLLM_SpendLogs trong Postgres.

Fallback và load balancing

OpenAI sập 30 phút? LiteLLM tự fallback sang Claude/Gemini theo thứ tự khai báo. Code app không biết gì, vẫn nhận response bình thường, chỉ chậm hơn 1-2 giây.

Có nhiều key OpenAI từ nhiều account để bypass rate limit? Khai báo nhiều model cùng model_name: gpt-4o với key khác nhau, set router_strategy là simple-shuffle, least-busy, hoặc latency-based-routing. LiteLLM phân tải đều, nếu 1 key bị 429 thì auto switch sang key còn lại.

Tích hợp với LangChain, Continue, Cursor

ClientCấu hình
LangChain (Python)ChatOpenAI(base_url="https://llm.your-domain.com/v1", api_key="sk-virtual-key")
OpenAI SDKOpenAI(base_url=..., api_key=...)
Cursor IDESettings -> Models -> OpenAI -> Override base URL
Continue.devconfig.json: provider openai, apiBase, apiKey, model
Open WebUIAdmin Settings -> Connections -> OpenAI API URL
LlamaIndexOpenAI(api_base=..., api_key=...) hoặc LiteLLM client

Lợi ích: dev đổi từ GPT sang Claude chỉ bằng cách đổi model string, không cần đụng đến code SDK. PM cũng có thể dùng Open WebUI gọi tới gateway, mọi traffic đều log và áp budget chung.

Monitoring và audit log

LiteLLM ghi mỗi request vào bảng LiteLLM_SpendLogs với 20+ trường: timestamp, user, team, model, prompt_tokens, completion_tokens, cost USD, latency ms, status. Query Postgres trực tiếp để báo cáo:

-- Top 5 user tốn nhất tháng này
SELECT "user", SUM(spend) AS total_usd
FROM "LiteLLM_SpendLogs"
WHERE "startTime" >= date_trunc('month', now())
GROUP BY "user"
ORDER BY total_usd DESC
LIMIT 5;

-- Tổng cost theo model
SELECT model, SUM(spend) AS total
FROM "LiteLLM_SpendLogs"
WHERE "startTime" >= now() - interval '7 days'
GROUP BY model
ORDER BY total DESC;

Có thể ship log sang Langfuse, Helicone, Phoenix để có UI đẹp hơn, trace từng span. Tích hợp 1 dòng config: callbacks: ["langfuse"] + env LANGFUSE_PUBLIC_KEY/SECRET.

Bảo mật và compliance

  • Master key chỉ admin biết, lưu trong password manager (Bitwarden, 1Password), không paste vào Slack.
  • Bật enforce_user_param để mọi request bắt buộc gắn user_id, tránh anonymity.
  • Set guardrails trong LiteLLM để chặn PII (CMND, email, phone) bị gửi đi OpenAI.
  • Backup Postgres hằng đêm, đặc biệt bảng key và spend logs.
  • Rotate key hằng quý cho production app, dev key thì set expire 90d auto.
  • Bật rate limit toàn cục để chống misuse: 1000 RPM trên toàn proxy.

Bẫy thường gặp khi deploy

Triệu chứngNguyên nhânCách fix
Streaming chunk tới chậmCaddy/Nginx buffer SSEflush_interval -1 (Caddy) / proxy_buffering off (Nginx)
Cost không cộng đúngThiếu user param hoặc team_id saiBật enforce_user_param, sửa client gửi user
Cache không hitTemperature hoặc seed khác nhauSet fixed temperature 0 và seed cố định
Postgres connection refusedContainer postgres chưa sẵn sàngTăng restart_policy, healthcheck postgres trước
UI /ui không loadThiếu UI_USERNAME/UI_PASSWORDSet env UI_USERNAME=admin UI_PASSWORD=strong
Cloud VPS cho vibe coder

VPS chạy LiteLLM gateway cho team AI nội bộ

Cloud VPS TND sẵn AlmaLinux 9, Ubuntu 22/24, Debian 12/13. SSD CEPH, snapshot 1-click, backup hằng ngày, network 200Mbps trong nước. Gói 4GB RAM thoải mái chạy LiteLLM + Postgres + Redis cho team 30 dev gọi LLM song song.

Xem 8 cấu hình Cloud VPS →

FAQ

LiteLLM có miễn phí không?

Có phiên bản open source miễn phí (MIT-like license), đầy đủ tính năng cho team nhỏ-trung. Phiên bản Enterprise có thêm SSO, audit nâng cao, SLA, dành cho công ty lớn. Self-host bản OSS đủ cho 95% case startup.

So với OpenRouter thì khác gì?

OpenRouter là SaaS, tính phí mark-up khoảng 5% trên giá gốc, không kiểm soát được data flow. LiteLLM self-host: bạn giữ key thật, data không qua bên thứ 3, không mark-up, đổi lại bạn phải bỏ công maintain VPS. Với team có ngân sách AI hơn 500 USD/tháng, self-host LiteLLM tiết kiệm thấy rõ.

Có hỗ trợ embedding và image generation không?

Có. LiteLLM hỗ trợ endpoint /embeddings (text-embedding-3-small, voyage, Cohere), /audio/transcriptions (Whisper, Deepgram), /images/generations (DALL-E, Stable Diffusion qua Replicate). Đều theo schema OpenAI. Cache embedding rất hiệu quả vì input cố định.

Có thể proxy LLM local như Ollama qua LiteLLM không?

Có. Khai báo model với prefix ollama_chat/llama3.2 và base URL trỏ đến Ollama instance. Mọi client gọi qua LiteLLM gateway sẽ thấy llama-local như một model OpenAI bình thường. Hữu ích khi muốn route prompt nhạy cảm sang LLM local, prompt thường sang cloud.

Khi LiteLLM proxy chết, app có chết theo không?

Có, đó là rủi ro của single gateway. Mitigation: chạy 2 instance LiteLLM sau load balancer (Nginx, HAProxy, Caddy upstream block), hoặc dùng systemd auto-restart, hoặc dùng VPS có snapshot + auto-heal. Cho production critical, đặt healthcheck + monitor uptime + Slack alert là đủ tránh downtime kéo dài.