DE ▾

OpenAI Python SDK: Custom base_url – Einrichtung und Fehlerbehebung

Ein Kabel, das von einer Server-Socket-Verbindung zu einer anderen wechselt, zeigt einen base-URL-Wechsel für ein SDK

Die OpenAI-SDKs ermöglichen es dir, den Endpunkt mit einem Argument zu überschreiben. Diese Seite zeigt die genaue Einrichtung der benutzerdefinierten base_url für das OpenAI Python SDK für diese API, plus die Node-Entsprechung, Streaming und die Fehler, die die meisten ersten Aufrufe fehlschlagen lassen.

Zuletzt aktualisiert

Zusammenfassung

  • Setze base_url auf https://api.apicompatible.com/v1 und übergebe deinen Schlüssel als api_key; nichts anderes in deinem Code muss sich ändern.
  • Die Modell-ID ist uncensored. Das Beibehalten eines alten Modellnamens ist der häufigste Grund, warum ein erster Aufruf fehlschlägt.
  • Streaming funktioniert mit stream=True, und jede gestreamte Anfrage belegt einen deiner gleichzeitigen Slots, bis sie endet.
  • Umgebungsvariablen ermöglichen es dir, Endpunkte zu wechseln, ohne den Code zu berühren.

Die kurze Antwort

Erstelle den Client mit zwei Argumenten, base_url und api_key, und nutze weiterhin die Methoden, die du bereits kennst. Die Basis-URL für diese API ist https://api.apicompatible.com/v1, die Modell-ID ist uncensored, und die Authentifizierung ist ein Standard-Bearer-Token, das das SDK aus deinem Schlüssel erstellt.

from openai import OpenAI

client = OpenAI(
    base_url="https://api.apicompatible.com/v1",
    api_key="YOUR_API_KEY",
)

resp = client.chat.completions.create(
    model="uncensored",
    messages=[
        {"role": "system", "content": "You are a concise assistant."},
        {"role": "user", "content": "Name three uses for a hash map."},
    ],
)

print(resp.choices[0].message.content)
print(resp.usage)

Das ist die gesamte Änderung. Das SDK hängt /chat/completions an die Basis-URL an, sodass die Anfrage unter POST /v1/chat/completions eingeht. Wenn du noch keinen Schlüssel hast, erklärt die API-Schlüssel-Seite, wie du dich registrierst und wie das Testguthaben funktioniert.

Einstellen der Basis-URL über Umgebungsvariablen

Das offizielle Python SDK liest OPENAI_API_KEY und OPENAI_BASE_URL aus den Umgebungsvariablen aus, wenn du sie nicht im Code übergibst. Das ist nützlich, wenn dieselbe Anwendung gegen verschiedene Endpunkte in Entwicklung und Produktion läuft, oder wenn ein Drittanbieter-Tool den Client für dich erstellt und dir keine Möglichkeit gibt, Konstruktorenargumente zu bearbeiten.

export OPENAI_BASE_URL="https://api.apicompatible.com/v1"
export OPENAI_API_KEY="YOUR_API_KEY"

python - <<'EOF'
from openai import OpenAI

client = OpenAI()
r = client.chat.completions.create(
    model="uncensored",
    messages=[{"role": "user", "content": "Say hello in five words."}],
)
print(r.choices[0].message.content)
EOF

Explizite Argumente haben Vorrang vor Umgebungsvariablen. Wenn eine Anfrage an den falschen Host geht, prüfe, ob ein anderer Teil deines Codes einen Client mit einer eigenen base_url erstellt, und ob ein .env-Loader läuft, bevor dein Skript die Variablen liest.

Bewahre den Schlüssel außerhalb der Quellcodeverwaltung auf. Ein Schlüssel in einer Umgebungsvariable oder einem Secrets-Manager ist leicht zu rotieren; ein Schlüssel in einer festgeschriebenen Datei ist das nicht.

Die gleiche Änderung in Node

Das Node-Paket verwendet camelCase für dieselbe Option. Alles andere, einschließlich der Methodennamen und der Antwortstruktur, entspricht dem, was du gegen jeden OpenAI-Format-Endpunkt schreiben würdest.

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.apicompatible.com/v1",
  apiKey: process.env.API_KEY,
});

const completion = await client.chat.completions.create({
  model: "uncensored",
  messages: [{ role: "user", content: "Give me a one-line commit message for a typo fix." }],
});

