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.contentPerutean 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_MODELMelacak 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 futureMenyatukan 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 visiblePengalihan 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 answerPemeriksaan 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
- Penyimpanan Singgahan Persis dengan Redis
- Penyimpanan Singgahan Semantik dengan Embedding
- Penyimpanan Singgahan Awalan Perintah OpenAI
- Pengelompokan, Perutean Model, dan Dasbor Biaya