Die Doubao API bietet eine OpenAI-kompatible Schnittstelle, aber „kompatibel“ bedeutet nicht „einfach abschreiben“. Die drei häufigsten Stolperstellen sind: Die Base URL wird fälschlich als /v1 geschrieben, model enthält den Anzeigenamen statt der Modell-ID oder Endpoint-ID, und beim ersten Aufruf wird bereits Deep Thinking aktiviert, wodurch die Ausgabe abgeschnitten wird. Dieser Artikel führt curl und Python der Reihe nach durch und behandelt anschließend Streaming, Tool-Aufrufe, häufige Fehler und eine Migrationscheckliste.

Hinweis: Doubao, Volcengine Ark, Volcengine und ByteDance sind Marken oder Produktnamen von ByteDance und verbundenen Unternehmen; OpenAI ist eine Marke ihres jeweiligen Inhabers. Dieser Artikel dient nur der technischen Einführung; es besteht keine Zugehörigkeit, Vertretung oder Empfehlung gegenüber den genannten Unternehmen. Schnittstellen, Modelle und Kontingente können sich ändern; maßgeblich sind die offizielle Dokumentation und unsere Modellpreise.

1. Drei Dinge vor dem Start klären

Punkt Direktverbindung zu Volcengine Ark Einheitliches Gateway
Base URL https://ark.cn-beijing.volces.com/api/v3 https://ai.zhongshangqihang.com/v1
Authentifizierung Authorization: Bearer <ARK_API_KEY> Authorization: Bearer <Gateway-Key>
model Modell-ID oder ep--Endpoint-ID Laut Modellliste im Gateway
Geeignet für Nur Doubao, eigene Identitätsprüfung und Rechnungsstellung Mehrere Modelle, einheitliche Abrechnung und Kontingente

Key und Base URL müssen als Paar verwendet werden. Ein offizieller Key mit Gateway-Adresse oder ein Gateway-Key mit offizieller Adresse führt meist direkt zu 401. Beim Wechsel des Zugangs müssen beide gemeinsam getauscht werden.

2. Base URL und Anfragepfad: /api/v3, nicht /v1

Die offizielle Datenadresse lautet https://ark.cn-beijing.volces.com/api/v3, der Chat-Pfad /chat/completions, die vollständige Adresse https://ark.cn-beijing.volces.com/api/v3/chat/completions. Sie hat kein bei OpenAI übliches /v1-Präfix; ein zusätzliches /v1 führt zu 404.

Die Region steht in der Domain (cn-beijing). Liegen Ressourcen in einer anderen Region, gilt die in Konsole und Dokumentation genannte Adresse. Die offizielle Dokumentation weist außerdem darauf hin, dass etwa bei einem Coding Plan eine andere Base URL verwendet wird und eine falsche Angabe zusätzliche Kosten verursachen kann. Prüfen Sie dies vor einem Tarifwechsel.

3. Was in model gehört: Modell-ID oder Endpoint-ID

Die offizielle Dokumentation nennt zwei Aufrufarten:

  • Voreingestellte Inferenz: Direkt die Modell-ID eintragen, etwa doubao-seed-2-1-pro-260915; ein vorher angelegter Endpoint ist nicht nötig.
  • Benutzerdefinierter Inferenz-Endpoint: Die Endpoint-ID eintragen, meist beginnend mit ep-. Geeignet für feste Bereitstellungen, fein abgestimmte Verwaltung oder LoRA-Modelle.

Modell-IDs enthalten ein Versionsdatum. Schreiben Sie keine Anzeigenamen wie „Doubao 2.1 Pro“ und ergänzen Sie keine Suffixe aus dem Gedächtnis. Bei Signatur mit Access Key (AK/SK) muss model die Endpoint-ID enthalten; bei einem API Key kann laut Dokumentation die Modell-ID oder die Endpoint-ID verwendet werden. Kommt InvalidEndpointOrModel.ModelIDAccessDisabled zurück, unterstützt das aktuelle Konto den direkten Modell-ID-Aufruf nicht und es muss ein Endpoint angelegt werden.

4. Minimaler Aufruf mit curl

Deaktivieren Sie zuerst Deep Thinking, um Variablen zu reduzieren. Beispiel für den offiziellen Zugang:

export ARK_API_KEY="IHR_VOLCENGINE_ARK_API_KEY"
export ARK_MODEL_ID="doubao-seed-2-1-pro-260915"

