LLM Cost Optimization — 10 patterns giảm hóa đơn 50-95% không mất quality
Pattern thực chiến giảm chi phí LLM ở scale: prompt caching, semantic cache, model routing, distillation, batch API, quantization, streaming + early stop, và framework đo ROI khi self-host.
LLM rẻ ở prototype, đắt ở production. Startup dùng GPT-4 thoải mái khi MAU = 100. Lên 100K MAU, hóa đơn $50K/tháng và founder bắt đầu hoảng.
Bài này là practical playbook giảm cost 50-95% mà giữ quality. 10 pattern + cost calculation + decision framework. Áp dụng được ngay mai cho production app.
Reference: Tokens & Pricing nếu cần ôn lại fundamental về cost.
1. Vì sao cost matters — thực tế ở scale
1.1. Math đơn giản, kết quả gây sốc
Chatbot serve 100K user, mỗi user 5 query/ngày, mỗi query 2K input + 500 output token, dùng Claude 3.5 Sonnet:
Per query cost:
Input: 2K × $3/1M = $0.006
Output: 500 × $15/1M = $0.0075
Total: $0.0135 / query
Daily volume: 100K × 5 = 500K query
Daily cost: 500K × $0.0135 = $6,750
Monthly cost: $202,500
Yearly cost: $2.43M
$2.4M/năm cho 1 chatbot duy nhất. Đa số startup không sống nổi mức này.
1.2. Cost dọc theo growth curve
1K users → $24K/năm (acceptable)
10K users → $240K/năm (cần optimize)
100K users → $2.4M/năm (must optimize)
1M users → $24M/năm (need self-host hoặc partner deal)
Mỗi 10x user = 10x cost. Nếu pricing model không scale tương ứng → margin chết.
1.3. Đâu là pain point?
3 nguồn cost:
- Output tokens: 3-5x input. Verbose response = đốt tiền.
- Repeated context: paste cùng system prompt + docs mỗi request.
- Premium model cho mọi query: dùng Claude Opus cho “fix typo”.
10 pattern dưới đây address từng nguồn này.
2. Pattern 1: Prompt Caching
Saving: 50-90% cost cho cached portion
API provider cache prefix prompt. Lần sau request với prefix identical → giá rẻ.
2.1. Discount
| Provider | Cached input cost |
|---|---|
| Anthropic | 10% giá thường (90% off) |
| OpenAI | 50% giá thường |
| Google Gemini | 25% giá thường (75% off) |
2.2. Cách structure prompt cache-friendly
[CACHEABLE PREFIX]
System prompt
Rules / convention
Tool definitions
Reference docs
Few-shot examples
[/CACHEABLE PREFIX]
[VARIABLE TAIL]
User query
Conversation history mới nhất
[/VARIABLE TAIL]
Phần CACHEABLE giữ identical → hit cache → giảm 50-90%. Phần TAIL thay đổi mỗi request → tính giá full.
2.3. Anthropic explicit caching
Anthropic yêu cầu mark cache breakpoint:
client.messages.create(
model="claude-3-5-sonnet-20241022",
system=[
{
"type": "text",
"text": "Long system prompt with rules and docs...",
"cache_control": {"type": "ephemeral"}
}
],
messages=[...]
)
Cache TTL: 5 phút (default). User chat liên tục → từ message 2 trở đi save 90%.
2.4. Real impact
Chatbot RAG với 5K token system prompt + retrieved docs:
Without caching:
5500 token input × $3/1M × 100K query/ngày = $1,650/ngày
With caching (Anthropic):
First request: 5500 × $3.75/1M = $0.020 (write cache, slight
premium)
Sub-requests: 5500 × $0.30/1M = $0.0017 (90% off)
Avg cost (giả sử cache hit 80%):
100K × ((0.20 × 0.020) + (0.80 × 0.0017)) = $536/ngày
Saving: $1,114/ngày = 67% giảm
2.5. Pitfalls
- Cache invalidate khi byte 1 trong prefix đổi → shuffle prompt order có thể break cache.
- TTL 5 phút → user lâu mới chat lại không hit cache.
- Cost write cache cao hơn fresh → cần >2 hit để break-even.
3. Pattern 2: Semantic Cache (LLM-level cache)
Saving: 30-70% cho query trùng lặp
Khác prompt cache (provider-side). Semantic cache là layer của bạn:
Query → check cache (vector similarity)
├── Hit (sim > 0.95): trả response cached
└── Miss: call LLM, store response
3.1. Implementation
from openai import OpenAI
import redis
client = OpenAI()
cache = redis.Redis() # hoặc vector DB
def embed(text):
return client.embeddings.create(
model="text-embedding-3-small",
input=text
).data[0].embedding
def cached_chat(query, threshold=0.95):
query_vec = embed(query)
# Search cache
candidates = vector_search(query_vec, k=1)
if candidates and candidates[0].score > threshold:
return candidates[0].response
# Cache miss
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": query}]
)
cache.add(query_vec, response.choices[0].message.content)
return response.choices[0].message.content
3.2. Khi nào hiệu quả
Use case có query repetitive:
- FAQ chatbot (90% query trùng lặp ý)
- Customer support (cùng câu hỏi nhiều user)
- Product Q&A
- Documentation search
Cost embedding rẻ ($0.02/1M tokens cho text-embedding-3-small) so với LLM call → ROI thường rất tốt.
3.3. Pitfalls
- Threshold quá cao (0.99) → ít hit, ROI thấp.
- Threshold quá thấp (0.85) → trả response sai cho query nuance khác.
- Stale data: query hôm nay = query tuần trước nhưng context đổi. → TTL 1-7 ngày.
- Personalization: user A hỏi “lương tôi” ≠ user B hỏi cùng câu. Cache phải scope per user.
3.4. Library
- GPTCache (Zilliz) — semantic cache Python
- Redis Vector — cache + vector trong 1 DB
- LangChain LLMCache — built-in semantic cache option
4. Pattern 3: Model Routing
Saving: 60-90% cost với quality giữ nguyên
Không phải task nào cũng cần model lớn. Route động theo task complexity:
Query → classifier (rules / LLM nhỏ)
├── Simple ("dịch sang Anh", "format JSON")
│ → GPT-4o-mini ($0.15/1M)
├── Medium ("explain function này")
│ → Claude Haiku ($0.8/1M)
└── Complex ("design architecture cho X")
→ Claude Sonnet ($3/1M)
4.1. Classifier strategies
Rule-based (đơn giản, free):
def route(query):
if len(query) < 50:
return "haiku"
if any(kw in query.lower() for kw in ["architect", "design", "review"]):
return "sonnet"
return "mini"
LLM-based (chính xác hơn, cost classifier nhỏ):
def route(query):
classifier_result = mini_llm.complete(
f"Classify difficulty: easy/medium/hard\nQuery: {query}\nClass:"
)
return {"easy": "mini", "medium": "haiku", "hard": "sonnet"}[classifier_result]
Classifier cost ~$0.0001/query → negligible. Saving 60-90% trên expensive query.
4.2. Library
- OpenRouter — auto routing với chiến lược định trước
- NotDiamond, Martian — startup chuyên router AI
- LangChain Router — built-in
4.3. A/B test bắt buộc
Routing có thể downgrade quality. Always A/B test:
- 10% traffic giữ premium model
- 90% traffic theo router
- Compare quality (user rating, conversion)
Nếu quality không drop > 2-3% → router safe.
5. Pattern 4: Output Token Reduction
Saving: 30-60% direct
Output đắt 3-5x input. Giảm output → giảm cost rõ rệt.
5.1. Explicit length constraint
❌ "Explain RAG"
→ response 2000 tokens, verbose
✅ "Explain RAG in 100 words. Bullet points only. No introduction."
→ response 200 tokens
10x reduction.
5.2. Force structured output
JSON / structured response tự nhiên ngắn hơn prose:
"List 5 framework. Format JSON: {name, useCase, popularity}.
No prose."
5.3. Stop sequences
Cắt response sớm:
client.chat.completions.create(
model="gpt-4o",
messages=[...],
stop=["</answer>", "---", "## Next"]
)
Model output tới stop sequence → dừng. Tiết kiệm token thừa.
5.4. Max tokens cap
Hard limit. Cẩn thận: cắt giữa câu nếu không đủ.
max_tokens=500 # response không vượt 500 tokens
5.5. Anti-pattern: force ngắn quá
Quá ngắn → response không đủ info → user hỏi lại → tổng cost cao hơn. Sweet spot 60-80% length default.
6. Pattern 5: Distillation
Saving: 90-99% inference cost (nếu volume lớn)
Train model nhỏ học từ model lớn. Dùng output GPT-4 → fine-tune GPT-4o-mini → kết quả 90-95% quality của GPT-4 với cost của mini.
6.1. Process
1. Collect 5K-50K examples
2. Run through GPT-4 (expensive teacher) → get high-quality output
3. Fine-tune GPT-4o-mini (cheap student) on (input, GPT-4 output) pairs
4. Deploy student model
6.2. Economics
Distillation cost (one-time):
- Teacher inference: 10K example × GPT-4 cost ≈ $300
- Fine-tune: $50-100
- Total: ~$400
Inference cost per query:
- GPT-4: $0.02
- Fine-tuned mini: $0.001
- Saving: 95%
Break-even: ~25K query
At 1M query/month: saves $19K/month
6.3. Khi nên distill
- Volume lớn (>100K query/tháng)
- Task narrow (1 domain, không cần general intelligence)
- Acceptable quality drop 2-5%
Đọc thêm: Fine-tuning Basics.
7. Pattern 6: Batch API
Saving: 50% direct
Nếu task không cần realtime (background job, analytics), dùng batch API:
| Provider | Batch discount |
|---|---|
| OpenAI | 50% off |
| Anthropic | 50% off |
| 50% off |
7.1. Use cases
- Daily report generation
- Backfill embeddings
- Content moderation overnight
- Data labeling pipeline
- Periodic content generation
7.2. Trade-off
- Latency: 1-24 giờ thay vì giây
- Không stream
- Phải buffer requests thành batch
OpenAI batch:
batch = client.batches.create(
input_file_id="file-abc",
endpoint="/v1/chat/completions",
completion_window="24h"
)
# 24h sau
output = client.batches.retrieve(batch.id).output_file_id
8. Pattern 7: Streaming + Early Stop
Saving: variable, 10-30%
User nhấn “stop” giữa response → server abort → không tốn output token còn lại.
8.1. Implementation
stream = client.chat.completions.create(
model="gpt-4o",
messages=[...],
stream=True
)
for chunk in stream:
yield chunk.choices[0].delta.content
if user_stopped():
break # streamhoặc abort connection
8.2. UX combo
UI có nút “Stop generation” rõ ràng. User thấy AI lạc → stop ngay, re-prompt với clarify thay vì đợi xong response 2000 token rồi không dùng.
9. Pattern 8: Smart Context Management
Saving: 30-70% input cost
Context dài = đốt tiền. Nhưng đa số chat dùng context không hiệu quả.
9.1. Trim history
Conversation 20 turn → context 50K. Thực tế model chỉ cần 3-5 turn gần nhất + summary phần cũ.
def trim(history, max_messages=10):
if len(history) <= max_messages:
return history
# Tóm tắt phần cũ
old = history[:-max_messages]
summary = llm_summarize(old)
return [
{"role": "system", "content": f"Earlier conversation: {summary}"},
*history[-max_messages:]
]
9.2. Lazy context loading
Đừng paste cả @src/ vào context “phòng hờ”. Chỉ load file thực sự
cần. Cursor làm điều này tự động — bạn add @file thay vì @dir.
9.3. Conversation forking
User đổi chủ đề → start new chat thay vì tiếp tục. Context cũ vô nghĩa cho task mới, đốt tiền không lý do.
9.4. Sliding window cho long doc
Tài liệu 100K token, query 1 fact cụ thể. Đừng paste cả 100K. Chunk
- embed + retrieve top-3 → 3K context. Đó là RAG.
Đọc thêm: RAG Guide.
10. Pattern 9: Quantization (cho self-host)
Saving: 50-75% memory + 30-50% latency
Nếu self-host model, quantize giúp scale đáng kể.
10.1. Cách hoạt động
Model gốc fp16 (16-bit float per weight). Quantize → 8-bit, 4-bit hoặc thấp hơn:
Llama 3.3 70B fp16: 140 GB VRAM
Llama 3.3 70B int8: 70 GB VRAM
Llama 3.3 70B int4: 35 GB VRAM
10.2. Quality trade-off
| Format | Quality drop | VRAM saving |
|---|---|---|
| fp16 → int8 | <1% | 50% |
| fp16 → int4 | 2-5% | 75% |
| fp16 → int2/binary | 10-30% | 87.5% |
Sweet spot: int4 (Q4_K_M format) cho production.
10.3. Format phổ biến
- GGUF: llama.cpp, Ollama, LM Studio
- GPTQ: cũ, vẫn phổ biến
- AWQ: tốt cho inference batch
- bitsandbytes: Hugging Face transformers
Đọc thêm: Open Source LLM Ecosystem.
11. Pattern 10: Self-host Break-even
Saving: 70-95% ở scale
Khi nào nên switch từ API sang self-host?
11.1. Cost calculation
API (Claude Sonnet):
$3/1M input + $15/1M output
Avg query 2K input + 500 output = $0.0135/query
Self-host (Llama 3.3 70B trên 2× H100):
Hardware: $4/h × 24 × 30 = $2,880/month (rented)
Throughput: ~50 query/s × 60 × 60 × 24 × 30 = 130M query/month max
Effective cost: $2,880 / 130M = $0.000022/query
→ 600x rẻ hơn API ở 100% utilization
→ 60x rẻ hơn ở 10% utilization
11.2. Break-even point
API cost = Self-host fixed cost
$0.0135 × N = $2,880
N ≈ 213K query/month
Vượt 200K query/tháng → self-host break-even. Vượt 1M → no-brainer.
11.3. Hidden cost của self-host
- DevOps: monitor, scale, deploy ($5K-20K/tháng staff)
- Reliability: API có 99.9% SLA, self-host bạn phải build
- Model quality: Llama 70B < Claude Sonnet ở nhiều task
- Update: provider auto upgrade, self-host phải re-evaluate model
→ Break-even thực tế cao hơn 200K vì hidden cost. Thường 1M+ query/tháng mới đáng.
12. ROI Framework — chọn pattern nào trước
Stack pattern theo độ dễ:
TIER 1 — Easy wins (làm tuần này)
├── Prompt caching (free saving 50-90%)
├── Output token reduction (prompt change)
├── Structured output (prompt change)
└── Streaming + early stop (UI change)
TIER 2 — Medium effort (tháng này)
├── Model routing (1-2 sprint)
├── Semantic cache (1-2 sprint)
└── Context trim / RAG (2-4 sprint)
TIER 3 — High effort (quarter này)
├── Distillation (cần ML team)
├── Self-host (cần DevOps + ML team)
└── Custom batch pipeline (1-2 month)
Đa số team nên start với Tier 1, đo saving, rồi tiến dần. Đừng nhảy thẳng self-host khi prompt caching chưa enable.
13. Monitoring & Budgeting
13.1. Metrics quan trọng
ECONOMICS
- Cost per request (P50, P95, P99)
- Cost per user (DAU/MAU)
- Cost per feature (Chat vs Search vs Summary)
USAGE
- Tokens in / out per request
- Cache hit rate
- Model distribution (% query mỗi model)
QUALITY
- User rating
- Response time
- Error rate
13.2. Tools
- Helicone — proxy, log mọi LLM call, dashboard
- Langfuse — open source observability
- OpenAI Platform Dashboard — built-in
- Custom: write to BigQuery / DataDog
13.3. Budget alerts
Daily spend > $X → Slack alert
Cost per user > $Y → flag suspicious
Cache hit < threshold → engineer review
Không có monitoring = không biết đang đốt tiền chỗ nào.
14. Tổng kết
LLM cost không phải fixed. Optimize 50-95% là achievable cho hầu hết production app.
5 pattern impactful nhất:
- Prompt caching (Tier 1, dễ, 50-90% off cached)
- Model routing (Tier 2, vừa, 60-90% off premium)
- Semantic cache (Tier 2, ROI cao cho repetitive query)
- Output reduction (Tier 1, prompt-level)
- RAG thay long context (Tier 2, scale)
Self-host (Tier 3) chỉ make sense ở scale rất lớn (1M+ query/tháng) và có DevOps capacity.
Cuối cùng: monitor first, optimize second. Không có data = đoán mò = optimize sai chỗ.
Đọc thêm
- Tokens & Pricing — fundamental
- LLM Models Comparison — chọn model đúng
- Fine-tuning Basics — distillation
- RAG Guide — context management
- Open Source LLM Ecosystem — self-host
Reference
- Anthropic Prompt Caching docs
- “Optimizing LLM Cost” — Helicone blog series
- vLLM throughput benchmarks
- “Knowledge Distillation” — Hinton et al. 2015