Zum Inhalt

// integration

Streaming

Gilt für

Produkt: Cloud · Server · Zielgruppe: Entwickler / Integrator

Wie basebox Antworten über die OpenAI-kompatible API streamt (Server-Sent Events), was ein Client verarbeiten muss und wie Reasoning-Inhalte ankommen. Streaming ist der Normalfall für interaktive Anwendungen: Die ersten Tokens erscheinen nach Sekundenbruchteilen statt erst nach der vollständigen Antwort.

Streaming anfordern

Setzen Sie im Request "stream": true:

curl -N -X POST "$BASEBOX_URL/v1/chat/completions" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $BASEBOX_API_TOKEN" \
  -H "X-Realm: $BASEBOX_REALM" \
  -d '{
    "model": "<model-id>",
    "messages": [{"role": "user", "content": "Count to 10 slowly"}],
    "stream": true
  }'

-N schaltet die Ausgabepufferung von curl ab, damit Sie die Chunks sofort sehen.

Das Format

Die Antwort ist ein text/event-stream. Jedes Ereignis ist eine Zeile data: gefolgt von einem JSON-Objekt vom Typ chat.completion.chunk; Ereignisse sind durch Leerzeilen getrennt. Der Stream endet mit data: [DONE].

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"1"},"finish_reason":null}]}

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":" 2"},"finish_reason":null}]}

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: [DONE]

Was ein Client tun muss:

  1. Zeilenweise lesen; Zeilen ohne data:-Präfix und Leerzeilen ignorieren.
  2. [DONE] erkennen und den Stream schließen.
  3. Jeden anderen Payload als JSON parsen und choices[0].delta auswerten.
  4. delta.content in der Reihenfolge des Eintreffens anhängen – so entsteht der Antworttext.
  5. finish_reason beachten: stop (normal beendet), length (Ausgabelimit erreicht), tool_calls (das Modell ruft Werkzeuge auf).

Reasoning-Inhalte

Bei Modellen mit Reasoning und aktiviertem Denkmodus liefert der Stream den Gedankengang getrennt vom Antworttext: Er kommt in einem eigenen Delta-Feld an, bevor die eigentliche content-Tokens beginnen. Behandeln Sie ihn wie die Oberfläche von basebox – als einklappbaren Zwischenschritt, nicht als Teil der Antwort. Speichern oder zeigen Sie ihn nur, wenn Ihr Anwendungsfall das verlangt.

Mehr Reasoning bedeutet mehr Tokens und längere Zeit bis zum ersten Antwort-Token; planen Sie Ihre Timeouts entsprechend. Hintergrund: Reasoning-Aufwand.

Tool Calling im Stream

Ruft das Modell Funktionen auf, kommen die Aufrufe als delta.tool_calls in Fragmenten: erst Name und ID, dann die Argumente stückweise als JSON-String. Sammeln Sie die Fragmente je index, bis finish_reason: "tool_calls" erscheint, führen Sie die Funktion aus und senden Sie das Ergebnis als Nachricht mit role: "tool" in der nächsten Anfrage.

Mit dem OpenAI-SDK

stream = client.chat.completions.create(
    model=model_id,
    messages=[{"role": "user", "content": "Count to 10 slowly"}],
    stream=True,
)
for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.content:
        print(delta.content, end="", flush=True)
print()

Das SDK übernimmt das Parsen der Ereignisse und das Erkennen von [DONE].

Verbindungen und Timeouts

  • Lange Verbindungen sind vorgesehen. Der basebox-Ingress ist auf 24 Stunden Lese-/Schreib-Timeout eingestellt und puffert Streaming-Antworten nicht.
  • Eigene Proxies prüfen. Ein Reverse Proxy oder Corporate Proxy zwischen Ihrem Client und basebox, der Antworten puffert, macht aus dem Stream eine Blockantwort. Pufferung für diesen Pfad abschalten.
  • Client-Timeouts großzügig setzen – Reasoning-Modelle und lange Antworten brauchen Zeit. Setzen Sie eher ein Idle-Timeout (Zeit ohne neuen Chunk) als ein Gesamt-Timeout.
  • Kein Wiederaufsetzen. Bricht ein Stream ab, gibt es keine Fortsetzung ab der letzten Position; senden Sie die Anfrage erneut.
  • Verbindung schließen = Abbruch. Beenden Sie den Stream clientseitig, wenn Nutzer die Antwort stoppen; das spart Tokens.

Fehler im Stream

Fehler vor dem ersten Chunk kommen als normale HTTP-Fehlerantwort (401, 403, 400, 404) – siehe Fehlerbehandlung. Bricht der Stream danach ab, sehen Sie in der Regel ein abruptes Verbindungsende ohne [DONE]; behandeln Sie einen Stream ohne [DONE] als unvollständig.

Häufige Probleme

Symptom Ursache Lösung
Antwort kommt komplett am Ende Pufferung (curl ohne -N, Proxy, Framework) Pufferung abschalten
Stream bricht nach festen Sekunden ab Client- oder Proxy-Timeout Timeouts erhöhen; Idle-Timeout statt Gesamt-Timeout
Text enthält Gedankengang Reasoning-Delta als Content behandelt Felder getrennt auswerten
finish_reason: "length" Ausgabelimit des Modells erreicht Kürzere Antwort anfordern oder Anfrage aufteilen
Leere Deltas Rollen-/Metadaten-Chunks Ignorieren, nur content anhängen

Weiter: Fehlerbehandlung · Benutzerhandbuch