0Pricing
AI Engineering Academy · Pelajaran

Pengelompokan, Perutean Model, dan Dasbor Biaya

Arahkan permintaan sederhana ke model yang lebih murah seperti GPT-4o-mini dan permintaan kompleks ke GPT-4o, kelompokkan permintaan yang tidak mendesak, lalu buat dasbor biaya yang melacak pengeluaran berdasarkan fitur.

Pengelompokan, Perutean Model, dan Dasbor Biaya adalah pelajaran AI Engineering Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Engineering Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Engineering Academy mencakup 4 pelajaran total.

Tiga Tuas Tambahan untuk Pengoptimalan Biaya

Setelah caching, tiga strategi tambahan dapat mengurangi biaya operasional LLM secara drastis: pengelompokan permintaan (menunda permintaan yang tidak mendesak dan mengirimkannya secara massal dengan tarif API yang lebih rendah), perutean model (mengarahkan kueri sederhana ke model murah dan kueri kompleks ke model yang lebih canggih), serta dasbor biaya (melacak pengeluaran per fitur untuk menemukan bagian yang memberikan ROI pengoptimalan tertinggi). Secara keseluruhan, strategi ini dapat mengurangi biaya sebesar 40-60 persen lagi setelah caching.

Batch API OpenAI: Diskon 50% untuk Beban Kerja Asinkron

Batch API OpenAI menerima file JSONL yang berisi hingga 50.000 permintaan dan memprosesnya secara asinkron dalam waktu 24 jam dengan 50 persen dari harga standar. Fitur ini ideal untuk beban kerja noninteraktif: membuat embedding untuk korpus dokumen besar, menghasilkan deskripsi produk, menjalankan evaluasi setiap malam, atau melakukan prapemrosesan data pelatihan. Imbalannya adalah latensi—hasil tersedia beberapa jam kemudian, bukan segera.

import json
from openai import OpenAI

client = OpenAI()

# Prepare batch file
requests = [
    {
        'custom_id': f'req_{i}',
        'method': 'POST',
        'url': '/v1/chat/completions',
        'body': {
            'model': 'gpt-4o-mini',
            'messages': [
                {'role': 'user', 'content': f'Summarize: {document}'}
            ],
            'max_tokens': 150,
        }
    }
    for i, document in enumerate(documents_to_process)
]

# Write JSONL batch file
with open('/tmp/batch_requests.jsonl', 'w') as f:
    for req in requests:
        f.write(json.dumps(req) + '\n')

# Upload and submit batch
with open('/tmp/batch_requests.jsonl', 'rb') as f:
    batch_file = client.files.create(file=f, purpose='batch')

batch = client.batches.create(
    input_file_id=batch_file.id,
    endpoint='/v1/chat/completions',
    completion_window='24h',
)
print(f'Batch {batch.id} submitted, status: {batch.status}')

Memantau Hasil Batch

Setelah mengirim batch, pantau statusnya hingga selesai (status berubah dari in_progress menjadi completed). Setelah selesai, unduh file keluaran yang berisi hasil untuk semua permintaan. Setiap baris keluaran adalah objek JSON dengan custom_id dari permintaan dan salah satu dari kolom response atau error—selalu tangani keduanya karena setiap permintaan dalam satu batch dapat gagal secara independen.

import time

def wait_for_batch(batch_id: str, poll_interval: int = 60) -> str:
    while True:
        batch = client.batches.retrieve(batch_id)
        print(f'Status: {batch.status}, completed: {batch.request_counts.completed}')

        if batch.status == 'completed':
            return batch.output_file_id
        elif batch.status == 'failed':
            raise RuntimeError(f'Batch failed: {batch.errors}')

        time.sleep(poll_interval)

def download_batch_results(output_file_id: str) -> list[dict]:
    content = client.files.content(output_file_id)
    results = []
    for line in content.text.strip().split('\n'):
        results.append(json.loads(line))
    return results

output_file_id = wait_for_batch(batch.id)
results = download_batch_results(output_file_id)
for result in results[:3]:
    print(result['custom_id'], result.get('response', {}).get('body', {}).get('choices', [{}])[0])

Perutean Model: Sesuaikan Kompleksitas dengan Ukuran Model

Perutean model menetapkan setiap permintaan ke model termurah yang mampu menanganinya dengan baik. GPT-4o-mini berbiaya sekitar 30 kali lebih rendah daripada GPT-4o, tetapi sama baiknya untuk tugas klasifikasi sederhana, ekstraksi, dan tanya jawab singkat. Arahkan tugas sederhana dan terstruktur ke model kecil yang murah, sedangkan penalaran kompleks, sintesis konteks panjang, dan pembuatan yang bernuansa ke model besar yang kuat. Bahkan jika 60 persen lalu lintas diarahkan ke model murah, penghematan biayanya tetap signifikan.

