spicyapiDokumentation
Text und Chat
Hauptinhalt

Von OpenAI oder OpenRouter migrieren

OpenAI-Bibliotheken mit SpicyAPI verbinden: Basis-URL, Key und Modell-ID ändern, Feldunterschiede beachten und OpenRouter-Zusätze entfernen.

Ruft Ihr Code bereits ein Chatmodell über offizielle OpenAI-Bibliotheken oder ein Werkzeug mit „OpenAI-kompatibel“-Einstellung auf, ändern Sie für SpicyAPI drei Dinge: Basis-URL, API-Key und Modell-ID. Diese Seite nennt die Änderungen und abweichendes Verhalten, damit die Migration nicht mit unerwartetem 400 endet. Vollständige Programme finden Sie unter Chatbeispiele.

Die drei Änderungen

EinstellungWert bei SpicyAPI
Basis-URLhttps://api.spicyapi.ai/v1
API-KeySpicyAPI-Key mit sk-spicy-, als Authorization: Bearer gesendet
ModellExakte Textmodell-ID aus Livekatalog, etwa in SPICY_MODEL, siehe Modell-IDs
import os
from openai import OpenAI

# Before: client = OpenAI()   (reads OPENAI_API_KEY, calls api.openai.com)
client = OpenAI(api_key=os.environ["SPICY_API_KEY"], base_url="https://api.spicyapi.ai/v1")

reply = client.chat.completions.create(
    model=os.environ["SPICY_MODEL"],
    messages=[{"role": "user", "content": "Say hello in one sentence."}],
)
print(reply.choices[0].message.content)

OpenAI-Bibliotheken lesen auch OPENAI_BASE_URL und OPENAI_API_KEY aus der Umgebung. Damit kann bestehender Code unverändert laufen; allerdings werden alle übrigen OpenAI-Aufrufe desselben Prozesses ebenfalls umgeleitet. Bevorzugen Sie deshalb ausdrückliche Übergabe wie oben.

Modell-IDs

Textmodell-IDs haben das Format publisher/model/chat. Kopieren Sie sie aus dem Livekatalog, statt bekannte Namen anderer Dienste zu übertragen:

  • GET /api/v1/models?modality=text listet nur Textmodelle mit Preisen und ergänzt mit includeSchema=1 deren inputSchema. Siehe Modellkatalog und Schemas.
  • GET /v1/models ist die von Werkzeugen gelesene OpenAI-Liste. Ohne Filter enthält sie Bild-, Video- und Audiomodelle, die unter /v1/chat/completions nicht aufrufbar sind. Ergänzen Sie ?modality=text für ausschließlich Text. Neben vier OpenAI-Feldern enthält jeder Eintrag modality und task; Chatmodelle zusätzlich context_length, max_output_tokens und supported_parameters, die akzeptierten Anfragefelder. OpenAI-Bibliotheken ignorieren Zusatzfelder.

Nicht existierende IDs liefern 404 mit code: "model_not_found" und param: "model". Die Meldung nennt das ID-Format und, sofern vorhanden, das nächstähnliche aufrufbare Chatmodell. Bild- oder Videomodell an Chatendpunkt liefert 400 mit Hinweis, dass es kein Chatmodell ist. IDs anderer Dienste können ähnlich aussehen, sind aber nicht austauschbar: Herstellernamen unterscheiden sich, Suffixe wie :free existieren hier nicht und Textmodelle enden mit /chat.

Anfragefelder

Jedes Modell veröffentlicht akzeptierte Felder in inputSchema und als Namen in supported_parameters unter /v1/models.

  • Nicht gelistete Sampling-Felder werden ignoriert. temperature, top_p, top_k, min_p, top_a, frequency_penalty, presence_penalty und repetition_penalty beeinflussen nur Zufälligkeit oder Wiederholung. Viele Clients senden sie standardmäßig; Modelle ohne Unterstützung generieren einfach ohne sie. Dasselbe gilt für n: 1, leeres stop, stop ohne modellseitige Stopsequenzen und reasoning_effort ohne Denkstufen. Ignorierte Felder nennt der Antwortheader X-Spicy-Ignored-Params, etwa frequency_penalty, presence_penalty.
  • Nicht akzeptierte Werte werden zum nächsten erlaubten Wert geändert. Sampling außerhalb des Modellbereichs wird auf die Grenze begrenzt, eine zu lange stop-Liste auf die ersten erlaubten Einträge gekürzt, und nicht angebotene reasoning_effort-Stufen werden zur nächstliegenden verfügbaren Stufe, bei Gleichstand zur niedrigeren. Änderungen stehen als name=value in X-Spicy-Adjusted-Params, etwa reasoning_effort=low, temperature=1.
  • Alle anderen nicht gelisteten Felder werden abgelehnt, mit 400, code: "unsupported_parameter", dem Feld unter param und konkreter Meldung, etwa logprobs: is not a supported field. Diese Felder verändern das Ergebnis; Sie bezahlen daher nicht für eine Antwort, die Ihre vermeintlich aktive Option nicht verwendete.
