jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

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:

  1. Output tokens: 3-5x input. Verbose response = đốt tiền.
  2. Repeated context: paste cùng system prompt + docs mỗi request.
  3. 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

ProviderCached input cost
Anthropic10% giá thường (90% off)
OpenAI50% giá thường
Google Gemini25% 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:

ProviderBatch discount
OpenAI50% off
Anthropic50% off
Google50% 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

FormatQuality dropVRAM saving
fp16 → int8<1%50%
fp16 → int42-5%75%
fp16 → int2/binary10-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:

  1. Prompt caching (Tier 1, dễ, 50-90% off cached)
  2. Model routing (Tier 2, vừa, 60-90% off premium)
  3. Semantic cache (Tier 2, ROI cao cho repetitive query)
  4. Output reduction (Tier 1, prompt-level)
  5. 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

Reference

  • Anthropic Prompt Caching docs
  • “Optimizing LLM Cost” — Helicone blog series
  • vLLM throughput benchmarks
  • “Knowledge Distillation” — Hinton et al. 2015