CHEAP_MODEL = 'gpt-4o-mini'
POWERFUL_MODEL = 'gpt-4o'

def classify_query_complexity(query: str) -> str:
    # Heuristic-based routing (replace with ML classifier for production)
    words = query.split()
    has_code = any(c in query for c in ['```', 'def ', 'class ', 'SELECT ', 'function '])
    is_multi_step = any(w in query.lower() for w in ['compare', 'analyze', 'explain why', 'evaluate'])
    is_long = len(words) > 50

    if has_code or is_multi_step or is_long:
        return POWERFUL_MODEL
    return CHEAP_MODEL

def routed_completion(messages: list[dict]) -> str:
    user_query = messages[-1].get('content', '')
    model = classify_query_complexity(user_query)
    print(f'Routing to: {model}')
    response = client.chat.completions.create(model=model, messages=messages)
    return response.choices[0].message.content

Perutean Berbasis LLM untuk Akurasi Lebih Tinggi

Perutean heuristik memang cepat, tetapi rapuh. Pendekatan yang lebih akurat menggunakan model klasifikasi kecil dan murah untuk menentukan model yang akan digunakan. Lakukan penyetelan halus pada model kecil menggunakan contoh kueri sederhana dan kompleks dalam domain Anda, atau gunakan pembuatan perintah few-shot dengan GPT-4o-mini itu sendiri. Pemanggilan pengklasifikasi hanya menghabiskan beberapa ratus token masukan—jauh lebih sedikit daripada salah mengarahkan kueri kompleks ke model murah yang menghasilkan jawaban keliru.

CLASSIFIER_SYSTEM = '''You are a query complexity classifier.
Classify the user query as SIMPLE or COMPLEX.
SIMPLE: factual lookup, extraction, classification with clear answer.
COMPLEX: multi-step reasoning, synthesis, comparison, code generation, long-form writing.
Reply with just SIMPLE or COMPLEX.'''

def llm_classify_complexity(query: str) -> str:
    response = client.chat.completions.create(
        model='gpt-4o-mini',  # use cheap model for routing
        messages=[
            {'role': 'system', 'content': CLASSIFIER_SYSTEM},
            {'role': 'user', 'content': query},
        ],
        max_tokens=10,
        temperature=0,
    )
    label = response.choices[0].message.content.strip()
    return POWERFUL_MODEL if label == 'COMPLEX' else CHEAP_MODEL

Melacak Biaya per Fitur

Untuk mengetahui bagian yang perlu diprioritaskan dalam upaya optimisasi, Anda perlu melacak biaya per fitur aplikasi, bukan hanya total pengeluaran. Bungkus setiap pemanggilan LLM dengan label fitur dan akumulasikan biaya token per label. 'search_summarization' mungkin menghabiskan 40 persen anggaran Anda, sementara hanya melayani 5 persen lalu lintas, sehingga menjadi target optimisasi prioritas tinggi. 'user_onboarding' mungkin mahal, tetapi melayani alur bernilai tinggi yang tidak ingin Anda turunkan kualitasnya.

from collections import defaultdict

cost_tracker = defaultdict(lambda: {'prompt_tokens': 0, 'completion_tokens': 0, 'cost_usd': 0.0})

MODEL_PRICING = {
    'gpt-4o-mini': {'input': 0.15 / 1e6, 'output': 0.60 / 1e6},
    'gpt-4o':      {'input': 2.50 / 1e6, 'output': 10.00 / 1e6},
}

def tracked_completion(feature: str, messages: list[dict], model: str = 'gpt-4o-mini') -> str:
    response = client.chat.completions.create(model=model, messages=messages)
    usage = response.usage
    pricing = MODEL_PRICING.get(model, {'input': 0, 'output': 0})
    cost = usage.prompt_tokens * pricing['input'] + usage.completion_tokens * pricing['output']

    cost_tracker[feature]['prompt_tokens'] += usage.prompt_tokens
    cost_tracker[feature]['completion_tokens'] += usage.completion_tokens
    cost_tracker[feature]['cost_usd'] += cost

    return response.choices[0].message.content

def print_cost_report():
    print(f'{"Feature":<30} {"Prompt":<10} {"Completion":<12} {"Cost USD":<12}')
    for feature, stats in sorted(cost_tracker.items(), key=lambda x: -x[1]['cost_usd']):
        print(f'{feature:<30} {stats["prompt_tokens"]:<10} {stats["completion_tokens"]:<12} ${stats["cost_usd"]:.4f}')