FeldBei SpicyAPI
messagesGleiche Struktur; Rollen system, developer, user, assistant, tool. Text überall; image_url-Teile nur bei Modellen, deren Schema sie aufführt
max_tokens, max_completion_tokensBeide mit gleicher Bedeutung akzeptiert. Denktokens zählen mit; Standard und Maximum je Modell
stream, stream_optionsUnterstützt mit OpenAI-Verbrauchsregeln: Stream enthält Verbrauch nur bei include_usage gleich true, siehe Antworten und Streams
tools, tool_choiceBei jedem Textmodell unterstützt. Manche erlauben nur auto und none für tool_choice; erzwungenes benanntes Werkzeug ergibt dort 400
parallel_tool_callsNur bei explizit gelisteten Modellen
reasoning_effortBei meisten Modellen, aber Werte unterscheiden sich: Manche bieten none, minimal, xhigh, max, manche kein medium. Nicht angebotene Stufe wird zur nächstliegenden geändert; lesen Sie für exakte Stufe enum
temperature, top_p, top_k, frequency_penalty, presence_penaltyBei gelisteten Modellen genutzt und auf Bereich begrenzt; sonst ignoriert und in X-Spicy-Ignored-Params genannt. Mehrere Modelle unterstützen keine Sampling-Felder
seedNur bei gelisteten Modellen
stopBei gelisteten Modellen genutzt und auf maximale Anzahl gekürzt; bei fehlender Stopsequenz-Unterstützung oder leerer Liste ignoriert
response_formatjson_object bei Modellen mit diesem Feld; sonst nicht verfügbar
user, metadata, storeAkzeptiert und ignoriert
n1 ignoriert; andere Werte bei Modellen ohne dieses Feld mit 400 abgelehnt
logprobs, top_logprobs, logit_bias und andere nicht gelistete FelderMit 400 abgelehnt

Prüfen Sie vor dem Senden Felder und Werte mit dem Befehl unter Chatbeispiele: Vor dem Start.

Antworten und Streams

Eine nicht gestreamte Antwort ist ein normales chat.completion-Objekt; reply.choices[0].message.content und reply.usage funktionieren wie bisher. Unterschiede sind gering:

  • reasoning_content. Denkende Modelle liefern Denktext in message.reasoning_content, beim Streaming in delta.reasoning_content, neben content. Er zählt bereits zu usage.completion_tokens.
  • ID entspricht Anfrage-ID. id hat das Format chatcmpl-req_...; Antwortheader x-request-id enthält denselben req_...-Wert. Nennen Sie ihn beim Support. Ein zweiter Header X-Spicy-Task-Id bezeichnet den Task mit der Belastung, siehe Kosten und Verbrauch.
  • Kein system_fingerprint und keine logprobs.

Streams verwenden dieselben chat.completion.chunk-Ereignisse, enden mit data: [DONE] und folgen OpenAI-Verbrauchsregeln:

  • Verbrauch nur auf Anforderung. Ohne stream_options.include_usage enthält kein Chunk usage; alle haben nicht leere choices. Mit "include_usage": true erscheint direkt vor [DONE] ein zusätzlicher Chunk mit leerem choices und endgültigem usage; alle anderen enthalten usage: null. Code aus OpenAI-Streamingbeispielen funktioniert unverändert. Prüfen Sie choices vor Zugriff auf choices[0], um den letzten Chunk sicher zu behandeln.
  • Ein finish_reason je Auswahl. Jede Auswahl endet unabhängig vom Modell mit genau einem Chunk mit finish_reason.
  • Keep-alive-Zeilen. Während Modellnachdenken hält : keep-alive als Kommentar die Verbindung offen. OpenAI-Bibliotheken überspringen diese; eigene Parser müssen das ebenfalls.

Streamen Sie lange Antworten oder hohen reasoning_effort. Nicht gestreamte Anfragen über etwa 30 Sekunden bleiben durch Leerraum vor JSON und X-Spicy-Keepalive: 1 offen, sodass OpenAI-Bibliotheken sie weiter parsen. Scheitern sie danach, kommt das Fehlerobjekt jedoch im Inhalt einer 200-Antwort, die Bibliotheken nicht als Fehler auslösen. Siehe Timeouts und Streaming.

Fehler

