Sebuah migrasi client OpenAI dapat terlihat selesai setelah dua perubahan konfigurasi: mengganti API key dan mengarahkan SDK ke base URL baru. Permintaan pertama berhasil, bentuk respons terlihat familier, dan pull request tampak siap digabungkan.
Itu membuktikan kompatibilitas antarmuka. Itu tidak membuktikan perilaku produksi.
Bagian yang lebih sulit dari migrasi client OpenAI adalah mempertahankan apa yang terjadi saat trafik menjadi tidak merata: permintaan datang beruntun, prompt membesar, stream berjalan lebih lama dari yang diharapkan, provider mengembalikan 429, atau respons mengalami timeout setelah pekerjaan mungkin sudah dimulai. Jika SDK, aplikasi Anda, dan job queue semuanya melakukan retry secara independen, satu panggilan yang gagal dapat menjadi beberapa percobaan yang hampir bersamaan.
Tutorial ini menunjukkan cara memigrasikan integrasi Python atau TypeScript bergaya OpenAI yang sudah ada ke gateway terpadu sambil membuat perilaku rate-limit dan retry eksplisit. Contohnya menggunakan base URL kompatibel OpenAI dari Flatkey, tetapi metode peninjauannya berlaku untuk migrasi gateway apa pun.
Jawaban singkat: apa yang harus berubah?
Untuk migrasi client OpenAI yang aman, tinjau pengaturan ini secara bersama-sama daripada menganggap base URL sebagai seluruh perubahan.
| Area migrasi | Apa yang ditinjau | Keputusan awal yang aman |
|---|---|---|
| Endpoint API | Base URL dan autentikasi | Ubah melalui environment variables, bukan literal yang tersebar |
| Pemilihan model | Identifier model yang tepat dan parameter yang didukung | Kunci satu model yang sudah diketahui untuk canary |
| Retry SDK | Jumlah retry otomatis dan status code yang dapat diretry | Pilih apakah SDK atau aplikasi Anda yang memiliki retry |
| Retry aplikasi | Backoff, jitter, batas percobaan, dan retry budget | Pertahankan satu pemilik retry dan log setiap percobaan |
| Kontrol RPM | Laju kedatangan request dan ukuran burst | Tambahkan batas concurrency atau antrian sebelum cutover |
| Kontrol TPM | Prompt ditambah token output yang diharapkan | Uji prompt besar yang realistis, bukan hanya smoke test satu baris |
| Timeout | Durasi koneksi, baca, dan total request | Set nilai eksplisit untuk panggilan sinkron dan streaming |
| Observabilitas | Request ID, percobaan, token, latensi, dan hasil akhir | Bandingkan log client dengan log penggunaan gateway |
Jika Anda memerlukan penjelasan di level akronim terlebih dahulu, baca Pembatasan rate LLM dijelaskan: RPM, TPM, dan retry. Panduan ini dimulai dari tempat penjelasan itu berakhir: pada diff migrasi dan rencana pengujian produksi.
Mengapa penggantian base URL diperlukan tetapi belum cukup
Quickstart Flatkey mendokumentasikan perubahan client minimal: pertahankan pola request OpenAI SDK dan set base URL ke https://router.flatkey.ai/v1. Ini juga merekomendasikan memeriksa Usage Logs setelah request agar Anda dapat memverifikasi model, jumlah token, latensi, dan biaya.
Itu adalah smoke test yang benar. Sebuah migrasi client OpenAI untuk produksi memerlukan empat pertanyaan tambahan:
- Apakah SDK secara otomatis me-retry
429, timeout, atau error server? - Apakah ada lapisan lain yang juga me-retry operasi gagal yang sama?
- Apakah concurrency dibatasi oleh request rate, token rate, atau keduanya?
- Bisakah Anda membedakan satu operasi logis dari setiap percobaannya?
Dokumentasi resmi OpenAI Python dan Node SDK saat ini menyatakan bahwa kegagalan tertentu di-retry dua kali secara default, termasuk respons 429, error koneksi, timeout, dan beberapa error server. Kedua SDK menyediakan konfigurasi retry dan timeout. Default tersebut nyaman untuk integrasi langsung, tetapi bisa menjadi amplifikasi yang tidak terlihat ketika kode Anda sendiri sudah menerapkan backoff.
Tujuan migrasi bukan “nonaktifkan semua retry.” Tujuannya adalah “ketahui lapisan mana yang memiliki retry.”
Step 1: inventarisasi setiap lapisan retry sebelum mengubah kode
Mulailah dengan menggambar alur panggilan yang sebenarnya.
tindakan pengguna atau job
-> pembungkus retry aplikasi
-> retry pengiriman antrian
-> retry OpenAI SDK
-> gateway
-> provider
Untuk setiap lapisan, catat:
- Error apa yang memicu percobaan berikutnya.
- Jumlah percobaan maksimum.
- Apakah penundaan menggunakan sleep tetap, exponential backoff, atau jitter.
- Apakah nilai
Retry-Afteryang diberikan server dihormati. - Apakah pengenal operasi yang sama dipertahankan di seluruh percobaan.
- Apakah request yang timeout diasumsikan gagal sebelum pekerjaan apa pun terjadi.
Asumsi terakhir berisiko. Timeout klien hanya memberi tahu Anda bahwa klien berhenti menunggu. Sistem upstream mungkin masih telah menerima atau menyelesaikan request tersebut. Untuk konten yang dihasilkan, retry karenanya dapat menciptakan hasil lain dan request yang dapat ditagih lainnya bahkan ketika aplikasi Anda hanya mengamati satu tugas logis.
Perkirakan amplifikasi kasus terburuk
Misalkan sebuah antrean dapat mengirimkan job tiga kali, pembungkus aplikasi mengizinkan tiga percobaan, dan SDK melakukan panggilan awal plus dua retry. Dalam kasus terburuk, satu job logis dapat memicu:
3 pengiriman antrean × 3 percobaan aplikasi × 3 percobaan SDK = 27 percobaan HTTP
Anda mungkin tidak pernah mencapai angka penuh, tetapi perkalian ini menjelaskan mengapa 429 singkat dapat berubah menjadi badai retry. Tuliskan angka ini dalam review migrasi. Itu membuat default tersembunyi menjadi terlihat.
Step 2: pindahkan pengaturan endpoint ke konfigurasi
Jaga agar diff migrasi tetap dapat dibalik. Jangan mengganti string endpoint di seluruh codebase.
Python before and after
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["LLM_API_KEY"],
base_url=os.environ.get("LLM_BASE_URL", "https://api.openai.com/v1"),
max_retries=0,
timeout=45.0,
)
Untuk canary Flatkey, konfigurasi:
export LLM_API_KEY="$FLATKEY_API_KEY"
export LLM_BASE_URL="https://router.flatkey.ai/v1"
TypeScript before and after
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.LLM_API_KEY,
baseURL: process.env.LLM_BASE_URL ?? "https://api.openai.com/v1",
maxRetries: 0,
timeout: 45_000,
});
Contoh-contoh ini menetapkan retry SDK ke nol karena bagian berikutnya memberikan kepemilikan retry yang eksplisit kepada aplikasi. Jika aplikasi Anda tidak memiliki lapisan retry, Anda dapat mempertahankan retry SDK yang terbatas. Jangan sampai keduanya aktif tanpa sengaja.
Untuk daftar kompatibilitas yang lebih luas, lihat OpenAI Compatible API Gateway: Migration Checklist for Minimal Code Changes.
Step 3: berikan kepemilikan retry yang eksplisit pada satu lapisan
Kebijakan retry yang baik memiliki lima bagian:
- Daftar singkat kegagalan yang dapat di-retry.
- Batas percobaan yang ketat.
- Batas maksimum total waktu retry.
- Exponential backoff dengan jitter.
- Log terstruktur untuk setiap percobaan.
Berikut wrapper Python kecil untuk panggilan chat sinkron:
import random
import time
from openai import APITimeoutError, APIConnectionError, APIStatusError, RateLimitError
RETRYABLE_STATUS_CODES = {408, 409, 429, 500, 502, 503, 504}
def create_chat_with_retry(client, *, model, messages, max_attempts=4):
started_at = time.monotonic()
for attempt in range(1, max_attempts + 1):
try:
return client.chat.completions.create(
model=model,
messages=messages,
)
except (RateLimitError, APITimeoutError, APIConnectionError) as error:
retryable = True
caught_error = error
except APIStatusError as error:
retryable = error.status_code in RETRYABLE_STATUS_CODES
caught_error = error
if not retryable or attempt == max_attempts:
raise caught_error
exponential_delay = min(2 ** (attempt - 1), 16)
jitter = random.uniform(0, 0.5 * exponential_delay)
sleep_seconds = exponential_delay + jitter
print({
"event": "llm_retry",
"attempt": attempt,
"next_delay_seconds": round(sleep_seconds, 2),
"elapsed_seconds": round(time.monotonic() - started_at, 2),
"error_type": type(caught_error).__name__,
})
time.sleep(sleep_seconds)
raise RuntimeError("unreachable")
Anggap ini sebagai titik awal yang dapat ditinjau, bukan kebijakan universal. Dalam produksi, parse dan patuhi header respons Retry-After yang valid sebelum kembali ke delay yang dihitung secara lokal. Tambahkan budget waktu total yang telah berlalu agar retry tidak melebihi latensi yang dapat ditoleransi produk Anda.
Jangan retry setiap error
| Failure | Tindakan default | Alasan |
|---|---|---|
400 invalid request |
Jangan retry tanpa perubahan | Payload harus berubah |
401 authentication |
Jangan retry tanpa perubahan | Key atau header harus berubah |
404 model not found |
Jangan retry tanpa perubahan | Identifier model atau akses harus berubah |
429 rate limit |
Retry dengan delay dan jitter | Kapasitas mungkin menjadi tersedia |
500 or 503 |
Retry dalam budget kecil | Kegagalan mungkin bersifat sementara |
| Client timeout | Retry dengan hati-hati | Permintaan upstream mungkin sudah dieksekusi |
Panduan cepat Flatkey memberikan panduan tingkat tinggi yang sama untuk 429: coba lagi dengan exponential backoff dan jitter. Tambahan khusus migrasi adalah memastikan hanya satu lapisan yang menjalankan kebijakan tersebut.
Langkah 4: sesuaikan concurrency untuk RPM dan TPM
Migrasi client OpenAI dapat mempertahankan sintaks request sambil mengubah kapasitas yang tersedia. RPM dan TPM membatasi workload yang berbeda:
- RPM menjadi bottleneck saat Anda mengirim banyak request kecil.
- TPM menjadi bottleneck saat prompt, output, atau evaluasi paralel berukuran besar.
Gunakan traffic yang teramati, bukan satu rata-rata saja. Kumpulkan setidaknya:
- Request per menit pada median dan puncak.
- Input token pada p50, p95, dan maksimum.
- Output token pada p50 dan p95.
- Durasi request median dan p95.
- Jumlah stream konkuren.
Batas concurrency kasar dapat diperkirakan dari setiap limit:
Concurrency berbasis RPM ≈ (RPM / 60) × rata-rata detik request
Concurrency berbasis TPM ≈ (TPM / rata-rata token per request / 60)
× rata-rata detik request
Gunakan hasil yang lebih rendah sebagai batas awal, lalu sisakan ruang untuk lonjakan dan retry.
Contoh: anggap sebuah route mengizinkan 600 RPM dan 300.000 TPM, request rata-rata menggunakan 1.500 token total, dan durasi rata-rata 3 detik.
Batas RPM: (600 / 60) × 3 = 30 request konkuren
Batas TPM: (300.000 / 1.500 / 60) × 3 = 10 request konkuren
TPM adalah batas yang lebih ketat dalam contoh ini. Memulai pada 30 request konkuren karena RPM terlihat longgar akan menimbulkan respons 429 yang sebenarnya bisa dihindari.
Perhitungan ini bersifat indikatif, bukan jaminan dari provider. Provider dapat menggunakan rolling window, token bucket, batas token input dan output yang terpisah, pool khusus model, atau kontrol akselerasi. Rencana pengujian harus memverifikasi perilaku nyata untuk model dan akun yang dipilih.
Langkah 5: uji perilaku streaming dan timeout secara terpisah
Jangan menganggap panggilan non-streaming yang berhasil sebagai bukti bahwa streaming aman.
Untuk request streaming, uji:
- Waktu ke token pertama.
- Interval hening maksimum antar chunk.
- Timeout pembacaan client.
- Perilaku saat consumer terputus.
- Apakah retry wrapper Anda dapat tanpa sengaja memulai stream kedua.
- Apakah output parsial dipertahankan, dibuang, atau ditampilkan ke pengguna.
Stream yang gagal setelah output parsial tidak setara dengan request yang gagal sebelum ada output sama sekali. Melakukannya retry secara otomatis dapat menampilkan teks ganda atau menghasilkan kelanjutan yang berbeda. Putuskan apakah produk harus retry, meminta konfirmasi pengguna, atau menampilkan hasil parsial.
Ingat juga bahwa timeout SDK dan timeout infrastruktur bisa berbeda. Reverse proxy, platform serverless, job worker, atau koneksi browser dapat berakhir sebelum library client mencapai timeout-nya sendiri. Selama migrasi client OpenAI, catat timeout terkecil dalam seluruh jalur request.
Langkah 6: jalankan matriks canary sebelum traffic yang lebih luas
Gunakan satu model yang dipin dan persentase traffic yang kecil. Canary pertama harus menjawab apakah route baru mempertahankan perilaku, bukan apakah setiap model bekerja.
| Kasus uji | Input | Bukti yang diharapkan |
|---|---|---|
| Autentikasi | Kunci valid dan tidak valid | Sukses plus 401 yang tidak di-retry |
| Validasi model | ID model valid dan salah eja | Sukses plus error model yang tidak di-retry |
| Burst permintaan kecil | Banyak prompt pendek | Antrian terkontrol tanpa lonjakan retry |
| Burst prompt besar | Lebih sedikit prompt dengan token tinggi | Tekanan TPM terlihat dan tetap terbatas |
429 yang dipaksa |
Untuk sementara melebihi batas canary | Satu pemilik retry, penundaan dengan jitter, jumlah percobaan dibatasi |
| Timeout yang dipaksa | Setel timeout client yang sengaja singkat | Timeout tercatat tanpa replay tanpa batas |
| Gangguan streaming | Putus sambungan selama stream | Perilaku output parsial yang eksplisit |
| Error server | Inject atau simulasikan 503 |
Retry terbatas dan pelaporan error final |
| Rollback | Kembalikan base URL sebelumnya | Rollback hanya konfigurasi berhasil |
Untuk setiap operasi logis, catat:
operation_id
attempt_number
base_url_name
model_requested
http_status
input_tokens
output_tokens
latency_ms
retry_delay_ms
final_outcome
Lalu bandingkan log aplikasi dengan Flatkey Usage Logs. Jumlahnya harus masuk akal jika dilihat bersama. Jika satu operasi aplikasi dipetakan ke beberapa request gateway, instrumentasi retry Anda harus menjelaskan alasannya.
Langkah 7: definisikan ambang batas rollout dan rollback
Migrasi client OpenAI harus memiliki kondisi berhenti numerik sebelum canary pertama dimulai.
Contoh ambang batas:
- Rollback jika tingkat error final naik lebih dari persentase poin yang disepakati.
- Jeda jika percobaan per operasi melebihi anggaran retry yang diharapkan.
- Jeda jika latensi p95 melebihi anggaran timeout produk.
- Jeda jika penggunaan token per operasi yang berhasil berubah secara tak terduga.
- Perluas traffic hanya setelah jalur streaming dan non-streaming sama-sama lolos.
Hindari membandingkan hanya hitungan mentah 429. Antrian yang baik dapat mengurangi error final sambil sementara meningkatkan request yang tertunda. Lacak hasil di tingkat percobaan dan di tingkat operasi.
Checklist pull request migrasi
Salin checklist ini ke PR implementasi.
- Base URL dan key berasal dari variabel lingkungan.
- Canary menggunakan pengenal model yang tepat dan terverifikasi.
- Satu lapisan menjadi pemilik retry.
- Default retry SDK didokumentasikan di PR.
- Perilaku
429, timeout, dan5xxmemiliki percobaan yang dibatasi. - Backoff menyertakan jitter dan menghormati
Retry-Aftersaat tersedia. - Batas RPM dan TPM diperkirakan dari traffic yang teramati.
- Streaming memiliki tes kegagalan terpisah.
- Setiap percobaan berbagi satu
operation_idlogis. - Log penggunaan dan log aplikasi dibandingkan.
- Ambang batas rollout dan rollback ditulis sebelum peluncuran.
- Endpoint sebelumnya dapat dipulihkan tanpa perubahan kode tambahan.
Kesalahan migrasi yang umum
Menjaga retry SDK dan retry aplikasi tanpa menghitung totalnya
Ini adalah temuan review yang paling penting. Default tetap menjadi perilaku, bahkan ketika tidak terlihat di fungsi lokal.
Menguji hanya prompt yang sangat kecil
Permintaan satu baris membuktikan kredensial dan kompatibilitas respons. Itu hampir tidak mengatakan apa pun tentang tekanan TPM, batas output, aliran panjang, atau latensi p95.
Mencoba ulang kesalahan autentikasi dan validasi
Backoff tidak dapat memperbaiki kunci yang tidak valid, parameter yang tidak didukung, atau model yang salah eja. Mencoba ulang payload yang tidak diubah membuang kapasitas dan menyembunyikan дефek yang sebenarnya.
Menganggap timeout sebagai bukti bahwa tidak ada permintaan yang berjalan
Client mungkin berhenti menunggu setelah upstream menerima panggilan. Rancang retry dan pencatatan dengan ambiguitas itu dalam pikiran.
Mengubah endpoint, model, prompt, dan kebijakan retry dalam satu rilis
Itu membuat kegagalan sulit diatribusikan. Migrasikan satu bentuk permintaan yang sudah diketahui terlebih dahulu, lalu perluas pilihan model setelah rute dapat diamati.
Definisi yang lebih aman dari “OpenAI-compatible”
Untuk perencanaan migrasi, “OpenAI-compatible” seharusnya berarti pola interaksinya cukup familiar untuk mengurangi perubahan kode. Istilah ini tidak boleh ditafsirkan sebagai janji bahwa setiap provider memiliki kuota, penghitungan token, semantik error, latensi, perilaku streaming, atau dukungan parameter yang identik.
Pembedaan itu membuat migrasi client OpenAI lebih mudah ditinjau. Pertahankan antarmuka yang stabil di tempat yang membantu, tetapi uji kontrak operasional di tempat provider dan rute bisa berbeda.
Flatkey memusatkan akses dan penagihan di balik satu base URL yang kompatibel dengan OpenAI, yang dapat menyederhanakan diff client dan perluasan model di kemudian hari. Pekerjaan engineering-nya tetap untuk membuat retry, throughput, dan observability menjadi eksplisit sebelum traffic produksi berpindah.
Itulah standar yang harus dipenuhi oleh migrasi client OpenAI pada lingkungan produksi: perubahan antarmuka kecil yang didukung oleh bukti operasional yang eksplisit.
Tinjau halaman harga Flatkey saat memilih model untuk canary Anda, lalu setujui migrasi hanya setelah checklist lulus dalam code review dan perilaku rute terlihat di log.
Pertanyaan yang sering diajukan
Apakah saya harus menonaktifkan retry OpenAI SDK selama migrasi?
Nonaktifkan jika aplikasi atau antrian Anda sudah memiliki retry sendiri. Jika tidak ada lapisan lain yang melakukan retry, retry SDK yang dibatasi bisa masuk akal. Aturan pentingnya adalah menghindari beberapa pemilik retry yang independen.
Apa perbedaan antara RPM dan TPM selama migrasi?
RPM membatasi frekuensi request, sedangkan TPM membatasi throughput token. Panggilan kecil dengan frekuensi tinggi dapat terkena RPM terlebih dahulu; prompt atau output yang lebih sedikit tetapi besar dapat terkena TPM terlebih dahulu. Uji kedua bentuk beban kerja.
Apakah 429 harus selalu dicoba ulang?
Hanya dalam retry yang dibatasi dan anggaran latensi. Patuhi Retry-After jika tersedia, jika tidak gunakan exponential backoff dengan jitter. Hentikan jika operasi tidak lagi dapat memenuhi tujuan latensi produk.
Bisakah saya mencoba ulang generasi yang timeout dengan aman?
Tidak dengan kepastian. Permintaan upstream mungkin telah dieksekusi meskipun client mengalami timeout. Perlakukan retry sebagai kemungkinan permintaan duplikat dan catat hubungan antara percobaan.
Apa canary minimum yang aman?
Gunakan satu model yang dipin, satu bentuk request, kepemilikan retry yang eksplisit, batas konkurensi, dan pengujian untuk 429, timeout, gangguan streaming, dan rollback. Bandingkan percobaan di sisi klien dengan log penggunaan gateway sebelum memperluas traffic.



