← Semua tulisan

API Kompatibel OpenAI yang Drop-In — Migrasi dalam Dua Baris

20 Agu 2026 · 5 menit baca · api, migration

unbleep adalah API yang kompatibel dengan OpenAI, yang dalam praktiknya berarti migrasinya hanya dua baris dan tanpa dependensi baru. Anda tetap memakai SDK resmi, logika retry Anda, loop streaming Anda, penghitungan token Anda, dan handler error Anda. Yang berubah hanyalah ke mana request dikirim dan key mana yang mengautentikasinya. Tulisan ini membahas proses penggantiannya, lalu empat hal yang cukup berbeda sehingga bisa merusak sesuatu kalau Anda tidak mengetahuinya.

Migrasi ke API kompatibel OpenAI dalam dua baris

python
import os

from openai import OpenAI

client = OpenAI(
    base_url="https://unbleep.ai/v1",
    api_key=os.environ["UNBLEEP_API_KEY"],
)

resp = client.chat.completions.create(
    model="unbleep",
    messages=[{"role": "user", "content": "Summarise this incident report."}],
)
print(resp.choices[0].message.content)

Kalau Anda lebih memilih tidak menyentuh kode sama sekali, SDK membaca kedua nilai itu dari environment, jadi perubahan konfigurasi saja sudah cukup:

bash
export OPENAI_BASE_URL="https://unbleep.ai/v1"
export OPENAI_API_KEY="ub_live_9f2c..."

Pasangan yang sama itu mencakup sebagian besar ekosistem yang dibangun di atas SDK — LangChain, LlamaIndex, Instructor, Vercel AI SDK, apa pun yang menyediakan pengaturan base URL. Key diberi prefix agar kebocorannya langsung terlihat oleh secret scanner: ub_live_ dan ub_test_ sama-sama ditagihkan ke kredit prabayar yang sama dengan tarif per token yang sama. Test key adalah kredensial terpisah yang bisa dicabut, dengan batas yang lebih rendah — 15 request/menit alih-alih 60 milik akun — bukan tier gratis. Simpan keduanya di sisi server.

GET /v1/models berfungsi, jadi tooling yang mengenumerasi model untuk mengisi dropdown tidak perlu penanganan khusus.

Memilih model

Ada tiga tier. Id bertanggal — unbleep-250811, unbleep-high-250811, unbleep-mini-250811 — diterima sebagai alias, tetapi saat ini semuanya mengarah ke build yang sama dengan id polosnya, dan respons melaporkan kembali id polos tersebut. Anggap id bertanggal sebagai ejaan yang siap untuk masa depan, bukan jaminan reproduksibilitas; jika sebuah evaluasi harus bisa diulang, catat keluarannya, bukan id modelnya.

| Model | Konteks | Harga masuk / keluar per 1M | Catatan | | --- | --- | --- | --- | | unbleep | 256K | $3.00 / $3.00 | Default. Tier penalaran. | | unbleep-high | 1M* | $5.00 / $5.00 | Pekerjaan terbesar. Tier penalaran. | | unbleep-mini | 32K | $1.00 / $1.00 | Murah dan cepat. Menjawab langsung, tanpa jejak penalaran. |

*Body request dibatasi 2.000.000 byte — kira-kira 500k token — jadi satu panggilan tidak benar-benar bisa mengisi jendela 1M; yang lebih besar dari itu dikembalikan sebagai 413 payload_too_large.

Batas 32K pada unbleep-mini adalah yang paling sering menjebak orang yang bermigrasi dari model berkonteks 128K: prompt yang tadinya muat sekarang akan ditolak. Kalau Anda me-routing berdasarkan biaya, lakukan routing berdasarkan panjang juga.

python
def pick_model(prompt_chars: int) -> str:
    """~4 chars/token is a deliberate under-estimate; leave room for the completion."""
    est_tokens = prompt_chars // 4
    if est_tokens < 24_000:
        return "unbleep-mini"
    return "unbleep" if est_tokens < 200_000 else "unbleep-high"

Streaming

Set stream=True dan Anda mendapat Server-Sent Events standar: setiap event adalah chat.completion.chunk yang membawa delta, dan stream diakhiri dengan literal data: [DONE]. Loop yang sudah Anda punya berjalan tanpa perubahan.

bash
curl -N https://unbleep.ai/v1/chat/completions \
  -H "Authorization: Bearer $UNBLEEP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "unbleep",
    "messages": [{"role": "user", "content": "Explain the residual stream."}],
    "stream": true,
    "stream_options": {"include_usage": true}
  }'

Anda mendapat hitungan token baik diminta maupun tidak: unbleep selalu meminta usage dari backend dan meneruskannya, dan hanya stream_options: {"include_usage": false} yang eksplisit yang akan mencabutnya dalam perjalanan keluar. Bagaimanapun, stream diakhiri dengan satu chunk terakhir yang array choices-nya kosong — membawa objek usage yang terisi kecuali Anda memilih keluar — itulah sebabnya loop di bawah memeriksa choices sebelum menyentuhnya.

