Menekan biaya inference dengan strategi berlapis: batching, caching, model routing, dan quantization. Kalian belajar mengukur biaya per fitur, memetakan workload ke model yang tepat, dan menurunkan cost tanpa mengorbankan kualitas jawabantype: text

Di episode 17 kalian memasang cost tracking. Episode ini memakainya: cost optimization — seni menurunkan biaya inference tanpa menurunkan kualitas. Ini bukan sekadar "hemat", tapi keputusan arsitektur: biaya per request menentukan harga produk, margin bisnis, dan seberapa besar volume yang bisa kalian layani.
Mengapa penting? Karena satu request yang "mahal" terlihat kecil, tapi dikali 10 juta request per bulan hasilnya jutaan dolar. Tim AI engineer yang baik adalah tim yang bisa menjawab pertanyaan "fitur ini menghabiskan berapa, dan bagaimana menurunkannya?" dengan data, bukan perasaan.
Semua optimasi dimulai dari data biaya per fitur (dari episode 17). Sebelum mengoptimasi, jawab: fitur mana yang paling mahal? Biasanya pola yang sama muncul: satu fitur menyumbang mayoritas biaya.
from collections import defaultdict
biaya = defaultdict(float) # fitur -> total cost (dari metrik episode 17)
for m in get_cost_metrics(): # placeholder data observability
biaya[m["feature"]] += m["cost"]
total = sum(biaya.values())
for fitur, cost in sorted(biaya.items(), key=lambda x: -x[1]):
print(f"{fitur}: {cost:,.0f} ({cost/total:.0%})")Aturan Pareto biasanya berlaku: 80% biaya datang dari 20% fitur. Optimasi dimulai dari situ.
| Strategi | Cara Kerja | Efek |
|---|---|---|
| Caching | Hindari panggilan LLM berulang | Bisa memangkas 50-90% volume |
| Model routing | Model kecil untuk yang mudah | Turunkan biaya rata-rata per request |
| Batching / prompt compression | Lebih sedikit token per request | Turunkan biaya per request |
| Quantization (self-host) | Model 4-bit vs 16-bit | Turunkan kebutuhan GPU |
Kita sudah membangun semantic caching di episode 8. Tingkatkan: cache di beberapa level.
import redis, hashlib, json
cache = redis.Redis(host="localhost", port=6379)
def cached_call(model: str, messages: list[dict], ttl: int = 86400) -> str:
key = hashlib.sha256(json.dumps([model, messages]).encode()).hexdigest()
hit = cache.get(key)
if hit:
return hit.decode()
jawaban = llm_call(model, messages)
cache.set(key, jawaban, ex=ttl)
return jawabanPerhatian: jangan pernah men-cache data pribadi (episode 20) — cache identik tanpa pemisahan user adalah kebocoran data.
Tidak semua request butuh model frontier. Model routing memetakan request ke model berdasarkan kompleksitas:
TIERS = [
{"model": "gpt-4o", "min_score": 0.8, "note": "kontrak / dokumen penting"},
{"model": "gpt-4o-mini", "min_score": 0.4, "note": "percakapan normal"},
{"model": "qwen3:8b", "min_score": 0.0, "note": "klasifikasi sederhana"},
]
def route_request(request) -> str:
skor = complexity_score(request) # placeholder: heuristic
for t in TIERS:
if skor >= t["min_score"]:
return t["model"]
return TIERS[-1]["model"]Cara menentukan complexity score: panjang prompt, fitur (biasa vs premium), retry history, atau klasifikasi cepat oleh model kecil. Pola umum: kaskade — mulai dengan model murah; jika model memberi sinyal keraguan (atau evaluasi gagal), naik ke model mahal:
def cascaded_call(messages: list[dict]) -> str:
jawaban = llm_call("gpt-4o-mini", messages)
if not confidence_ok(jawaban): # sinyal keraguan dari model murah
jawaban = llm_call("gpt-4o", messages)
return jawabanKaskade sering memangkas biaya 50-70% karena mayoritas request selesai di tier murah.
Tip
Evaluasi routing secara berkala (episode 9): ambil sampel request yang di-routing ke model murah dan ukur kualitasnya dengan LLM-judge. Jika kualitas turun, sesuaikan ambang routing. Routing tanpa evaluasi adalah tebakan.
Setiap token yang tidak perlu adalah uang. Tiga target utama:
import tiktoken
enc = tiktoken.encoding_for_model("gpt-4o")
asli = enc.encode(system_prompt + context + pertanyaan)
optimized = enc.encode(optimized_system + top3_context + pertanyaan)
print(f"token: {len(asli)} -> {len(optimized)} "
f"(hemat {(1 - len(optimized)/len(asli)):.0%})")Untuk self-host (episode 21), quantization menurunkan presisi bobot model (16-bit → 8-bit → 4-bit). Dampaknya:
| Presisi | VRAM (7B model) | Kualitas |
|---|---|---|
| FP16 | ~14 GB | Referensi |
| INT8 | ~7 GB | Sedikit menurun |
| INT4 (GGUF/AWQ) | ~4 GB | Sedikit menurun, sering dapat diterima |
vllm serve Qwen/Qwen2.5-7B-Instruct-AWQ \
--quantization awq --max-model-len 8192Aturan praktis: 4-bit untuk tugas generatif sederhana, 8-bit jika butuh kualitas lebih, FP16 jika kualitas adalah segalanya. Selalu ukur dengan eval suite (episode 9) — "sedikit menurun" harus terukur, bukan asumsi.
Inti yang harus dibawa pulang:
Di episode 23 selanjutnya kita menaikkan level agent: multi-agent & orchestration — LangGraph/CrewAI, agent teams, dan menyeimbangkan kekuatan multi-agent dengan determinisme. Sampai jumpa di episode 23!