Arahkan mudah → murah, sulit → premium.
Dua pola: classifier-first memilih model di awal, confidence-based hanya eskalasi saat diperlukan. Keduanya memangkas biaya 80%+ dibanding perutean naif ke satu model premium saja.
Kenapa perlu
Sebagian besar permintaan itu mudah
Distribusi trafik produksi sangat timpang. Di sebagian besar trafik chatbot + support, ~60% permintaan berupa pencarian faktual atau pemformatan sederhana — model kelas hemat menanganinya dengan sempurna. Mengarahkan itu ke claude-sonnet-4-6 berarti membayar ~15× lebih mahal dari yang diperlukan.
Triknya: model mungil untuk memutuskan model mana yang dipakai. Atau: coba yang murah dulu dan eskalasi saat confidence rendah.
Pola 1 — Classifier lebih dulu
Pilih model di awal
Model 7B mengklasifikasikan tingkat kesulitan pertanyaan. Classifier menambah ~$0.000_05 per permintaan — dapat diabaikan dibanding panggilan sonnet seharga $0.012.
import os
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.anoman.io/v1", api_key=os.environ["ANOMAN_API_KEY"])
# Tiny, cheap classifier. ~$0.000_05 per call.
CLASSIFIER_MODEL = "qwen-2.5-7b"
# Heavy model for hard requests.
HEAVY_MODEL = "claude-sonnet-4-6"
# Cheap model for easy requests.
LIGHT_MODEL = "gpt-4o-mini"
CLASSIFIER_SYSTEM = """
Classify the difficulty of the user's question as one of:
easy — Factual lookup, simple instruction, short formatting task
medium — Multi-step reasoning, document summarization, code generation
hard — Algorithm design, math proof, multi-turn planning, long context
Respond with ONLY the single word. No explanation.
""".strip()
def classify(question: str) -> str:
response = client.chat.completions.create(
model=CLASSIFIER_MODEL,
messages=[
{"role": "system", "content": CLASSIFIER_SYSTEM},
{"role": "user", "content": question},
],
max_tokens=10,
temperature=0,
)
return response.choices[0].message.content.strip().lower()
def ask(question: str) -> str:
difficulty = classify(question)
model = {
"easy": LIGHT_MODEL,
"medium": LIGHT_MODEL,
"hard": HEAVY_MODEL,
}.get(difficulty, HEAVY_MODEL) # safe default: escalate
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": question}],
# Track which path took for monitoring
metadata={"routed_via": "classifier", "difficulty": difficulty},
)
return response.choices[0].message.content
print(ask("Capital of Indonesia?")) # easy → cheap
print(ask("Prove that the halting problem is undecidable.")) # hard → premiumPola 2 — Eskalasi confidence
Coba murah, eskalasi saat menyerah
Menginstruksikan model murah untuk merespons dengan ESCALATE saat tidak yakin. Model murah mendapat kesempatan menangani setiap permintaan; kita hanya membayar premium saat ia secara eksplisit menyerah. Tingkat eskalasi ~5% umum untuk setup dengan prompt yang baik.
# Try the cheap model first. Only escalate when the cheap model says
# "I'm not sure" or doesn't follow the output format.
CHEAP = "gpt-4o-mini"
HEAVY = "claude-sonnet-4-6"
ASK_SYSTEM = """
Answer the user's question. If you're not confident, respond with
exactly: ESCALATE
Otherwise, give the answer.
""".strip()
def ask_with_escalation(question: str) -> tuple[str, str]:
"""Returns (answer, model_used)."""
response = client.chat.completions.create(
model=CHEAP,
messages=[
{"role": "system", "content": ASK_SYSTEM},
{"role": "user", "content": question},
],
max_tokens=300,
temperature=0,
)
answer = response.choices[0].message.content.strip()
if answer.startswith("ESCALATE") or answer == "":
# Cheap model bailed. Escalate.
response = client.chat.completions.create(
model=HEAVY,
messages=[{"role": "user", "content": question}],
)
return response.choices[0].message.content, HEAVY
return answer, CHEAPPola 3 — Hybrid
Classifier + eskalasi
Gunakan classifier sebagai gerbang cepat untuk mengarahkan permintaan sulit yang jelas langsung ke premium (tanpa overhead panggilan ganda). Untuk selebihnya, jalur murah-dengan-eskalasi berlaku. Gabungan terbaik keduanya.
# Combine both: the classifier picks a candidate model, the candidate
# can still escalate on low confidence. Catches mis-classifications.
def smart_ask(question: str) -> dict:
difficulty = classify(question)
if difficulty == "hard":
# Skip cheap layer entirely.
return {"answer": ask_heavy(question), "model": HEAVY, "path": "direct"}
answer, model_used = ask_with_escalation(question)
return {
"answer": answer,
"model": model_used,
"path": "escalated" if model_used == HEAVY else "cheap",
}Ekonomi
Perhitungan kasar
Assume 10,000 requests/day:
- 60% easy (factual)
- 30% medium (summarization, simple code)
- 10% hard (multi-step reasoning)
Naive routing — everything to claude-sonnet-4-6:
- Avg cost: ~$0.012 per request (~500 in + ~300 out tokens)
- Daily: $120
- Monthly: ~$3,600
Classifier-first routing:
- Classifier: 10K × $0.00005 = $0.50
- Easy → cheap (6K × $0.0005) = $3
- Med → cheap (3K × $0.0008) = $2.40
- Hard → heavy (1K × $0.012) = $12
- Daily: $17.90
- Monthly: ~$540
- Savings: 85% vs naive
Confidence escalation — assume 5% escalation rate from cheap:
- Cheap call: 10K × $0.0008 = $8
- Heavy retry: 500 × $0.012 = $6
- Daily: $14
- Monthly: ~$420
- Savings: 88% vs naive
Tips produksi
- Lacak metadata — kirim
metadata: {difficulty, path}pada setiap panggilan agar halaman Usage di dashboard menampilkan distribusi perutean. Membantu Anda menyetel prompt classifier. - Pantau tingkat eskalasi — jika >15%, classifier Anda terlalu sering salah mengarahkan. Setel prompt atau pindah ke pola hybrid.
- Jalur sadar latensi — classifier menambah ~200 ms. Untuk UX yang sensitif latensi, pilih eskalasi confidence (jalur murah sekali panggil, eskalasi hanya saat diperlukan).
- Cache classifier — pertanyaan yang sama menghasilkan klasifikasi yang sama. Tambahkan
x-anoman-cache: semanticpada panggilan classifier agar pertanyaan berulang melewati bahkan hop classifier murah. - A/B test ambang batas — pisahkan 5% trafik ke "selalu pakai premium" sebagai kontrol kualitas. Bandingkan tingkat thumbs-up pengguna akhir vs kelompok yang dirutekan.
Lacak distribusi perutean Anda di dashboard.
Rincian per-model dengan biaya per rute.