console.log(completion.choices[0].message.content);

Für eine rohe HTTP-Prüfung ohne SDK sendet dieser curl-Aufruf dieselbe Anfrage und ist praktisch, um SDK-Probleme von Schlüsselproblemen zu trennen:

curl https://api.apicompatible.com/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"uncensored","messages":[{"role":"user","content":"ping"}]}'

Streaming, asynchron und Retries

Streaming verwendet Server-Sent Events, und das SDK wandelt sie in einen Iterator um. Überge stream=True und lese die Deltas, während sie eintreffen. Die Token-Anzahl wird am Ende des Streams übermittelt, also behandle Chunks, die keinen Text enthalten, entsprechend.

from openai import OpenAI

client = OpenAI(
    base_url="https://api.apicompatible.com/v1",
    api_key="YOUR_API_KEY",
)

stream = client.chat.completions.create(
    model="uncensored",
    messages=[{"role": "user", "content": "Explain idempotency in two sentences."}],
    stream=True,
)

for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
print()

Der Async-Client nimmt dieselben zwei Argumente an. Ersetze OpenAI durch AsyncOpenAI, füge await hinzu und verwende async for auf Streams.

Zwei Limits sind relevant, wenn du mehr als eine Anfrage gleichzeitig ausführst. Ein Voll-Schlüssel erlaubt 8 parallele Anfragen und 300 Anfragen pro Minute, und ein Test-Schlüssel erlaubt 2 und 60. Eine gestreamte Anfrage behält ihren Parallelitäts-Slot, bis der Stream endet, also verschwendet ein gestoppter Consumer, der den Stream nie leert, einen Slot. Über einem Limit erhältst du HTTP 429 mit dem Fehlercode rate_limited oder concurrency. Das SDK wiederholt fehlgeschlagene Anfragen standardmäßig ein paar Mal, und du kannst das mit max_retries auf dem Client ändern. Ein 429 mit einem Retry-After: 5-Header bedeutet temporäre Überlastung, also ist fünf Sekunden warten die richtige Reaktion.

Timeouts, Client-Wiederverwendung und Debugging der gesendeten Daten

Erstelle den Client einmal und verwende ihn wieder. Jeder Client behält seinen eigenen Verbindungs-Pool, also verschwendet der Aufbau eines neuen Clients für jede Anfrage Zeit und macht Streaming-Code schwerer nachzuvollziehen. Beide untenstehenden Optionen werden im Konstruktor gesetzt und gelten für jeden Aufruf, der über diesen Client erfolgt.

from openai import OpenAI

client = OpenAI(
    base_url="https://api.apicompatible.com/v1",
    api_key="YOUR_API_KEY",
    timeout=60.0,
    max_retries=2,
)

Lange Generierungen können eine Weile dauern, also erzeugt ein sehr kurzes Timeout Fehler, die wie Dienstfehler aussehen. Wähle ein Timeout, das zu deiner längsten erwarteten Antwort passt, und erhöhe es für große Ausgaben.

Wenn du nicht erkennen kannst, welche URL oder welchen Schlüssel eine Anfrage verwendet hat, aktiviere das Debug-Logging des SDK. Neuere Versionen des Python-Pakets lesen eine OPENAI_LOG-Umgebungsvariable, und das Setzen auf debug gibt die Anfragezeile und den Antwortstatus aus. Prüfe die aktuelle SDK-Dokumentation für das genaue Verhalten in deiner Version und entferne die Variable danach, da Logs sensible Daten enthalten können. Der ausgegebene Host sollte api.apicompatible.com sein. Wenn etwas anderes angezeigt wird, überschreibt eine andere Client-Instanz oder eine Umgebungsvariable deine Einstellung.

Eine letzte Gewohnheit, die Zeit spart: Halte die Basis-URL, den Schlüssel und die Modell-ID in einem Konfigurationsmodul. Wenn alle drei an einem Ort leben, wird das Wechseln der Endpunkte zu einer einzelnen Bearbeitung und einer einzelnen Prüfung.

Fehler, die den ersten Aufruf brechen

Die meisten fehlgeschlagenen ersten Aufrufe stammen von einer kurzen Liste von Ursachen. Gehe sie der Reihe nach durch, bevor du den Dienst verdächtigst.

Die Basis-URL enthält /v1 nicht oder hat einen falschen Pfad