Field reasoning_content

Inilah satu-satunya tambahan sejati pada skema. unbleep dan unbleep-high berpikir sebelum menjawab, dan rantai pemikiran itu dikembalikan di reasoning_content, field yang bersanding dengan content pada message (non-streaming) atau pada delta (streaming). Backend hulu tidak sepakat apakah menamainya reasoning atau reasoning_content; API menormalkannya menjadi reasoning_content sehingga Anda hanya perlu menangani satu bentuk.

Karena bukan bagian dari skema OpenAI, field ini tidak ada di type stub SDK. Model respons mengizinkan field tambahan, jadi akses atribut berfungsi saat runtime — tetapi bacalah dengan getattr agar respons dari mini, yang tidak punya jejak penalaran, tidak melempar error:

python
import sys

stream = client.chat.completions.create(
    model="unbleep",
    messages=[{"role": "user", "content": "Why did this detection rule misfire?"}],
    stream=True,
    stream_options={"include_usage": True},
)

usage = None
for chunk in stream:
    if not chunk.choices:          # final usage-only chunk
        usage = chunk.usage
        continue
    delta = chunk.choices[0].delta
    thought = getattr(delta, "reasoning_content", None)
    if thought:                    # trace to stderr, answer to stdout
        sys.stderr.write(thought)
    if delta.content:
        sys.stdout.write(delta.content)

if usage:
    details = usage.completion_tokens_details
    print(f"\nreasoning tokens: {getattr(details, 'reasoning_tokens', 0)}")

Tiga konsekuensi praktis:

python
resp = client.chat.completions.create(
    model="unbleep",
    messages=[{"role": "user", "content": "phishing or benign?"}],
    max_tokens=4,
    extra_body={"thinking": False},   # spend the budget on the answer, not the trace
)

Jangan pernah memasukkan reasoning_content kembali ke giliran berikutnya sebagai konten assistant. Itu adalah keluaran diagnostik, bukan riwayat percakapan, dan memutarnya ulang akan menurunkan kualitas respons berikutnya.

Error dan dua jebakan yang sungguhan

Error memakai amplop (envelope) OpenAI — {"error": {"type", "code", "message"}} — jadi blok except yang sudah ada tetap berfungsi. Kode statusnya sesuai dugaan: 401 key salah, 422 diblokir oleh policy: strict, 429 rate limit, 5xx masalah upstream yang bisa dicoba ulang.

Status yang mungkin belum pernah Anda tangani adalah 402, kredit habis. Akun bersifat prabayar, jadi tidak ada overage dan tidak ada invoice — request berhenti begitu saja sampai Anda mengisi ulang. OpenAI menandai kuota habis sebagai 429, yang berarti jalur migrasi yang naif akan membuat logika backoff Anda mencoba ulang 402 selamanya. Perlakukan status ini sebagai terminal dan pasang alert untuknya.

Jebakan kedua: system_fingerprint tidak dikembalikan. Field itu mengidentifikasi backend penyaji, jadi dibuang bersama field vendor lainnya. Jika Anda mengandalkannya sebagai kunci cache atau pemeriksaan reproduksibilitas, Anda perlu penanda versi sendiri: id model bertanggal adalah alias untuk build saat ini, bukan snapshot beku, jadi tidak akan memberi tahu Anda ketika backend berubah.

Rate limit dikembalikan sebagai header di setiap respons — x-ratelimit-limit-requests, x-ratelimit-remaining-requests, x-ratelimit-reset-requests — sehingga batch job bisa mengatur laju request-nya alih-alih menemukan batas itu dengan menabraknya. Ada batas kedua yang tidak dijelaskan oleh header: maksimal 8 request yang berjalan bersamaan per akun, dan request kesembilan dikembalikan 429 dengan kode too_many_concurrent_requests. Panggilan streaming menahan slotnya sampai stream berakhir, jadi batasi worker pool Anda sendiri di angka 8.

Apa yang sedang Anda tuju

Perlu ditegaskan: model di balik endpoint ini adalah model abliterated, artinya perilaku penolakannya telah dihilangkan di tingkat bobot. Itulah intinya — ini adalah API developer yang ditujukan untuk riset keamanan, red-teaming, dan evaluasi, di mana penolakan adalah galat pengukuran. Itu juga berarti guardrail yang biasa tidak ada di sini untuk menangkap prompt yang buruk, jadi pastikan ada manusia yang bertanggung jawab atas keluarannya dan bacalah kebijakan penggunaan. Penggunaan yang sah adalah tanggung jawab Anda.

Dapatkan API key — migrasinya sungguh cuma dua baris.