curl "https://ark.cn-beijing.volces.com/api/v3/chat/completions" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "'"$ARK_MODEL_ID"'",
    "messages": [{"role": "user", "content": "Antworte nur mit OK"}],
    "thinking": {"type": "disabled"},
    "max_tokens": 32
  }'

Wenn 200 zurückkommt und choices[0].message.content Inhalt enthält, stimmen Key, Adresse und Modell. Bei 404 prüfen Sie zuerst, ob model das Versionssuffix enthält oder ob stattdessen ein ep--Endpoint nötig ist. Bei 401 prüfen Sie Key und Header und verdächtigen Sie nicht zuerst das Guthaben.

5. Aufruf mit dem OpenAI SDK in Python

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["ARK_API_KEY"],
    base_url="https://ark.cn-beijing.volces.com/api/v3",
)

resp = client.chat.completions.create(
    model=os.environ.get("ARK_MODEL_ID", "doubao-seed-2-1-pro-260915"),
    messages=[
        {"role": "system", "content": "Du bist ein technischer Assistent. Antworte knapp."},
        {"role": "user", "content": "Erkläre in drei Sätzen, was ein Inferenz-Endpoint ist."},
    ],
    max_tokens=512,
    extra_body={"thinking": {"type": "disabled"}},
)

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

Das OpenAI SDK kennt das Feld thinking nicht und überträgt es daher über extra_body; wenn das Gateway oder Modell es nicht unterstützt, entfernen Sie das Feld. Prüfen Sie nach dem ersten erfolgreichen Aufruf die Eingabe- und Ausgabe-Tokens in usage und legen Sie danach Timeout, Parallelität und Kostenbudget fest.

6. Streaming: delta, reasoning_content und [DONE]

Mit stream=True gibt der Server über SSE blockweise Daten zurück. Das Antwortobjekt ist chat.completion.chunk, der Text steht in choices[0].delta.content, der Denkinhalt in delta.reasoning_content. finish_reason erscheint nur im letzten Chunk; am Ende wird data: [DONE] gesendet.