Das SDK fügt nur den Endpunktnamen hinzu, also muss die Basis-URL bei /v1 enden. Die Verwendung von https://api.apicompatible.com ohne das Versionssegment oder das Einfügen des vollständigen /v1/chat/completions-Pfad führt normalerweise zu einem Not-Found-Fehler, weil die finale URL falsch endet. Gib client.base_url aus, wenn du unsicher bist, was das SDK aufgelöst hat.

Die Modell-ID ist noch ein Name eines anderen Anbieters

Diese API bedient ein Modell und seine ID ist uncensored. Ein verbliebener Modellname aus einer vorherigen Einrichtung ist eine häufige Fehlerursache, und er ist leicht zu übersehen, wenn der Name in einer Konfigurationsdatei statt im Code steht. Suche dein Projekt nach der alten Zeichenfolge.

Der Schlüssel stammt vom falschen Ort

Ein Schlüssel eines anderen Anbieters funktioniert hier nicht, und umgekehrt gilt das auch. Wenn du sowohl OPENAI_API_KEY als auch ein explizites api_key setzt, wird der explizite Wert verwendet. Prüfe, welcher Wert den Client erreicht hat.

Du rufst einen Endpunkt auf, den diese API nicht anbietet

Die API ist nur Text. Sie bietet /v1/chat/completions, /v1/responses und /v1/models. Es gibt keine Bild-, Audio- oder Embedding-Endpunkte und kein Fine-Tuning, also müssen Codepfade, die diese nutzen, beim ursprünglichen Anbieter bleiben. Die Kosten- und Trade-off-Analyse behandelt, wann diese Aufteilung sinnvoll ist.

Die Payload ist zu groß

Die maximale Anfrage-Body-Größe beträgt 8 MB. Lange Kontexte sind bis zu 100.000 Token insgesamt für Prompt plus Completion in Ordnung, aber Base64-Blobs oder große eingefügte Dateien können zuerst die Body-Limit erreichen.

Prüfung der Verbindung und deines Guthabens

Rufe vor dem Debuggen von Anwendungscode GET /v1/models auf. Eine saubere Liste bedeutet, dass Schlüssel und URL richtig sind. Jede Antwort enthält auch einen X-Balance-USD-Header, mit dem du die Ausgaben ohne separaten Aufruf beobachten kannst. Verwende mit dem Python SDK with_raw_response, um Header zu lesen:

from openai import OpenAI

client = OpenAI(
    base_url="https://api.apicompatible.com/v1",
    api_key="YOUR_API_KEY",
)

raw = client.chat.completions.with_raw_response.create(
    model="uncensored",
    messages=[{"role": "user", "content": "ping"}],
)

print(raw.headers.get("X-Balance-USD"))
print(raw.headers.get("X-Request-Id"))
completion = raw.parse()
print(completion.choices[0].message.content)

Behalte den X-Request-Id-Wert bei Supportanfragen bei, da er die exakte Anfrage identifiziert. Fehlgeschlagene oder abgelehnte Anfragen werden nicht berechnet, also kostet ein Fehler nichts. Die Preise betragen $0,15 pro 1M Input-Token und $0,50 pro 1M Output-Token aus Prepaid-Guthaben; die Preisseite hat die Details und die Dokumentation listet jeden Parameter auf.

Häufige Fragen

Brauche ich ein spezielles SDK, um eine benutzerdefinierte base_url zu verwenden?

Nein. Die Standard OpenAI Python- und Node-Pakete akzeptieren eine base URL-Option. Du änderst diese Option und den Schlüssel und behältst deine bestehenden Aufrufe bei.

Ist es base_url oder baseURL?

Python verwendet base_url und Node verwendet baseURL. Beide verwenden denselben Wert, https://api.apicompatible.com/v1.

Welchen Modellnamen soll ich senden?

Sende uncensored als Modell. Diese API führt ein Modell aus, also gibt es nichts anderes zur Auswahl.

Warum erhalte ich HTTP 429, wenn ich nur wenige Anfragen ausführe?

Ein Test-Schlüssel erlaubt 2 parallele Anfragen, und offene Streams zählen dazu, bis sie enden. Schließe oder beende Streams, oder wechsle zu einem Voll-Schlüssel für 8 parallele Anfragen.

Hole deinen Schlüssel in Sekunden

Melde dich an, kopiere den Token, aktualisiere die Endpunkt-URL. Das ist die gesamte Konfiguration.

Konto eröffnen