Mọi chiến lược tối ưu token bạn xây dựng trong 9 module trước đều dựa trên một tập giả định: context window (giới hạn số token mà model có thể xử lý trong một lần gọi) hiện tại, bảng giá hiện tại, và năng lực model hiện tại. Vấn đề là cả ba giả định này đều đang thay đổi với tốc độ chưa từng có trong lịch sử ngành phần mềm. Một kỹ thuật RAG (Retrieval-Augmented Generation — kỹ thuật truy xuất tài liệu liên quan rồi đưa vào prompt trước khi sinh câu trả lời) bạn thiết kế kỹ lưỡng cho context window 8K token cách đây hai năm có thể trở nên lãng phí — hoặc tệ hơn, phản tác dụng — khi model mới có context window 1 triệu token và cache hit rate (tỷ lệ phần trăm token được tính giá rẻ hơn nhờ đã có trong cache) cao.
Bài này không dạy bạn một kỹ thuật tối ưu cụ thể. Nó dạy bạn cách xây dựng một hệ thống để phát hiện khi nào các kỹ thuật cũ hết hiệu quả, khi nào cơ hội tối ưu mới xuất hiện, và làm sao để kiến trúc của bạn tự thích ứng mà không cần viết lại toàn bộ pipeline mỗi lần có model mới ra mắt.
Understanding the Forces Driving Change
Trước khi xây bất kỳ hệ thống giám sát nào, cần hiểu rõ bản chất của ba lực đang tái định hình toàn bộ bài toán tối ưu token. Đây không phải là những thay đổi ngẫu nhiên — chúng có quy luật, có thể dự đoán được xu hướng (dù không dự đoán được thời điểm chính xác), và mỗi lực đòi hỏi một phản ứng kiến trúc khác nhau.
Force 1: Context Window Expansion
Context window đã tăng theo cấp số nhân trong vài năm qua: từ 4K–8K token (GPT-3.5 thời kỳ đầu) lên 128K (GPT-4 Turbo), rồi 200K (Claude 3), và hiện tại nhiều model production đã hỗ trợ 1 triệu token hoặc hơn. Đây không phải là một cải tiến tuyến tính — nó thay đổi hoàn toàn phép tính chi phí-lợi ích của nhiều kỹ thuật.
Hệ quả trực tiếp: những kỹ thuật được sinh ra để "lách" giới hạn context nhỏ — chunking tài liệu thành đoạn 500 token, xây dựng vector database để retrieval từng phần, tóm tắt lịch sử hội thoại liên tục — đôi khi không còn là lựa chọn tối ưu về chi phí. Với prompt caching (kỹ thuật cache phần prompt tĩnh để tính giá rẻ hơn ở các lượt gọi sau) áp dụng cho context dài, việc nhúng nguyên toàn bộ một bộ tài liệu 300K token vào system prompt và để nó được cache lại có thể rẻ hơn NHIỀU so với việc chạy một pipeline retrieval riêng biệt — vì bạn tiết kiệm được: (1) chi phí vận hành vector database, (2) latency của bước retrieval, (3) rủi ro retrieval sai đoạn dẫn đến câu trả lời sai mà phải retry.
Nhưng điều quan trọng là: context window lớn hơn không có nghĩa "cứ nhúng hết vào là xong". Chi phí input token vẫn tính theo số token gửi đi (trừ phần được cache), và với các workload có tỷ lệ cache-hit thấp (ví dụ mỗi request có nội dung động khác nhau), nhúng toàn bộ 500K token vẫn đắt hơn nhiều so với retrieval một đoạn 2K token liên quan. Force 1 không "giết chết" RAG — nó thay đổi các điều kiện biên (boundary conditions) mà tại đó RAG còn hợp lý.
Force 2: Pricing Model Evolution
Giá token đã và đang giảm liên tục — nhưng không đều, và không đơn giản. Một số xu hướng cụ thể đáng theo dõi:
- Giá giảm theo thời gian cho cùng một tier năng lực: model "mini"/"flash" đời sau thường rẻ hơn 30–70% so với model tương đương đời trước, đồng thời có năng lực bằng hoặc hơn.
- Pricing tier (bậc giá) phân theo độ dài context: nhiều nhà cung cấp áp giá cao hơn cho các request vượt một ngưỡng context nhất định (ví dụ trên 128K hoặc 200K token), nghĩa là chi phí không tuyến tính theo số token khi bạn vượt ngưỡng.
- Prompt caching giảm giá input đã cache tới 90%: đây là thay đổi lớn nhất về pricing trong 2 năm qua. Nó biến "context tĩnh lặp lại" (system prompt, tài liệu tham chiếu, few-shot example) từ một khoản chi phí lặp lại mỗi request thành một khoản chi phí gần như một lần.
- Batch API và off-peak pricing: xử lý theo lô (không cần phản hồi tức thời) thường được giảm giá 50% trở lên — mở ra cơ hội tối ưu cho các workload không real-time (báo cáo định kỳ, phân loại hàng loạt, tạo dữ liệu huấn luyện).
Hệ quả với đội ngũ kỹ thuật: một bài toán mà cách đây 6 tháng bạn quyết định "quá đắt để tự động hóa bằng LLM" có thể hôm nay đã rẻ hơn 5–10 lần với đúng model, đúng cấu hình cache. Ngược lại, nếu bạn không theo dõi, bạn có thể đang trả giá gấp 3–5 lần mức cần thiết cho một workload chỉ vì chưa chuyển sang model/tier mới.
Force 3: Model Capability Improvements
Lực thứ ba tinh vi hơn hai lực trên: các model ngày càng "hiệu quả về token" hơn ở cùng một mức chi phí — chúng cần ít few-shot example hơn để đạt độ chính xác tương đương, cần ít bước reasoning trung gian (chain-of-thought) hơn cho các bài toán đơn giản, và tuân theo instruction ngắn gọn tốt hơn (giảm nhu cầu viết prompt dài dòng, lặp lại nhiều lần để "nhắc" model).
Điều này có nghĩa là các kỹ thuật prompt engineering (kỹ thuật thiết kế prompt) từng cần thiết để "ép" model đời cũ trả lời đúng — ví dụ chuỗi 5 few-shot example dài, hướng dẫn từng bước chi tiết cho một tác vụ phân loại đơn giản — có thể trở thành dư thừa với model mới, chỉ làm tăng chi phí input token mà không tăng chất lượng output. Ngược lại, một số kỹ thuật rút gọn (structured output, function calling chặt) trở nên hiệu quả hơn khi model được huấn luyện tốt hơn cho các định dạng đó.
Mẹo: Đừng theo dõi ba lực này một cách cảm tính qua tin tức hay Twitter/X. Hãy đặt lịch review hàng tháng (không cần hàng ngày) với một checklist cụ thể: (1) có model mới nào ra mắt trong tier giá bạn đang dùng?, (2) giá của model bạn đang dùng có thay đổi?, (3) context window tối đa của nhà cung cấp chính có tăng? Ghi log các mốc thay đổi này vào một file CHANGELOG-models.md trong repo — nó vừa là tài liệu tra cứu, vừa giúp bạn nhìn lại được tốc độ thay đổi thực tế để lập kế hoạch ngân sách.
Building a Model Evaluation Pipeline
Phản ứng cảm tính trước mỗi lần model mới ra mắt ("nghe nói model X rẻ hơn, đổi thử xem") là cách nhanh nhất để phá vỡ chất lượng hệ thống production. Bạn cần một pipeline có kỷ luật: phân loại workload, đánh giá model mới một cách hệ thống, và chỉ chuyển đổi khi có dữ liệu định lượng chứng minh lợi ích.
The Model Evaluation Framework
Framework gồm 4 bước lặp lại mỗi khi có model mới hoặc giá thay đổi:
- Phân loại workload theo yêu cầu năng lực (reasoning phức tạp, structured output, đa ngôn ngữ, độ nhạy về latency) và mức chi phí hiện tại.
- Chạy benchmark nội bộ — không dựa vào benchmark công khai của nhà cung cấp, vì benchmark của bạn phải phản ánh đúng distribution dữ liệu thực tế của bạn.
- Tính chi phí dự kiến với model mới dựa trên token usage thực đo được, bao gồm cache hit rate ước tính.
- Ra quyết định có ngưỡng rõ ràng (ví dụ: chỉ chuyển nếu tiết kiệm ≥ 30% VÀ độ chính xác không giảm quá 1%).
Dưới đây là một file cấu hình mẫu để phân loại workload — đây là "nguồn sự thật" (source of truth) mà pipeline benchmark sẽ đọc vào:
workloads:
- name: ticket_classifier
description: "Phân loại ticket hỗ trợ khách hàng vào 12 category"
current_model: gpt-4o-mini
monthly_volume_requests: 420000
avg_input_tokens: 380
avg_output_tokens: 15
requires:
- structured_output # JSON schema cố định
- low_latency # < 800ms p95
accuracy_baseline: 0.94 # đo trên golden set 500 ticket đã gán nhãn tay
golden_set_path: "eval/golden_sets/ticket_classifier_v3.jsonl"
monthly_cost_usd: 890
- name: commit_message_generator
description: "Sinh commit message chuẩn Conventional Commits từ diff"
current_model: claude-sonnet-5
monthly_volume_requests: 38000
avg_input_tokens: 2400
avg_output_tokens: 60
requires:
- code_understanding
- structured_output
accuracy_baseline: 0.88 # đo bằng human review sample 200 commit/tháng
golden_set_path: "eval/golden_sets/commit_msg_v1.jsonl"
monthly_cost_usd: 580
evaluation_thresholds:
min_cost_savings_pct: 30 # chỉ đề xuất chuyển nếu tiết kiệm >= 30%
max_accuracy_regression_pct: 1 # không chấp nhận giảm độ chính xác > 1%
min_golden_set_size: 200 # golden set phải đủ lớn để có ý nghĩa thống kê
Khi một model mới ra mắt (hoặc giá đổi), script benchmark sẽ đọc file này, chạy lại toàn bộ golden set với model mới, và in ra báo cáo so sánh:
ticket_classifier: $890 → $89/month (90% savings) — HIGH PRIORITY
accuracy: 0.94 → 0.945 (within tolerance, slight improvement)
action: MIGRATE — update workload_classification.yaml, rerun canary 48h
commit_message_generator: $580 → $120/month (79% savings) — HIGH PRIORITY
accuracy: 0.88 → 0.86 (within 1% tolerance)
action: MIGRATE — schedule A/B test before full rollout
Báo cáo này chính là input cho quy trình ra quyết định — không phải cảm giác "nghe nói rẻ hơn", mà là số liệu tiết kiệm cụ thể theo từng workload, kèm điều kiện chất lượng (accuracy) không bị vi phạm.
Mẹo: Luôn giữ golden set (tập dữ liệu đã gán nhãn tay để đánh giá) độc lập với model — không bao giờ dùng chính output của model hiện tại để tạo golden set, vì bạn sẽ chỉ đo được "model mới có giống model cũ không" chứ không đo được "model mới có đúng không". Định kỳ 3–6 tháng, lấy mẫu ngẫu nhiên thêm 50–100 case mới từ production vào golden set để nó không bị lệch (drift) theo thời gian.
Adapting to Context Window Growth
Context window lớn hơn buộc bạn phải xét lại từng quyết định kiến trúc đã đưa ra khi context còn hạn chế. Đây là phần dễ bị bỏ qua nhất, vì kiến trúc RAG hay chunking một khi đã chạy ổn trong production thường không ai muốn động vào.
The Context Window Expansion Decision Matrix
Không phải cứ context window lớn hơn là nên "nhúng hết". Quyết định đúng phụ thuộc vào 3 biến: (1) tỷ lệ dữ liệu tĩnh lặp lại giữa các request (càng cao, cache càng hiệu quả), (2) tần suất gọi (volume cao khuếch đại cả lợi ích và rủi ro của mỗi lựa chọn), (3) độ nhạy về độ chính xác truy xuất (một số bài toán cần định vị chính xác 1 đoạn thông tin trong hàng triệu token, mà "nhúng hết" đôi khi làm giảm chất lượng do hiện tượng "lost in the middle" — model có xu hướng bỏ sót thông tin ở giữa context rất dài).
Ma trận quyết định đơn giản:
| Tỷ lệ cache hit dự kiến | Volume request | Độ nhạy độ chính xác truy xuất | Khuyến nghị |
|---|---|---|---|
| Cao (> 70%) | Bất kỳ | Thấp–trung bình | FULL CONTEXT — nhúng toàn bộ, tận dụng cache |
| Cao (> 70%) | Cao | Cao (cần định vị chính xác) | HYBRID — nhúng phần lớn tài liệu tĩnh + retrieval cho phần biến động |
| Thấp (< 30%) | Cao | Bất kỳ | RAG — retrieval vẫn tối ưu vì mỗi request context khác nhau, cache không giúp được |
| Thấp (< 30%) | Thấp | Bất kỳ | Cân nhắc theo chi phí tuyệt đối — volume thấp thì chênh lệch không đáng để đổi kiến trúc |
Lưu ý quan trọng: "cache hit rate cao" không tự nhiên mà có — nó đòi hỏi bạn thiết kế prompt để phần tĩnh (system prompt, tài liệu tham chiếu) luôn nằm ở đầu prompt và giữ nguyên thứ tự/nội dung giữa các request, còn phần biến động (câu hỏi người dùng, dữ liệu theo session) nằm ở cuối. Nếu bạn xáo trộn thứ tự hoặc chèn timestamp vào phần đầu prompt, cache sẽ liên tục bị miss dù bạn "tưởng" đang cache.
Re-evaluating RAG in the Large Context Era
RAG không "chết" — nhưng vai trò của nó thay đổi. Trước đây RAG giải quyết bài toán "context không đủ chỗ chứa toàn bộ tri thức". Với context 1 triệu token, với nhiều bộ tài liệu nội bộ, "không đủ chỗ" không còn là vấn đề — vấn đề còn lại là "chi phí" và "độ chính xác truy xuất".
Ví dụ cụ thể để minh họa cách đánh giá lại:
Old architecture (RAG):
- Vector DB (embedding + retrieval): ~$180/month vận hành
- Avg input tokens/request: 2,200 (top-5 chunks + question)
- Cost: 3,000 req/day * 2,200 tokens * $0.15/1M = ~$29.7/day = ~$890/month
- Rủi ro: retrieval sai chunk ~8% số câu hỏi → cần re-query, giảm trải nghiệm
New architecture (Full Context + Prompt Caching):
- Toàn bộ 180,000 token tài liệu nằm ở đầu prompt, cache trong 5 phút (rolling)
- Cache hit rate thực đo: 92% (nhiều câu hỏi liên tiếp trong ngày làm việc)
- Cached input cost: 180,000 * $0.15/1M * 0.1 (giá cache ~10% giá gốc) = $0.0027/request khi hit
- Cache miss (8%): 180,000 * $0.15/1M = $0.027/request
- Cost: (0.92 * 0.0027 + 0.08 * 0.027) * 3,000 = ~$14.1/day = ~$423/month
- Không cần vận hành Vector DB, không có rủi ro retrieval sai chunk
Bài học rút ra không phải "luôn bỏ RAG" mà là: khi bộ tri thức của bạn đủ nhỏ để nằm trong context window có cache, và traffic pattern đủ tập trung để cache hit rate cao, phương án full-context thường thắng cả về chi phí lẫn chất lượng (không còn lỗi retrieval sai). RAG vẫn là lựa chọn đúng khi bộ tri thức quá lớn (hàng chục triệu token), khi mỗi request cần một tập con dữ liệu hoàn toàn khác nhau (cache hit rate thấp), hoặc khi cần cập nhật dữ liệu theo thời gian thực mà việc re-cache toàn bộ context là không thực tế.
Mẹo: Đừng chuyển đổi kiến trúc RAG → full-context (hoặc ngược lại) dựa trên trực giác. Chạy song song (shadow mode) cả hai kiến trúc trên một phần traffic thực trong 1–2 tuần, đo cả chi phí thực tế VÀ độ chính xác câu trả lời (qua human review hoặc LLM-as-judge có kiểm định), rồi mới quyết định rollout toàn bộ.
Monitoring Pricing and Model Release Changes
Bạn không thể phản ứng với những thay đổi mà bạn không biết đang xảy ra. Phần này xây dựng cơ chế giám sát tự động — không cần con người ngồi kiểm tra changelog mỗi ngày.
Pricing Change Alerting
Ý tưởng: một script chạy định kỳ (cron job hoặc GitHub Actions), pull giá hiện tại từ API/trang pricing của các nhà cung cấp bạn dùng, so sánh với giá đã lưu lần trước, và cảnh báo nếu có thay đổi vượt một ngưỡng.
"""
Theo dõi thay đổi giá của các model đang dùng trong production.
Chạy hàng ngày qua cron/GitHub Actions, so sánh với snapshot giá lần trước
được lưu trong pricing_snapshot.json, và gửi cảnh báo Slack nếu chênh lệch
vượt ngưỡng PRICE_CHANGE_THRESHOLD.
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
import requests
SNAPSHOT_PATH = Path("data/pricing_snapshot.json")
PRICE_CHANGE_THRESHOLD = 0.05 # cảnh báo nếu giá đổi >= 5%
SLACK_WEBHOOK_URL_ENV = "SLACK_PRICING_WEBHOOK_URL"
TRACKED_MODELS = [
{"provider": "anthropic", "model": "claude-sonnet-5"},
{"provider": "openai", "model": "gpt-4o-mini"},
{"provider": "openai", "model": "gpt-4o"},
]
def fetch_current_pricing(provider: str, model: str) -> dict:
"""
Gọi API pricing của nhà cung cấp (hoặc parse trang pricing công khai).
Trả về dict gồm input_per_million, output_per_million, cached_input_per_million.
Triển khai thực tế cần adapter riêng cho từng provider.
"""
# NOTE: thay bằng lời gọi API/scraper thực tế của bạn.
raise NotImplementedError
def load_snapshot() -> dict:
if SNAPSHOT_PATH.exists():
return json.loads(SNAPSHOT_PATH.read_text())
return {}
def save_snapshot(snapshot: dict) -> None:
SNAPSHOT_PATH.parent.mkdir(parents=True, exist_ok=True)
SNAPSHOT_PATH.write_text(json.dumps(snapshot, indent=2))
def send_slack_alert(message: str) -> None:
import os
webhook = os.environ.get(SLACK_WEBHOOK_URL_ENV)
if not webhook:
print(f"[WARN] No Slack webhook configured. Alert: {message}")
return
requests.post(webhook, json={"text": message}, timeout=10)
def main() -> int:
snapshot = load_snapshot()
changes_found = False
new_snapshot = dict(snapshot)
for entry in TRACKED_MODELS:
key = f"{entry['provider']}:{entry['model']}"
current = fetch_current_pricing(entry["provider"], entry["model"])
previous = snapshot.get(key)
new_snapshot[key] = {
**current,
"checked_at": datetime.now(timezone.utc).isoformat(),
}
if previous is None:
continue # lần đầu theo dõi, chưa có gì để so sánh
for field in ("input_per_million", "output_per_million", "cached_input_per_million"):
old_val = previous.get(field)
new_val = current.get(field)
if old_val is None or new_val is None or old_val == 0:
continue
pct_change = (new_val - old_val) / old_val
if abs(pct_change) >= PRICE_CHANGE_THRESHOLD:
changes_found = True
direction = "GIẢM" if pct_change < 0 else "TĂNG"
send_slack_alert(
f":rotating_light: [Pricing Alert] {key} — {field} {direction} "
f"{abs(pct_change) * 100:.1f}% (${old_val} → ${new_val} / 1M tokens). "
f"Cần chạy lại model_evaluation_pipeline để đánh giá cơ hội migrate."
)
save_snapshot(new_snapshot)
return 0 if not changes_found else 0 # exit 0 luôn, alert đã gửi qua Slack
if __name__ == "__main__":
sys.exit(main())
Script này chạy an toàn hàng ngày, không cần ai kiểm tra tay: nó tự lưu snapshot, tự so sánh, và chỉ làm phiền bạn qua Slack khi có thay đổi thực sự đáng chú ý (vượt ngưỡng 5%). Khi có cảnh báo, đó chính là tín hiệu để chạy lại pipeline đánh giá model ở phần trước.
Release Monitoring Strategy
Ngoài giá, bạn cũng cần biết khi nào có model MỚI ra mắt (không chỉ đổi giá model cũ). Hai cơ chế bổ trợ nhau:
- RSS feeds or email alerts for changelog monitoring: hầu hết nhà cung cấp lớn đều có trang changelog với RSS feed hoặc mailing list release notes. Đăng ký các nguồn này bằng một RSS reader tự động (hoặc filter email vào một channel/label riêng) đảm bảo bạn không phải chủ động vào từng trang kiểm tra.
- Set up GitHub Actions to check weekly and post to Slack: với các nhà cung cấp không có RSS ổn định, dùng một workflow định kỳ để kiểm tra và tổng hợp.
name: AI Provider Changelog Watch
on:
schedule:
- cron: "0 9 * * 1" # 9:00 sáng thứ Hai hàng tuần (UTC)
workflow_dispatch: {} # cho phép chạy tay khi cần
jobs:
check-changelogs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: pip install requests feedparser
- name: Check provider changelogs and pricing pages
id: check
run: python scripts/check_provider_updates.py
env:
GH_STATE_PATH: .github/state/last_seen_releases.json
- name: Commit updated state
if: steps.check.outputs.has_updates == 'true'
run: |
git config user.name "ai-provider-watch-bot"
git config user.email "bot@example.com"
git add .github/state/last_seen_releases.json
git commit -m "chore: update last-seen AI provider releases"
git push
- name: Notify Slack
if: steps.check.outputs.has_updates == 'true'
uses: slackapi/slack-github-action@v1.27.0
with:
payload: |
{
"text": "${{ steps.check.outputs.summary }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_PRICING_WEBHOOK_URL }}
Workflow này chạy vào mỗi sáng thứ Hai, kiểm tra changelog của các nhà cung cấp đã cấu hình, so sánh với danh sách release đã "thấy" lần trước (lưu trong .github/state/last_seen_releases.json), và chỉ post lên Slack khi có release mới — không spam channel mỗi tuần nếu không có gì thay đổi.
Mẹo: Đặt một "budget" thời gian rõ ràng cho việc theo dõi này — ví dụ 30 phút/tuần để đọc lướt các cảnh báo Slack và quyết định có cần chạy model evaluation pipeline hay không. Nếu không có ngân sách thời gian cụ thể, cảnh báo sẽ tích tụ và bị bỏ qua, khiến toàn bộ hệ thống giám sát trở nên vô nghĩa.
Durable vs. Ephemeral Optimization Techniques
Không phải mọi kỹ thuật tối ưu bạn học trong khóa học này có "tuổi thọ" bằng nhau. Phân biệt rõ kỹ thuật nào bền vững (durable) và kỹ thuật nào tạm thời (ephemeral) giúp bạn đầu tư thời gian đúng chỗ — và biết khi nào một kỹ thuật cần được "nghỉ hưu".
Durable Techniques (remain valuable regardless of model evolution)
Đây là các nguyên lý gắn với bản chất kinh tế của token-based pricing, không phụ thuộc vào model cụ thể nào:
- Loại bỏ thông tin thừa trong prompt (dead weight — nội dung không ảnh hưởng đến output nhưng vẫn tốn token): luôn có giá trị, vì pricing luôn tính theo số token gửi đi, bất kể model mạnh hay yếu đến đâu.
- Structured output / function calling chặt chẽ: giảm output token dư thừa (giải thích dài dòng khi chỉ cần JSON), luôn tiết kiệm chi phí và giảm rủi ro parse lỗi.
- Prompt caching cho phần nội dung tĩnh lặp lại: nguyên lý "tách phần tĩnh khỏi phần động để tối đa hóa cache hit" sẽ còn đúng miễn là mô hình pricing dựa trên cache còn tồn tại — và không có dấu hiệu nó biến mất trong tương lai gần.
- Đo lường trước khi tối ưu (đo token usage theo từng workload trước khi quyết định thay đổi gì): đây là nguyên lý kỹ thuật phần mềm nói chung, không riêng gì LLM — luôn đúng.
- Batching các request không cần real-time: chênh lệch giá giữa batch và real-time API tồn tại vì lý do hạ tầng (cho phép nhà cung cấp lên lịch tải), nên nó sẽ còn tồn tại lâu dài.
- Golden set / eval pipeline độc lập với model: là hạ tầng đánh giá, không phải kỹ thuật tối ưu cho một model cụ thể — luôn cần thiết để ra quyết định dựa trên dữ liệu.
Ephemeral Techniques (may become less relevant with model evolution)
Đây là các kỹ thuật được sinh ra để khắc phục hạn chế CỤ THỂ của model/context đời hiện tại — và sẽ mất giá trị (hoặc thậm chí phản tác dụng) khi hạn chế đó biến mất:
- Chunking tài liệu thành đoạn nhỏ để "lách" context window hạn chế: mất giá trị dần khi context window đủ lớn để chứa toàn bộ tài liệu với cache hit rate cao (xem lại phần "Re-evaluating RAG").
- Few-shot prompting dài với nhiều ví dụ để "dạy" model đời cũ một pattern: model mới thường học pattern từ 1–2 ví dụ, hoặc từ instruction ngắn gọn — giữ 5–8 ví dụ cũ chỉ tốn token vô ích.
- Chuỗi chain-of-thought ép buộc ("hãy suy nghĩ từng bước") cho các bài toán đơn giản: model reasoning đời mới tự động áp dụng reasoning nội bộ hiệu quả hơn, ép thêm CoT thủ công có thể chỉ làm tăng output token mà không tăng chất lượng.
- Prompt "vá lỗi" hành vi cụ thể của một model (ví dụ: "Đừng thêm lời chào ở đầu câu trả lời" để sửa tật của một model cụ thể): những "vá lỗi" này gắn chặt với model version cụ thể và cần được xem lại mỗi lần đổi model.
- Kiến trúc multi-step phức tạp để bù cho model yếu về reasoning phức tạp: khi model mới xử lý trực tiếp được bài toán trong 1 bước, kiến trúc multi-step cũ chỉ làm tăng số lượt gọi (và tổng token) không cần thiết.
Mẹo: Gắn tag #durable hoặc #ephemeral (dưới dạng comment) ngay trong code khi bạn implement một kỹ thuật tối ưu. Khi review định kỳ (theo lịch ở phần trước), lọc riêng các đoạn #ephemeral để kiểm tra trước — đây chính là nơi có khả năng cao nhất đã "hết thời" và cần đánh giá lại.
Future-Proofing Your Optimization Architecture
Mục tiêu cuối cùng không phải là dự đoán đúng tương lai (không ai làm được điều này với độ chính xác cao), mà là xây dựng kiến trúc để khi tương lai đến — model mới, giá mới, context window mới — bạn thích ứng bằng việc đổi cấu hình, không phải viết lại code.
Design Principles for Adaptive Systems
Ba nguyên tắc thiết kế cốt lõi:
- Tách model selection ra khỏi business logic: code xử lý nghiệp vụ không nên "hardcode" tên model. Một layer routing (điều hướng) riêng chịu trách nhiệm chọn model dựa trên yêu cầu của workload, đọc từ config có thể cập nhật độc lập.
- Tham số hóa các ngưỡng, không hardcode: ngưỡng cache, ngưỡng context length để chuyển giữa RAG và full-context, ngưỡng tiết kiệm chi phí để migrate — tất cả nên nằm trong config, không nằm rải rác trong logic if/else.
- Thiết kế cho khả năng A/B test song song nhiều model: kiến trúc phải cho phép chạy 2 model cùng lúc trên các tỷ lệ traffic khác nhau, để việc đánh giá model mới (ở phần "Building a Model Evaluation Pipeline") có thể chạy trên traffic thật, không chỉ trên golden set offline.
Một implementation cụ thể — module routing đọc config để chọn model, không cần đổi code khi có model mới:
"""
Router chọn model cho một workload dựa trên config model_routing.yaml.
Business logic gọi router.get_model(workload_name) và không cần biết
model cụ thể nào đang được dùng phía sau.
"""
from dataclasses import dataclass
from pathlib import Path
import yaml
@dataclass
class ModelChoice:
provider: str
model: str
supports_prompt_caching: bool
max_context_tokens: int
class ModelRouter:
def __init__(self, config_path: str = "config/model_routing.yaml"):
self._config_path = Path(config_path)
self._config = self._load_config()
def _load_config(self) -> dict:
return yaml.safe_load(self._config_path.read_text())
def reload(self) -> None:
"""Cho phép reload config khi có thay đổi mà không cần restart service."""
self._config = self._load_config()
def get_model(self, workload_name: str) -> ModelChoice:
workloads = self._config.get("workloads", {})
entry = workloads.get(workload_name)
if entry is None:
entry = self._config["default"]
return ModelChoice(
provider=entry["provider"],
model=entry["model"],
supports_prompt_caching=entry.get("supports_prompt_caching", False),
max_context_tokens=entry.get("max_context_tokens", 128_000),
)
def get_canary_model(self, workload_name: str) -> ModelChoice | None:
"""Trả về model đang được canary test cho workload này, nếu có."""
canary_cfg = self._config.get("canary", {}).get(workload_name)
if canary_cfg is None:
return None
return ModelChoice(
provider=canary_cfg["provider"],
model=canary_cfg["model"],
supports_prompt_caching=canary_cfg.get("supports_prompt_caching", False),
max_context_tokens=canary_cfg.get("max_context_tokens", 128_000),
)
Và file config tương ứng — đây là "bề mặt cập nhật" (update surface) chính khi có model mới ra mắt:
default:
provider: openai
model: gpt-4o-mini
supports_prompt_caching: true
max_context_tokens: 128000
workloads:
ticket_classifier:
provider: openai
model: gpt-4o-mini
supports_prompt_caching: true
max_context_tokens: 128000
commit_message_generator:
provider: anthropic
model: claude-sonnet-5
supports_prompt_caching: true
max_context_tokens: 200000
internal_docs_qa:
provider: anthropic
model: claude-sonnet-5
supports_prompt_caching: true
max_context_tokens: 1000000 # cập nhật khi context window mở rộng
canary:
ticket_classifier:
provider: openai
model: gpt-4o-mini-v2 # ví dụ model mới vừa ra mắt
supports_prompt_caching: true
max_context_tokens: 128000
traffic_pct: 5
Với thiết kế này, quy trình phản ứng khi có model mới trở thành: (1) chạy model evaluation pipeline, (2) nếu đạt ngưỡng, thêm entry vào block canary với traffic_pct nhỏ, (3) theo dõi 48–72 giờ, (4) nếu ổn, chuyển entry đó lên workloads chính và xóa canary — toàn bộ không cần một dòng code nào thay đổi trong service xử lý nghiệp vụ.
Mẹo: Đừng để model_routing.yaml trở thành một file "viết rồi bỏ quên". Thêm một bước CI kiểm tra: mỗi khi file này thay đổi, tự động chạy lại một tập smoke test nhỏ (10–20 case trong golden set) với model mới trong config trước khi cho phép merge — điều này ngăn một thay đổi config tưởng như "chỉ đổi tên model" vô tình phá vỡ một workload production.
Summary
Ba lực — context window mở rộng, giá thay đổi, năng lực model cải thiện — không phải là những sự kiện đơn lẻ mà là xu hướng liên tục sẽ tiếp diễn trong nhiều năm tới. Phản ứng đúng không phải là chạy theo từng tin tức model mới, mà là xây dựng ba lớp hạ tầng bền vững: (1) một pipeline đánh giá model có kỷ luật, dựa trên golden set và ngưỡng định lượng rõ ràng; (2) một cơ chế giám sát tự động cho pricing và release, để bạn biết khi nào cần hành động mà không phải kiểm tra tay; (3) một kiến trúc routing tách model selection ra khỏi business logic, để việc thích ứng chỉ đòi hỏi đổi config, không đòi hỏi viết lại code.
Đồng thời, hãy phân biệt rõ kỹ thuật tối ưu nào là nguyên lý bền vững (loại bỏ dead weight, prompt caching, đo lường trước khi tối ưu) và kỹ thuật nào chỉ là giải pháp tạm thời cho hạn chế hiện tại (chunking để lách context nhỏ, few-shot dài để "dạy" model yếu). Đầu tư thời gian học sâu vào nhóm đầu; sẵn sàng "nghỉ hưu" nhóm sau khi model evolution làm chúng trở nên dư thừa.
Cuối cùng, tối ưu token không phải là một dự án có điểm kết thúc — nó là một năng lực vận hành liên tục, giống như security patching hay performance monitoring. Đội ngũ nào xây dựng được thói quen và hạ tầng để thích ứng nhanh với ba lực này sẽ liên tục vận hành ở mức chi phí thấp hơn và chất lượng cao hơn so với đội ngũ chỉ tối ưu một lần rồi để nguyên.