anoman
Resep · Perutean Hemat Biaya

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 → premium
Mode kegagalan: classifier salah mengarahkan pertanyaan sulit ke model murah. Setel system prompt agar cenderung eskalasi, atau gunakan pola hybrid di bawah.

Pola 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, CHEAP

Pola 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: semantic pada 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.