Fehler verwenden die OpenAI-Struktur {"error": {"message", "type", "param", "code"}} mit üblichen HTTP-Statuscodes. Die Bibliotheken lösen ihre gewohnten Exceptions aus. param benennt das Feld als Punktpfad wie temperature oder messages.1.content.0. code unterscheidet gleiche Status: unsupported_parameter für nicht akzeptiertes Feld oder Nachrichtenteil, invalid_request für fehlendes Feld oder nicht akzeptierten Wert, content_rejected für Inhaltsablehnung ebenfalls mit 400 und model_not_found mit 404. Anders als OpenAI verwendet SpicyAPI 402, wenn Guthaben oder Ausgabenlimit die Anfrage nicht deckt. Vollständige Tabelle mit Maßnahmen unter Chatbeispiele: Fehlerbehebung.

OpenAI-Bibliotheken wiederholen 429 und 5xx selbst. Das ist hier sicher: Fehlgeschlagene Anfragen werden nicht berechnet. Senden Sie Idempotency-Key je Aufruf und lesen vorher Idempotenzschlüssel für Textendpunkte.

Kosten und Verbrauch

Antworten nennen Tokenzahlen in usage, keinen Preis. Eingabe, Cacheeingabe und Ausgabe werden je Million Tokens bepreist; Preise stehen auf Modellseite und im Katalog. Für tatsächliche Kosten lesen Sie den bei jeder angenommenen Anfrage mit oder ohne Stream vorhandenen Antwortheader X-Spicy-Task-Id (job_…) und fragen GET /api/v1/jobs/recordInfo?taskId=<job_…> ab: cost ist endgültig bei settled gleich true. Einträge in GET /api/v1/jobs enthalten auch die requestId des erstellenden Aufrufs aus X-Request-Id; Konsole → Logs zeigt dieselben Tasks. Headerlesen mit OpenAI-Bibliotheken unter Chatbeispiele: Aufrufkosten ermitteln; außerdem Preisabfragen und Abrechnung.

Vor Ausführung wird ein Betrag für Nachrichten plus vollständige Ausgabe-max_tokens, bei Weglassen Modellstandard, reserviert. Berechnet wird nur Nutzung, aber die Reservierung muss zunächst gedeckt sein. Kleines Guthaben mit großem max_tokens liefert daher 402. Setzen Sie realistische max_tokens oder Key-Ausgabenlimits; siehe Abrechnung.

Hier nicht verfügbare Endpunkte

Textgenerierung bietet OpenAI Chat Completions, OpenAI Responses, Anthropic Messages und Google Gemini. Details unter Text und Streaming. Diese OpenAI-Endpunkte existieren nicht und liefern 404: /v1/embeddings, veraltetes /v1/completions, /v1/images/*, /v1/audio/*, /v1/moderations, /v1/files, /v1/batches, /v1/assistants und Fine-Tuning. Bild-, Video- und Audiomodelle verwenden stattdessen die Task-API, Videos zusätzlich /v1/videos.

Von OpenRouter wechseln

Auch OpenRouter nutzt OpenAI-Format. Die drei Änderungen gelten daher ebenfalls: Basis-URL https://openrouter.ai/api/v1 durch https://api.spicyapi.ai/v1 ersetzen, Key und Modell-IDs austauschen. Entfernen Sie dann OpenRouter-spezifische Felder, die hier 400 liefern:

OpenRouter-FeldMaßnahme
models als Ausweichliste und routeEntfernen. Eine Modell-ID senden; SpicyAPI bestimmt die Ausführung
providerEntfernen. Keine Auswahl des ausführenden Dienstes je Anfrage
reasoning, etwa {"effort": "high"}Wird zu oberstem reasoning_effort; enabled: false wird zu none, sofern modellseitig verfügbar. Andere Objektschlüssel werden ignoriert. Direktes reasoning_effort ist klarer
usage mit {"include": true}Entfernen. Nicht gestreamte Antworten enthalten immer usage; bei Stream stream_options: {"include_usage": true} senden
transforms, pluginsEntfernen

Header HTTP-Referer und X-Title sind unschädlich und werden ignoriert.

Checkliste

  1. Basis-URL https://api.spicyapi.ai/v1 und SpicyAPI-Key.
  2. Modell-ID aus Livekatalog mit /chat am Ende.
  3. Anfragefelder gegen Modell-inputSchema geprüft; nicht unterstützte Nicht-Sampling-Felder entfernt, Antwortheader X-Spicy-Ignored-Params und X-Spicy-Adjusted-Params einmal auf Änderungen geprüft.
  4. Bei stream_options.include_usage überspringt die Schleife den letzten Chunk mit leerem choices.
  5. Realistisches max_tokens oder Modellstandard, ergänzt um Key-Ausgabenlimits.
  6. Lange oder aufwendige Denkanfragen verwenden stream: true.

Weiterlesen

Chatbeispiele · Text und Streaming · Modellkatalog und Schemas · Authentifizierung · Abrechnung

Auf dieser Seite