Membangun Dasbor Biaya Sederhana

Dasbor biaya praktis menggabungkan data pengeluaran tingkat fitur dan menyediakannya melalui titik akhir HTTP sederhana. Simpan biaya kumulatif di Redis dengan kunci rekapitulasi harian agar Anda dapat melihat tren pengeluaran dari waktu ke waktu. Tambahkan dasbor ini ke alat pengembang internal agar tim dapat melihat dampak biaya dari rilis fitur hampir secara waktu nyata dan mendeteksi pengeluaran tak terkendali sebelum menjadi tagihan besar.

from fastapi import FastAPI
import datetime

app = FastAPI()

async def record_cost(feature: str, model: str, prompt_tokens: int, completion_tokens: int):
    pricing = MODEL_PRICING.get(model, {'input': 0, 'output': 0})
    cost = prompt_tokens * pricing['input'] + completion_tokens * pricing['output']
    today = datetime.date.today().isoformat()
    key = f'cost:{today}:{feature}:{model}'
    await async_r.incrbyfloat(key, cost)
    await async_r.expire(key, 86400 * 30)  # keep 30 days

@app.get('/dashboard/costs')
async def cost_dashboard():
    today = datetime.date.today().isoformat()
    pattern = f'cost:{today}:*'
    costs = {}
    async for key in async_r.scan_iter(match=pattern):
        value = await async_r.get(key)
        parts = key.split(':')
        feature_model = ':'.join(parts[2:])
        costs[feature_model] = float(value or 0)
    return {'date': today, 'costs': costs, 'total': sum(costs.values())}

Peringatan Anggaran Bulanan

Atur peringatan anggaran bulanan untuk mendeteksi lonjakan biaya yang tidak terduga sebelum menjadi tagihan besar. Hitung pengeluaran harian bergulir dari pelacak biaya, proyeksikan hingga akhir bulan, lalu kirimkan peringatan Slack ketika proyeksi tersebut melampaui batas anggaran Anda. Proyeksi sederhana—daily_spend * days_remaining—dapat mendeteksi permintaan tak terkendali sejak awal, meskipun pola aktualnya tidak linear.

import datetime
import httpx

SLACK_WEBHOOK = 'https://hooks.slack.com/services/YOUR/WEBHOOK'
MONTHLY_BUDGET_USD = 500.0

async def check_budget_alert():
    today = datetime.date.today()
    days_in_month = 30
    day_of_month = today.day
    days_remaining = days_in_month - day_of_month

    # Sum today's costs
    today_total = sum(cost_tracker[f]['cost_usd'] for f in cost_tracker)
    avg_daily = today_total  # simplified: just today's spend
    projected_month = avg_daily * days_in_month

    if projected_month > MONTHLY_BUDGET_USD:
        message = (
            f'LLM Budget Alert: Projected monthly spend ${projected_month:.2f} '
            f'exceeds budget ${MONTHLY_BUDGET_USD:.2f}. '
            f'Today spend: ${today_total:.2f}'
        )
        async with httpx.AsyncClient() as client:
            await client.post(SLACK_WEBHOOK, json={'text': message})

Antrean Permintaan untuk Mengelola Batas Laju

Saat lalu lintas melonjak, permintaan mencapai batas laju OpenAI dan gagal dengan 429 Too Many Requests. Antrean permintaan menyangga permintaan masuk dan mengirimkannya dengan laju yang terkendali, sehingga puncak lalu lintas menjadi lebih merata. Gunakan antrean asinkron yang didukung Redis atau perantara pesan seperti RabbitMQ untuk produksi, dan terapkan logika percobaan ulang dengan jeda eksponensial untuk error 429 sementara.

import asyncio
from asyncio import Queue

class RateLimitedLLMClient:
    def __init__(self, requests_per_minute: int = 500):
        self.rpm = requests_per_minute
        self.queue: Queue = Queue(maxsize=1000)
        self.interval = 60.0 / requests_per_minute

    async def start(self):
        asyncio.create_task(self._worker())

    async def _worker(self):
        while True:
            request_fn, future = await self.queue.get()
            try:
                result = await request_fn()
                future.set_result(result)
            except Exception as e:
                future.set_exception(e)
            await asyncio.sleep(self.interval)

    async def submit(self, request_fn) -> str:
        loop = asyncio.get_event_loop()
        future = loop.create_future()
        await self.queue.put((request_fn, future))
        return await future

Menyatukan Semuanya: Tumpukan Optimisasi Biaya

