Menampilkan sisa kuota token LLM secara real-time pada status bar (seperti Tmux, Waybar, Sketchybar, atau terminal prompt) memiliki tantangan teknis: endpoint manajemen kuota penyedia LLM (Anthropic, OpenAI) menerapkan rate limit ketat. Melakukan kueri langsung tanpa strategi agregasi dapat memicu HTTP 429 Too Many Requests dan mengganggu alur kerja CLI tools seperti Claude Code.
Arsitektur pemantauan kuota LLM ini berfokus pada dua pendekatan utama: Direct Local Polling dengan state file terisolasi, dan Centralized Webhook Proxy menggunakan relay event berbasis push.
Arsitektur 1: Direct Local Polling Adaptif
Pola ini mengeksekusi script ringan secara periodik langsung dari mesin lokal pengguna (via cron daemon atau interval status bar runner). Data kuota disimpan dalam file cache lokal (misalnya /tmp/llm_quota.json) agar widget UI hanya membaca disk I/O tanpa memblokir render loop.
Implementasi Adaptive Polling dengan Fallback Caching
Kode Python berikut mengimplementasikan polling adaptif. Interval request melambat secara otomatis saat kuota aman atau saat mendekati rate limit, serta mengurai header Retry-After ketika terkena limit upstream:
import json
import os
import time
import urllib.request
import urllib.error
CACHE_FILE = "/tmp/llm_quota_cache.json"
MIN_INTERVAL = 30 # Detik saat kuota kritis (< 15%)
MAX_INTERVAL = 300 # Detik saat kuota stabil (> 50%)
def get_cached_data():
if not os.path.exists(CACHE_FILE):
return None
try:
with open(CACHE_FILE, "r") as f:
return json.load(f)
except (IOError, json.JSONDecodeError):
return None
def fetch_upstream_quota(api_key: str):
cached = get_cached_data()
now = time.time()
# Evaluasi TTL dinamis dari cache sebelumnya
if cached:
next_run = cached.get("last_fetch", 0) + cached.get("interval", MIN_INTERVAL)
if now < next_run:
return cached # Gunakan data disk, bypass network call
req = urllib.request.Request(
"https://api.example.com/v1/usage/quota",
headers={"Authorization": f"Bearer {api_key}"}
)
try:
with urllib.request.urlopen(req, timeout=5) as res:
payload = json.loads(res.read().decode("utf-8"))
remaining_ratio = payload.get("tokens_remaining", 0) / payload.get("tokens_total", 1)
# Polling adaptif: makin tipis kuota, makin sering cek
calc_interval = MIN_INTERVAL if remaining_ratio < 0.15 else MAX_INTERVAL
record = {
"tokens_remaining": payload.get("tokens_remaining"),
"last_fetch": now,
"interval": calc_interval,
"status": "ok"
}
except urllib.error.HTTPError as e:
retry_after = int(e.headers.get("Retry-After", MAX_INTERVAL))
record = {
"tokens_remaining": cached.get("tokens_remaining") if cached else 0,
"last_fetch": now,
"interval": retry_after,
"status": f"throttled_{e.code}"
}
except Exception:
# Fallback ke cache sebelumnya jika terjadi timeout/network drop
if cached:
return cached
record = {"tokens_remaining": 0, "last_fetch": now, "interval": 60, "status": "err"}
with open(CACHE_FILE, "w") as f:
json.dump(record, f)
return record
if __name__ == "__main__":
token = os.getenv("LLM_MANAGEMENT_TOKEN", "")
data = fetch_upstream_quota(token)
print(f"{data['tokens_remaining']} tok ({data['status']})")
Arsitektur 2: Centralized Webhook Proxy / Push Relay
Pola ini memindahkan tanggung jawab polling keluar dari mesin pengembang ke server perantara (misal: Cloudflare Worker, micro-service Go, atau container VPS). Klien lokal tidak pernah menyentuh upstream provider API secara langsung.
Server relay bertindak sebagai konsentrator:
- Hanya server perantara yang melakukan poll terjadwal atau menerima webhook push notifikasi kuota dari provider LLM.
- Hasil agregasi disimpan ke memory store (Redis atau Worker KV) dengan cache eviction policy.
- Klien lokal cukup membuka koneksi Server-Sent Events (SSE) atau long-polling ringan ke proxy relay internal tanpa kredensial upstream.
Perbandingan Karakteristik Arsitektur
- API Rate Limit Upstream: Local polling rentan memicu 429 jika developer menjalankan banyak terminal/workspace bersamaan. Webhook Proxy mengonsolidasikan ratusan client menjadi 1 kueri upstream terpusat.
- Biaya Komputasi & Infrastruktur: Local polling bernilai biaya nol (berjalan di localhost). Webhook Proxy membutuhkan server publik beroperasi 24/7 dan public routing URL untuk menerima event webhook.
- Reliabilitas Jaringan: Polling lokal sangat dipengaruhi fluktuasi Wi-Fi/VPN laptop. Webhook Proxy memiliki konektivitas backbone server-to-server yang stabil.
- Kebersihan State Lokal: Local polling meninggalkan state file di
/tmpyang harus dibersihkan manual jika crash. Webhook relay menjaga status bar tetap stateless (cukup consume stream).
Kapan Harus Memilih Masing-Masing Pendekatan?
Pilih Adaptive Local Polling jika:
- Lingkungan kerja adalah mesin tunggal (single developer workstation).
- Anda tidak ingin mengelola atau membiayai infrastruktur backend perantara.
- Upstream API tidak menyediakan webhook out-of-the-box untuk pelacakan sisa kuota (hampir semua penyedia AI hanya menyediakan endpoint REST GET berbasis akun).
- Skenario offline/roaming: data cache terakhir tetap dapat dibaca oleh UI terminal tanpa blocking.
Pilih Webhook Proxy Relay jika:
- Mengelola kuota organisasi untuk tim engineering (mencegah akumulasi request ratusan developer membakar limit manajemen token org).
- Memerlukan notifikasi instan via push event saat kuota mendekati habis tanpa membuang CPU cycle client.
- Keamanan kredensial prioritas tinggi: API key dengan izin billing/manajemen kuota tidak boleh didistribusikan ke laptop developer.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!