Eine OpenAI-Client-Migration kann nach zwei Konfigurationsänderungen bereits abgeschlossen wirken: Ersetzen Sie den API-Schlüssel und verweisen Sie das SDK auf eine neue Base-URL. Die erste Anfrage ist erfolgreich, die Antwortstruktur wirkt vertraut, und der Pull Request scheint bereit zum Merge.
Das beweist die Schnittstellenkompatibilität. Es beweist nicht das Produktionsverhalten.
Der schwierigere Teil einer OpenAI-Client-Migration ist es, zu bewahren, was passiert, wenn der Traffic ungleichmäßig wird: Anfragen kommen in Schüben an, Prompts werden größer, Streams laufen länger als erwartet, ein Anbieter gibt 429 zurück, oder eine Antwort läuft in ein Timeout, nachdem die Arbeit möglicherweise bereits begonnen hat. Wenn das SDK, Ihre Anwendung und eine Job-Queue unabhängig voneinander erneut versuchen, kann ein einziger fehlgeschlagener Aufruf zu mehreren nahezu gleichzeitigen Versuchen werden.
Dieses Tutorial zeigt, wie Sie eine bestehende OpenAI-ähnliche Python- oder TypeScript-Integration auf ein einheitliches Gateway migrieren und dabei das Verhalten bei Rate Limits und Retries explizit machen. Die Beispiele verwenden die OpenAI-kompatible Base-URL von Flatkey, aber die Prüfmethode gilt für jede Gateway-Migration.
Kurze Antwort: Was sollte sich ändern?
Für eine sichere OpenAI-Client-Migration sollten Sie diese Einstellungen gemeinsam überprüfen, statt die Base-URL als die gesamte Änderung zu behandeln.
| Migrationsbereich | Was geprüft werden sollte | Sichere Startentscheidung |
|---|---|---|
| API-Endpunkt | Base-URL und Authentifizierung | Über Umgebungsvariablen ändern, nicht über verstreute Literale |
| Modellauswahl | Exakte Modell-IDs und unterstützte Parameter | Für den Canary einen bekannten Modellnamen fest verdrahten |
| SDK-Retries | Automatische Retry-Anzahl und retryfähige Statuscodes | Entscheiden, ob das SDK oder Ihre Anwendung die Retries verantwortet |
| Anwendungs-Retries | Backoff, Jitter, Versuchslimit und Retry-Budget | Nur einen Retry-Verantwortlichen behalten und jeden Versuch protokollieren |
| RPM-Steuerung | Ankunftsrate der Anfragen und Burst-Größe | Vor dem Cutover ein Concurrency- oder Queue-Limit hinzufügen |
| TPM-Steuerung | Prompt plus erwartete Ausgabe-Tokens | Realistische große Prompts testen, nicht nur einen Smoke-Test mit einer Zeile |
| Timeouts | Verbindungs-, Lese- und gesamte Anfragedauer | Explizite Werte für synchrone und Streaming-Aufrufe setzen |
| Beobachtbarkeit | Request-IDs, Versuche, Tokens, Latenz und Endergebnis | Client-Logs mit Gateway-Usage-Logs vergleichen |
Wenn Sie zuerst die Erklärung auf Akronym-Ebene benötigen, lesen Sie LLM-Rate-Limits erklärt: RPM, TPM und Retries. Dieser Leitfaden setzt dort an, wo diese Erklärung endet: bei der Migrations-Diff und dem Produktions-Testplan.
Warum ein Wechsel der Base-URL notwendig, aber nicht ausreichend ist
Flatkeys Quickstart dokumentiert die minimale Client-Änderung: Behalten Sie das Request-Muster des OpenAI SDK bei und setzen Sie die Base-URL auf https://router.flatkey.ai/v1. Außerdem wird empfohlen, nach der Anfrage die Usage Logs zu prüfen, damit Sie Modell, Token-Anzahl, Latenz und Kosten verifizieren können.
Das ist der richtige Smoke-Test. Eine produktive OpenAI-Client-Migration braucht vier zusätzliche Fragen:
- Retryt das SDK
429-, Timeout- oder Serverfehler automatisch? - Versucht auch eine andere Schicht dieselbe fehlgeschlagene Operation erneut?
- Wird die Parallelität durch Anforderungsrate, Tokenrate oder beides begrenzt?
- Können Sie eine logische Operation von ihren einzelnen Versuchen unterscheiden?
Die offizielle Dokumentation der OpenAI Python- und Node-SDKs sagt derzeit, dass ausgewählte Fehler standardmäßig zweimal erneut versucht werden, einschließlich 429-Antworten, Verbindungsfehlern, Timeouts und einigen Serverfehlern. Beide SDKs bieten Konfigurationsoptionen für Retries und Timeouts. Dieses Standardverhalten ist praktisch für eine direkte Integration, kann aber zu einer unsichtbaren Verstärkung werden, wenn Ihr eigener Code bereits Backoff implementiert.
Das Migrationsziel lautet nicht: „Jeden Retry deaktivieren.“ Das Ziel lautet: „Wissen, welche Schicht für den Retry verantwortlich ist.“
Schritt 1: Alle Retry-Schichten inventarisieren, bevor Sie den Code ändern
Beginnen Sie damit, den tatsächlichen Aufrufpfad zu zeichnen.
Benutzeraktion oder Job
-> Retry-Wrapper der Anwendung
-> Retry der Warteschlangen-Zustellung
-> OpenAI-SDK-Retry
-> Gateway
-> Provider
Erfassen Sie für jede Schicht:
- Welche Fehler einen weiteren Versuch auslösen.
- Die maximale Anzahl an Versuchen.
- Ob die Verzögerung feste Wartezeiten, exponentielles Backoff oder Jitter verwendet.
- Ob ein vom Server bereitgestellter Wert
Retry-Afterberücksichtigt wird. - Ob dieselbe Operations-ID über die Versuche hinweg beibehalten wird.
- Ob bei einem Timeout angenommen wird, dass die Anfrage fehlgeschlagen ist, bevor irgendeine Arbeit ausgeführt wurde.
Die letzte Annahme ist riskant. Ein Client-Timeout sagt nur aus, dass der Client nicht mehr gewartet hat. Das Upstream-System hat die Anfrage möglicherweise dennoch angenommen oder abgeschlossen. Bei generierten Inhalten kann ein Retry daher ein weiteres Ergebnis und eine weitere abrechenbare Anfrage erzeugen, selbst wenn Ihre Anwendung nur eine logische Aufgabe beobachtet hat.
Worst-Case-Verstärkung abschätzen
Angenommen, eine Warteschlange kann einen Job dreimal zustellen, der Anwendungs-Wrapper erlaubt drei Versuche, und das SDK führt den ersten Aufruf plus zwei Retries aus. Im schlimmsten Fall kann ein logischer Job Folgendes auslösen:
3 Warteschlangen-Zustellungen × 3 Anwendungsversuche × 3 SDK-Versuche = 27 HTTP-Versuche
Sie werden diesen Höchstwert möglicherweise nie erreichen, aber die Multiplikation erklärt, warum ein kurzes 429 in eine Retry-Sturm eskalieren kann. Schreiben Sie die Zahl in die Migrationsprüfung. So werden versteckte Standardwerte sichtbar.
Schritt 2: Endpunkt-Einstellungen in die Konfiguration verschieben
Halten Sie den Migrations-Diff reversibel. Ersetzen Sie Endpunkt-Strings nicht überall im Codebase.
Python vorher und nachher
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,
)
Für den Flatkey-Canary konfigurieren Sie:
export LLM_API_KEY="$FLATKEY_API_KEY"
export LLM_BASE_URL="https://router.flatkey.ai/v1"
TypeScript vorher und nachher
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,
});
Diese Beispiele setzen SDK-Wiederholungsversuche auf null, weil der nächste Abschnitt der Anwendung die explizite Verantwortung für Retries überträgt. Wenn Ihre Anwendung keine Retry-Schicht hat, können Sie stattdessen begrenzte SDK-Retries beibehalten. Behalten Sie nicht aus Versehen beides bei.
Für die breitere Kompatibilitäts-Checkliste siehe OpenAI Compatible API Gateway: Migration Checklist for Minimal Code Changes.
Schritt 3: Einer Schicht die explizite Retry-Verantwortung geben
Eine nützliche Retry-Strategie hat fünf Teile:
- Eine kurze Liste retry-fähiger Fehler.
- Eine strikte Obergrenze für Versuche.
- Eine maximale gesamte Retry-Zeit.
- Exponentielles Backoff mit Jitter.
- Strukturierte Logs für jeden Versuch.
Hier ist ein kleiner Python-Wrapper für einen synchronen Chat-Aufruf:
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")
Betrachten Sie dies als überprüfbaren Ausgangspunkt, nicht als universelle Richtlinie. In der Produktion sollten Sie einen gültigen Antwort-Header Retry-After parsen und berücksichtigen, bevor Sie auf die lokal berechnete Verzögerung zurückfallen. Fügen Sie ein Budget für die gesamte verstrichene Zeit hinzu, damit Retries die Latenz, die Ihr Produkt tolerieren kann, nicht überschreiten.
Nicht jeden Fehler erneut versuchen
| Fehler | Standardaktion | Warum |
|---|---|---|
400 ungültige Anfrage |
Unverändert nicht erneut versuchen | Die Nutzlast muss geändert werden |
401 Authentifizierung |
Unverändert nicht erneut versuchen | Der Schlüssel oder Header muss geändert werden |
404 Modell nicht gefunden |
Unverändert nicht erneut versuchen | Die Modellkennung oder der Zugriff muss geändert werden |
429 Ratenlimit |
Mit Verzögerung und Jitter erneut versuchen | Kapazität kann verfügbar werden |
500 oder 503 |
Innerhalb eines kleinen Budgets erneut versuchen | Der Fehler kann vorübergehend sein |
| Client-Timeout | Vorsichtig erneut versuchen | Die vorgelagerte Anfrage wurde möglicherweise bereits ausgeführt |
Flatkeys Schnellstart gibt für 429 dieselbe allgemeine Empfehlung: mit exponentiellem Backoff und Jitter erneut versuchen. Die migrationsspezifische Ergänzung besteht darin, sicherzustellen, dass nur eine Schicht diese Policy ausführt.
Schritt 4: Parallelität für RPM und TPM auslegen
Eine OpenAI-Client-Migration kann die Anfrage-Syntax beibehalten und dennoch das Kapazitätsprofil verändern. RPM und TPM begrenzen unterschiedliche Workloads:
- RPM wird zum Engpass, wenn Sie viele kleine Anfragen senden.
- TPM wird zum Engpass, wenn Prompts, Ausgaben oder parallele Auswertungen groß sind.
Verwenden Sie beobachteten Traffic statt eines einzelnen Durchschnitts. Erfassen Sie mindestens:
- Anfragen pro Minute im Median und am Peak.
- Eingabe-Tokens bei p50, p95 und Maximum.
- Ausgabe-Tokens bei p50 und p95.
- Median und p95 der Anfragedauer.
- Anzahl gleichzeitiger Streams.
Eine grobe Obergrenze für die Parallelität kann aus jedem Limit geschätzt werden:
RPM-basierte Parallelität ≈ (RPM / 60) × durchschnittliche Anfragedauer in Sekunden
TPM-basierte Parallelität ≈ (TPM / durchschnittliche Tokens pro Anfrage / 60)
× durchschnittliche Anfragedauer in Sekunden
Verwenden Sie das niedrigere Ergebnis als anfängliche Obergrenze und lassen Sie dann Spielraum für Spitzen und Wiederholungen.
Beispiel: Angenommen, ein Pfad erlaubt 600 RPM und 300.000 TPM, die durchschnittliche Anfrage verwendet insgesamt 1.500 Tokens und die durchschnittliche Dauer beträgt 3 Sekunden.
RPM-Obergrenze: (600 / 60) × 3 = 30 gleichzeitige Anfragen
TPM-Obergrenze: (300,000 / 1,500 / 60) × 3 = 10 gleichzeitige Anfragen
TPM ist in diesem Beispiel die engere Begrenzung. Mit 30 gleichzeitigen Anfragen zu starten, nur weil RPM großzügig aussieht, würde vermeidbare 429-Antworten verursachen.
Diese Berechnung ist richtungsweisend, keine Garantie des Anbieters. Anbieter können rollierende Fenster, Token-Buckets, getrennte Eingabe- und Ausgabe-Token-Limits, modellspezifische Pools oder Beschleunigungskontrollen verwenden. Der Testplan muss das tatsächliche Verhalten für das ausgewählte Modell und Konto verifizieren.
Schritt 5: Streaming- und Timeout-Verhalten separat testen
Behandeln Sie einen erfolgreichen Non-Streaming-Aufruf nicht als Beweis dafür, dass Streaming sicher ist.
Testen Sie bei Streaming-Anfragen:
- Zeit bis zum ersten Token.
- Maximales stilles Intervall zwischen Chunks.
- Client-Lese-Timeout.
- Verhalten, wenn der Consumer die Verbindung trennt.
- Ob Ihr Retry-Wrap versehentlich einen zweiten Stream starten kann.
- Ob Teilausgaben beibehalten, verworfen oder dem Benutzer angezeigt werden.
Ein Stream, der nach einer Teilausgabe fehlschlägt, ist nicht gleichbedeutend mit einer Anfrage, die fehlschlug, bevor irgendeine Ausgabe erzeugt wurde. Ein automatisches Wiederholen kann doppelten Text anzeigen oder eine andere Fortsetzung erzeugen. Entscheiden Sie, ob das Produkt erneut versuchen, den Benutzer fragen oder das Teilergebnis anzeigen soll.
Denken Sie auch daran, dass SDK-Timeouts und Infrastruktur-Timeouts unterschiedlich sein können. Ein Reverse Proxy, eine Serverless-Plattform, ein Job-Worker oder eine Browserverbindung kann beendet werden, bevor die Client-Bibliothek ihr eigenes Timeout erreicht. Während der OpenAI-Client-Migration sollten Sie das kleinste Timeout im kompletten Anfragepfad erfassen.
Schritt 6: Vor breitflächigem Traffic eine Canary-Matrix ausführen
Verwenden Sie ein fest gepinntes Modell und einen kleinen Prozentsatz des Traffics. Der erste Canary sollte beantworten, ob die neue Route das Verhalten beibehält, nicht ob jedes Modell funktioniert.
| Testfall | Eingabe | Erwarteter Nachweis |
|---|---|---|
| Authentifizierung | Gültige und ungültige Schlüssel | Erfolg plus ein nicht erneut versuchtes 401 |
| Modellvalidierung | Gültige und falsch geschriebene Modell-IDs | Erfolg plus ein nicht erneut versuchter Modellfehler |
| Kleiner Anforderungs-Burst | Viele kurze Prompts | Kontrollierte Queueing ohne Retry-Spike |
| Großer Prompt-Burst | Weniger Prompts mit vielen Tokens | TPM-Druck ist sichtbar und begrenzt |
Erzwungenes 429 |
Canary-Limit vorübergehend überschreiten | Ein Retry-Verantwortlicher, jitterte Verzögerungen, begrenzte Versuche |
| Erzwungener Timeout | Einen absichtlich kurzen Client-Timeout setzen | Protokollierter Timeout ohne unbegrenztes Wiederholen |
| Streaming-Unterbrechung | Während eines Streams trennen | Explizites Verhalten für teilweise Ausgaben |
| Serverfehler | 503 injizieren oder simulieren |
Begrenzte Retries und abschließende Fehlerberichterstattung |
| Rollback | Die vorherige Base-URL wiederherstellen | Rollback nur per Konfiguration gelingt |
Für jede logische Operation protokollieren:
operation_id
attempt_number
base_url_name
model_requested
http_status
input_tokens
output_tokens
latency_ms
retry_delay_ms
final_outcome
Vergleichen Sie dann die Anwendungslogs mit den Flatkey Usage Logs. Die Zählungen sollten zusammen Sinn ergeben. Wenn eine Anwendungsoperation auf mehrere Gateway-Anfragen abgebildet wird, sollte Ihre Retry-Instrumentierung erklären, warum.
Schritt 7: Rollout- und Rollback-Schwellen definieren
Eine OpenAI-Client-Migration sollte numerische Stoppbedingungen haben, bevor der erste Canary startet.
Beispielschwellen:
- Rollback, wenn die finale Fehlerrate um mehr als einen vereinbarten Prozentpunkt steigt.
- Pause, wenn die Versuche pro Operation das erwartete Retry-Budget überschreiten.
- Pause, wenn die p95-Latenz das Timeout-Budget des Produkts überschreitet.
- Pause, wenn sich der Tokenverbrauch pro erfolgreicher Operation unerwartet ändert.
- Traffic erst ausweiten, nachdem sowohl Streaming- als auch Nicht-Streaming-Pfade bestanden haben.
Vermeiden Sie den Vergleich nur roher 429-Zahlen. Eine gute Queue kann finale Fehler reduzieren, während sie vorübergehend die Zahl verzögerter Anfragen erhöht. Verfolgen Sie sowohl Ergebnisse auf Versuchsebene als auch auf Operationsebene.
Checkliste für den Migrations-Pull-Request
Kopieren Sie diese Checkliste in den Implementierungs-PR.
- Base-URL und Schlüssel stammen aus Umgebungsvariablen.
- Der Canary verwendet eine exakte, verifizierte Modellkennung.
- Eine Ebene ist für Retries verantwortlich.
- SDK-Standardwerte für Retries sind im PR dokumentiert.
-
429, Timeout- und5xx-Verhalten haben begrenzte Versuche. - Backoff enthält Jitter und respektiert
Retry-After, wenn vorhanden. - RPM- und TPM-Grenzen werden aus dem beobachteten Traffic geschätzt.
- Streaming hat einen separaten Fehler-Test.
- Jeder Versuch teilt sich eine gemeinsame logische
operation_id. - Usage Logs und Anwendungslogs werden verglichen.
- Rollout- und Rollback-Schwellen sind vor dem Start festgelegt.
- Der vorherige Endpoint kann ohne weitere Codeänderung wiederhergestellt werden.
Häufige Migrationsfehler
SDK-Retries und Anwendungs-Retries beibehalten, ohne die Gesamtsumme zu berechnen
Dies ist der wichtigste Befund der Überprüfung. Standardwerte sind weiterhin Verhalten, selbst wenn sie in der lokalen Funktion nicht sichtbar sind.
Nur einen winzigen Prompt testen
Eine einzeilige Anfrage belegt Anmeldedaten und Antwortkompatibilität. Sie sagt fast nichts über TPM-Druck, Ausgabegrenzen, lange Streams oder p95-Latenz aus.
Authentifizierungs- und Validierungsfehler erneut versuchen
Backoff kann einen ungültigen Schlüssel, einen nicht unterstützten Parameter oder ein falsch geschriebenes Modell nicht reparieren. Unveränderte Payloads erneut zu versuchen verschwendet Kapazität und verdeckt den eigentlichen Defekt.
Ein Timeout als Beweis dafür behandeln, dass keine Anfrage ausgeführt wurde
Der Client kann aufhören zu warten, nachdem der Upstream den Aufruf angenommen hat. Entwerfen Sie Wiederholungen und Abrechnung mit dieser Unklarheit im Hinterkopf.
Endpoint, Modelle, Prompts und Retry-Policy in einem Release ändern
Das macht Fehler schwer zuzuordnen. Migrieren Sie zuerst eine bekannte Request-Form, und erweitern Sie dann die Modellauswahl, nachdem die Route beobachtbar ist.
Eine sicherere Definition von „OpenAI-kompatibel“
Für die Migrationsplanung sollte „OpenAI-kompatibel“ bedeuten, dass das Interaktionsmuster vertraut genug ist, um Codeänderungen zu reduzieren. Es sollte nicht als Versprechen verstanden werden, dass jeder Anbieter identische Kontingente, Token-Zählung, Fehlersemantik, Latenz, Streaming-Verhalten oder Parameterunterstützung bietet.
Diese Unterscheidung macht eine OpenAI-Client-Migration einfacher zu prüfen. Behalten Sie die stabile Schnittstelle dort bei, wo es hilft, aber testen Sie den operativen Vertrag dort, wo Anbieter und Routen sich unterscheiden können.
Flatkey zentralisiert Zugriff und Abrechnung hinter einer einzigen OpenAI-kompatiblen Base-URL, was den Client-Diff und spätere Modellerweiterungen vereinfachen kann. Die technische Arbeit besteht weiterhin darin, Retries, Durchsatz und Beobachtbarkeit vor dem Wechsel des Produktivverkehrs explizit zu machen.
Das ist der Standard, den eine produktive OpenAI-Client-Migration erfüllen sollte: eine kleine Schnittstellenänderung, gestützt durch explizite operative Nachweise.
Sehen Sie sich die Flatkey-Preisseite an, wenn Sie die Modelle für Ihren Canary auswählen, und genehmigen Sie die Migration erst, nachdem die Checkliste im Code Review bestanden hat und das Routenverhalten in den Logs sichtbar ist.
Häufig gestellte Fragen
Sollte ich OpenAI-SDK-Retries während der Migration deaktivieren?
Deaktivieren Sie sie, wenn Ihre Anwendung oder Warteschlange bereits Retries übernimmt. Wenn keine andere Schicht erneut versucht, können begrenzte SDK-Retries angemessen sein. Die wichtige Regel ist, mehrere unabhängige Retry-Verantwortliche zu vermeiden.
Was ist der Unterschied zwischen RPM und TPM während einer Migration?
RPM begrenzt die Anfragefrequenz, während TPM den Token-Durchsatz begrenzt. Kleine, häufige Aufrufe können zuerst an RPM stoßen; weniger große Prompts oder Ausgaben können zuerst an TPM stoßen. Testen Sie beide Workload-Formen.
Soll ein 429 immer erneut versucht werden?
Nur innerhalb eines begrenzten Retry- und Latenzbudgets. Beachten Sie Retry-After, wenn verfügbar, andernfalls verwenden Sie exponentielles Backoff mit Jitter. Stoppen Sie, wenn der Vorgang das Latenzziel des Produkts nicht mehr einhalten kann.
Kann ich eine zeitüberschrittene Generierung sicher erneut versuchen?
Nicht mit Sicherheit. Die Upstream-Anfrage kann ausgeführt worden sein, obwohl der Client ein Timeout hatte. Behandeln Sie den Retry als mögliche Doppelanfrage und protokollieren Sie den Zusammenhang zwischen den Versuchen.
Was ist der minimale sichere Canary?
Verwenden Sie ein fest gepinntes Modell, eine Anforderungsform, eine explizite Zuständigkeit für Retries, ein Limit für die Parallelität und Tests für 429, Timeout, Streaming-Unterbrechung und Rollback. Vergleichen Sie clientseitige Versuche mit den Nutzungsprotokollen des Gateways, bevor Sie den Traffic ausweiten.