stream = client.chat.completions.create(
    model=os.environ["ARK_MODEL_ID"],
    messages=[{"role": "user", "content": "Schreibe ein Python-Beispiel zum Einlesen einer CSV-Datei."}],
    stream=True,
    stream_options={"include_usage": True},
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

Denkblöcke können einen leeren content haben; nehmen Sie nicht an, dass jeder Chunk Text enthält. Ein zu kleines max_tokens schneidet die Ausgabe ab. Bei einer Netzwerkunterbrechung bleiben bereits empfangene Inhalte erhalten; der Client sollte Teilresultate speichern und entscheiden, ob er erneut versucht.

7. Tool-Aufrufe: tools, tool_calls und Rückgabereihenfolge

tools wird ähnlich wie bei OpenAI geschrieben: Jedes Tool enthält type: "function" und function, wobei name, description und parameters Pflicht sind; parameters verwendet JSON Schema. Entscheidet sich das Modell für einen Aufruf, ist finish_reason gleich tool_calls, und message.tool_calls[i].function.arguments ist ein JSON-String, der selbst geparst werden muss.

Die Rückgabereihenfolge muss stimmen: Zuerst die Assistant-Nachricht mit tool_calls in den Dialog aufnehmen, dann für jeden Aufruf eine Nachricht mit role: "tool" ergänzen, inklusive passender tool_call_id und Ergebnis, und anschließend erneut das Modell aufrufen, bis finish_reason nicht mehr tool_calls ist. parallel_tool_calls ist standardmäßig true; mit false lässt sich auf einen Tool-Aufruf pro Runde begrenzen. Im Streaming tragen Tool-Aufruf-Deltas einen index; arguments müssen nach index akkumuliert werden.

8. Häufige Fehler: 401, 404 und 429 lokalisieren

HTTP Typischer Fehlercode Bedeutung Behandlung
401 AuthenticationError Key fehlt, ungültig oder Header ohne Bearer Key erneut kopieren, Authorization-Header prüfen
404 InvalidEndpointOrModel.NotFound Modell oder Endpoint existiert nicht oder der Workspace hat keine Berechtigung Vollständige ID aus der Konsole kopieren, Region und Workspace prüfen
404 ModelNotOpen Modell ist im Konto nicht freigeschaltet Modell in der Ark-Konsole freischalten
404 InvalidEndpointOrModel.ModelIDAccessDisabled Konto unterstützt direkten Modell-ID-Aufruf nicht Benutzerdefinierten Endpoint anlegen und ep--ID verwenden
400 InvalidParameter, MissingParameter Parameter fehlt, falscher Typ oder vom Modell nicht unterstützt Laut Dokumentation Felder anpassen, zuerst minimale Anfrage senden
403 AccessDenied, AccountOverdueError Keine Berechtigung oder negatives Guthaben Key- und Workspace-Rechte prüfen, Zahlungsrückstand klären
429 RateLimitExceeded.* RPM/TPM überschritten oder Verkehrsspitze Parallelität senken, exponentielle Backoff, bei Bedarf Erhöhung beantragen
500/503 InternalServiceError, ServerOverloaded Upstream-Fehler oder Überlastung Kurz warten, dann wiederholen; Ausweichkanal vorbereiten

9. Migrationscheckliste

Beim Wechsel von der Direktverbindung zu einem Gateway oder zwischen Gateways in dieser Reihenfolge prüfen:

  1. Eine feste Charge echter Prompts zusammenstellen und aktuelle Ausgaben, Laufzeit und usage als Vergleichsbasis erfassen.
  2. base_url und api_key gemeinsam tauschen, nicht nur eines von beiden.
  3. Modellnamen-Zuordnung anhand der Modellpreise neu bestätigen; keine alten Namen weiterverwenden.
  4. Streaming prüfen: Time to First Token, delta.content, finish_reason und [DONE].
  5. Tool-Aufrufe prüfen: tools, tool_calls, tool_call_id-Rückgabe und Reihenfolge über mehrere Runden.
  6. Prüfen, ob Erweiterungsparameter wie thinking und reasoning_effort unterstützt werden und ob Standardwerte abweichen.
  7. Verbindungs- und Lese-Timeout setzen; nur bei 429, 5xx und Timeouts wiederholen; Schreibvorgänge idempotent gestalten.
  8. Zuerst 5–10 % des Verkehrs umstellen, 3–7 Tage beobachten und die offizielle Direktverbindung als Rollback-Kanal behalten.

Für einen einheitlichen Zugang können Sie auf der Registrierungsseite einen Test-Key erstellen; Modellabdeckung und Abrechnungsregeln stehen in den Modellpreisen. Das ZSQH AI Gateway ist ein unabhängiger Drittanbieter und steht in keiner Verbindung zu ByteDance.

Weiterlesen:

Häufige Fragen

Muss die Base URL /v1 enthalten?

Nein. Der OpenAI-kompatible Zugang von Volcengine Ark lautet https://ark.cn-beijing.volces.com/api/v3, der Chat-Pfad /chat/completions; ein zusätzliches /v1 führt zu 404. Gateway-Adressen enden üblicherweise auf /v1; beides darf nicht vermischt werden.

Gehört in model die Modell-ID oder eine mit ep- beginnende Endpoint-ID?

Bei voreingestellter Inferenz die Modell-ID, bei benutzerdefinierten Endpoints die ep--ID; bei Signatur mit Access Key ist zwingend die Endpoint-ID nötig. Kommt ModelIDAccessDisabled zurück, muss ein Endpoint angelegt werden, nicht der Key geändert werden.

Sollte Deep Thinking beim ersten Aufruf aktiv sein?

Empfohlen ist zunächst „aus“, um mit der kürzesten Anfrage die Verbindung zu bestätigen. Einige Doubao-Modelle aktivieren Deep Thinking standardmäßig; dabei entsteht zuerst Denkinhalt, und ein zu kleines max_tokens schneidet den eigentlichen Text leicht ab. Erst nach Bestätigung der Verbindung je nach Aufgabe aktivieren.

Warum enthält das Streaming keine Inhalte?

Prüfen Sie zuerst, ob stream=True gesetzt ist, und dann, ob nur delta.content gelesen wird, während leere Blöcke ignoriert werden; Denkinhalt steht in delta.reasoning_content. Prüfen Sie außerdem max_tokens, Netzwerkpuffer und ob ein Proxy die SSE-Daten zu einer einmaligen Antwort zusammengefasst hat.

Warum muss der assistant-tool_calls zurückgegeben werden?

Das Protokoll verlangt, dass die Assistant-Nachricht tool_calls enthält und jede role: "tool"-Nachricht das Ergebnis über tool_call_id zuordnet. Wird dieser Schritt übersprungen, ruft das Modell das Tool möglicherweise erneut auf oder gibt direkt 400 zurück. Beim Streaming müssen Parameter nach index akkumuliert werden.