Was Kompatibilität tatsächlich verspricht
Eine OpenAI-kompatible API akzeptiert dieselben HTTP-Anfragen, die die OpenAI-SDKs senden. Du änderst die Base URL und den Schlüssel, und der Client funktioniert weiter. Dieses Versprechen gilt auf Protokollebene: der Pfad /v1/chat/completions, ein Bearer-Token im Authorization-Header, ein JSON-Body mit model und messages sowie eine Antwort mit choices und usage. Streaming folgt demselben SSE-Muster.
Es verspricht nicht dasselbe Modell, dasselbe Verhalten, dieselben Limits oder denselben Satz von Endpunkten. Das Unternehmen hinter der Original-API entscheidet, was es ausliefert, und jeder andere Anbieter entscheidet unabhängig, was er kopiert. Betrachte Kompatibilität als Möglichkeit, deinen Client-Code nicht neu schreiben zu müssen, nicht als Garantie, dass sich sonst nichts ändert.
Die Unterschiede im Vergleich
Die Tabelle listet die Bereiche auf, die sich zwischen Anbietern unterscheiden, und was für diese API gilt. Die rechte Spalte ist eine Aufforderung zu eigenen Tests, wenn du einen Dienst bewertest.
| Bereich | Diese API | Was du bei jedem Anbieter prüfen solltest |
|---|---|---|
| Modell-IDs | Eine ID: uncensored | Ob dein alter Modellname akzeptiert, gemappt oder abgelehnt wird |
| Endpunkte | /v1/chat/completions, /v1/responses, /v1/models | Ob jeder Endpunkt, den dein Code aufruft, existiert |
| Modalitäten | Nur Text | Unterstützung für Bilder, Audio und Video, falls benötigt |
| Embeddings, Fine-Tuning | Nicht angeboten | Wohin diese Aufrufe stattdessen geleitet werden |
| Kontextfenster | 100.000 Token, Prompt plus Vervollständigung | Ob das Limit nur Input oder beides abdeckt |
| Concurrency und Ratenlimit | Vollständiger Schlüssel: 8 gleichzeitig, 300 pro Minute. Test-Schlüssel: 2 gleichzeitig, 60 pro Minute | Wie Limits gemessen werden und wie eine Ablehnung gemeldet wird |
| Tool Calling, JSON-Modus | Unterstützt | Randfälle wie Tool-Aufrufe im Streaming |
| Inhaltsverhalten | Abgestimmt darauf, ohne Inhaltsablehnungen für legale Erwachsenennutzung zu antworten | Moderationsschichten, die beeinflussen, was das Modell zurückgibt |
| Abrechnung | Prepaid-Guthaben, pro Token, kein Abonnement | Mindestmengen, Ablauf, Abonnementstufen |
Die Preiszeile für diese API beträgt $0,15 pro 1M Input-Token und $0,50 pro 1M Output-Token. Lies bei jedem anderen Dienst die aktuelle Preisliste, statt dich auf Erinnerungen oder Drittanbieter-Zusammenfassungen zu verlassen.
Modell-IDs und Verhalten
Der größte praktische Unterschied ist das Modell selbst. Bei OpenAI wählst du aus einem Menü benannter Modelle. Hier sendest du "model": "uncensored" und erhältst ein einzelnes Open-Weight-Modell eines unabhängigen Anbieters. Es ist nicht die offizielle API eines Modellherstellers und kein Router, der Anfragen an mehrere Anbieter weiterleitet.
Das hat zwei Konsequenzen. Erstens kannst du keine A/B-Tests von Modellgrößen durchführen, indem du eine Zeichenfolge änderst; du führst ein Modell aus und passt Prompts und Sampling daran an. Zweitens müssen Prompts, die für ein anderes Modell geschrieben wurden, möglicherweise geringfügig bearbeitet werden, da Befolgungsverhalten, Formatierungsgewohnheiten und Ablehnungsverhalten unterschiedlich sind. Dieses Modell ist darauf abgestimmt, ohne Inhaltsfilter für die rechtmäßige Nutzung durch Erwachsene zu antworten, daher können Prompts mit langen Sicherheitseinleitungen, die für ein strengeres Modell geschrieben wurden, oft gekürzt werden.
Eine harte Grenze ändert sich nicht: kein sexueller Inhalt mit Minderjährigen.
Endpunkte und Funktionen, die nicht vorhanden sind
Kompatibilität ist selten über die gesamte OpenAI-Oberfläche hinweg vollständig. Hier sind die Lücken bewusst: Der Dienst verarbeitet nur Text und sonst nichts.
- Keine Bild-, Audio- oder Videoerstellung.
- Kein Embedding-Endpunkt, daher benötigt eine Retrieval-Pipeline einen separaten Embedding-Anbieter.
- Kein Fine-Tuning.
Das Vorhandene deckt die meisten Chat-Anwendungen ab: POST /v1/chat/completions, POST /v1/responses, Streaming, Function Calling mit tools und tool_choice sowie JSON-Modus über response_format. Sampling-Steuerungen wie temperature, top_p, stop, seed und die Strafen werden an das Modell durchgereicht.
Wenn deine Anwendung mehrere Funktionen kombiniert, ist das übliche Muster, den ursprünglichen Anbieter für Embeddings und Bilder beizubehalten und nur die Textgenerierung, die unzensiert sein soll, an die neue Base URL zu senden. Die Kosten- und Abwägungsanalyse funktioniert durch diese Aufteilung.
Limits, Fehler und Header
Grenzwerte sind der Punkt, an dem Migrationen Menschen überraschen, weil sie bestimmen, wie dein Code unter Last reagieren sollte. Diese API legt 8 gleichzeitige Anfragen und 300 Anfragen pro Minute für einen vollständigen Schlüssel fest, 2 und 60 für einen Test-Schlüssel sowie eine maximale Body-Größe von 8 MB. Eine Anfrage, die darüber hinausgeht, antwortet mit HTTP 429. Der Fehlercode sagt dir, welches Limit du überschritten hast: rate_limited für Anfragen pro Minute, concurrency für zu viele Anfragen gleichzeitig. Eine temporäre Überlastung gibt ebenfalls 429 zurück und fügt Retry-After: 5 hinzu.
Lies den Code und den Header, nicht nur den Status. Das erneute Senden eines concurrency-Fehlers sofort verschlechtert die Situation, während eine kurze Wartezeit sie löst. Eine gestreamte Anfrage belegt ihren Slot bis zum Ende des Streams, daher zählt Concurrency offene Streams, nicht nur laufende Aufrufe.
Responses enthalten X-Request-Id, X-Balance-USD, X-RateLimit-Limit-Requests und X-RateLimit-Limit-Concurrency. Der Balance-Header ist ein anbieterspezifischer Zusatz: OpenAI-SDK-Code ignoriert ihn, aber du kannst ihn lesen, um Ausgaben zu verfolgen. Der Saldo ist auch über GET /v1/balance und das OpenAI-Style-GET /v1/dashboard/billing/credit_grants verfügbar.
Migrations-Checkliste
Wenn du eine Anwendung zwischen Anbietern wechselst, gehe jedes Mal dieselbe kurze Liste durch. So fängst du die meisten Überraschungen ab, bevor die Nutzer sie bemerken.
- Ersetze Base URL, Schlüssel und Modell-ID gemeinsam und suche im Repository nach alten Modellnamen, die in Konfigurationsdateien versteckt sind.
- Entferne Aufrufe an Endpunkte, die auf der neuen Seite nicht existieren, und leite sie zu dem Anbieter weiter, der sie hat.
- Führe deinen Prompt-Satz aus und vergleiche die Ausgaben. Erwarte andere Formulierungen und Formatierungen von einem anderen Modell.
- Teste Streaming durch jeden Proxy und Lastverteiler zwischen deinen Nutzern und der API.
- Füge Retry-Logik für 429 hinzu, die den Fehlercode und den Retry-After-Header liest.
- Logge die Token-Nutzung pro Anfrage, damit Kostenüberraschungen in Tagen, nicht erst am Monatsende auffallen.
Ein schneller Kompatibilitätstest
Vertraue einer Feature-Liste, einschließlich dieser, nicht. Führe die Aufrufe aus, die deine Anwendung macht, und vergleiche die Ergebnisse. Ein kurzes Skript, das die Teile auslastet, von denen du abhängst, dauert nur wenige Minuten:
from openai import OpenAI
client = OpenAI(
base_url="https://api.apicompatible.com/v1",
api_key="YOUR_API_KEY",
)
# 1. Plain completion
r = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Reply with the word ready."}],
temperature=0,
seed=7,
)
print("plain:", r.choices[0].message.content)
# 2. JSON mode
j = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Return a JSON object with keys name and age for a fictional person."}],
response_format={"type": "json_object"},
)
print("json:", j.choices[0].message.content)
# 3. Streaming
chunks = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Count from one to five."}],
stream=True,
)
print("stream:", "".join(c.choices[0].delta.content or "" for c in chunks if c.choices))
Füge einen Fall für Function Calling hinzu, wenn dein Code Funktionen verwendet, und einen Fall für lange Kontexte, der nahe an deinen echten Prompt-Größen liegt. Details zu jedem Parameter findest du in der Dokumentation, und die API-Schlüssel-Seite zeigt, wie du das $0,50 Testguthaben beanspruchen kannst, das für diese Art von Test mehr als ausreichend ist.