Tumpukan optimisasi biaya LLM yang lengkap bekerja dalam beberapa lapisan: tembolok tepat menghilangkan pemanggilan untuk kueri identik yang berulang, tembolok semantik menghilangkan pemanggilan untuk kueri serupa, tembolok awalan mengurangi biaya masukan untuk semua pemanggilan yang tersisa, perutean model menggunakan model murah untuk kueri sederhana, pemrosesan secara berkelompok menunda pekerjaan yang tidak mendesak dengan potongan harga 50 persen, dan dasbor serta peringatan menjaga agar biaya tetap terlihat dan terkendali. Terapkan semuanya secara bertahap sesuai urutan dampaknya bagi aplikasi Anda.

# Decision framework for cost optimization priority:
#
# 1. Enable prefix caching (free, zero effort, automatic)
# 2. Add exact caching (high hit rate for FAQ/support bots)
# 3. Add model routing (simple heuristics first, ML classifier later)
# 4. Add semantic caching (complex, high ROI for paraphrase-heavy use cases)
# 5. Enable batch API (only for non-real-time pipelines)
# 6. Build cost dashboard (essential for ongoing monitoring)
#
# Typical combined result in a customer support bot:
# Before: $1,000/month
# After step 1-2: $400/month (-60%)
# After step 3-4: $200/month (-50% of remaining)
# After step 5-6: $150/month and visible

Pengalihan Bertingkat Saat Model Murah Gagal

Saat merutekan ke model murah, Anda harus menangani situasi ketika model tersebut menghasilkan jawaban yang tidak memuaskan. Terapkan pemeriksaan kualitas pada keluaran model murah—periksa panjang respons, keberadaan bidang yang diwajibkan, atau jalankan penilaian cepat LLM-sebagai-penilai—lalu beralih secara otomatis ke model kuat jika kualitasnya tidak memadai. Jaring pengaman ini memungkinkan Anda lebih agresif merutekan ke model murah tanpa mempertaruhkan penurunan pengalaman pengguna.

async def routing_with_fallback(messages: list[dict], min_length: int = 50) -> str:
    # Try cheap model first
    cheap_response = await async_client.chat.completions.create(
        model=CHEAP_MODEL, messages=messages, temperature=0.0
    )
    answer = cheap_response.choices[0].message.content

    # Quality check: response too short indicates poor answer
    if len(answer.strip()) < min_length:
        print(f'Cheap model answer too short ({len(answer)} chars), escalating...')
        powerful_response = await async_client.chat.completions.create(
            model=POWERFUL_MODEL, messages=messages, temperature=0.0
        )
        return powerful_response.choices[0].message.content

    return answer

Pemeriksaan Singkat

Uji pemahaman Anda tentang pemrosesan secara berkelompok, perutean model, dan dasbor biaya dari pelajaran ini.

Rangkuman Pelajaran

Dalam pelajaran ini Anda telah mempelajari bahwa API Batch OpenAI memberikan potongan harga 50 persen untuk beban kerja asinkron yang tidak berlangsung secara waktu nyata, perutean model menggunakan model murah seperti GPT-4o-mini untuk tugas sederhana dan model mahal untuk tugas kompleks, serta pelacakan biaya per fitur mengungkap bagian aplikasi yang paling banyak menghabiskan anggaran sehingga Anda dapat memprioritaskan optimisasi secara efektif. Jika digabungkan dengan strategi tembolok dari pelajaran sebelumnya, teknik-teknik ini dapat mengurangi biaya infrastruktur LLM sebesar 60–80 persen. Anda sekarang telah menyelesaikan kursus tembolok dan optimisasi biaya LLM.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Pengelompokan, Perutean Model, dan Dasbor Biaya” gratis?

Ya — teks lengkap “Pengelompokan, Perutean Model, dan Dasbor Biaya” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Engineering Academy, upgrade ke CoddyKit PRO. Kursus AI Engineering Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Pengelompokan, Perutean Model, dan Dasbor Biaya”?

Arahkan permintaan sederhana ke model yang lebih murah seperti GPT-4o-mini dan permintaan kompleks ke GPT-4o, kelompokkan permintaan yang tidak mendesak, lalu buat dasbor biaya yang melacak pengeluar… Kamu berlatih AI Engineering Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai AI Engineering Academy?

Tidak diperlukan pengalaman sebelumnya. AI Engineering Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.

Berapa lama pelajaran “Pengelompokan, Perutean Model, dan Dasbor Biaya” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Engineering Academy ini?

Ya. Setiap pelajaran AI Engineering Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Penyimpanan Singgahan Persis dengan Redis
  2. Penyimpanan Singgahan Semantik dengan Embedding
  3. Penyimpanan Singgahan Awalan Perintah OpenAI
  4. Pengelompokan, Perutean Model, dan Dasbor Biaya
← Kembali ke AI Engineering Academy