Streaming
Setzen Sie "stream": true, und derselbe Endpunkt liefert die Antwort schrittweise über Server-Sent Events, statt darauf zu warten, dass alles fertig ist.
Warum streamen
Eine Anfrage ohne Streaming blockiert, bis das Modell die gesamte Antwort fertig generiert hat, und gibt dann alles auf einmal zurück. Bei einer kurzen Antwort fällt das kaum auf. Bei einer längeren bedeutet es, mehrere Sekunden (manchmal länger) auf nichts zu starren, bevor überhaupt Text erscheint. Streaming behebt das, indem es die Antwort Stück für Stück sendet, sobald das Modell sie produziert, sodass ein Client innerhalb eines Bruchteils einer Sekunde nach dem Absenden der Anfrage mit dem Rendern von Text beginnen kann, statt auf das Ganze zu warten. Das ist der Unterschied zwischen einer Chat-Oberfläche, die sich augenblicklich anfühlt, und einer, die bei jeder Nachricht zu hängen scheint. Es ist optional und kostet bei der Nutzung nichts extra.
Aktivieren
{
"model": "tai-4.1",
"messages": [{"role": "user", "content": "1'den 5'e kadar say"}],
"stream": true
}
Der Content-Type der Antwort wird zu text/event-stream statt application/json. Jede Ereigniszeile beginnt mit dem Präfix data: , und die Verbindung bleibt offen, wobei pro neuem Textabschnitt ein Ereignis gesendet wird, bis der Stream mit einer wörtlichen Zeile data: [DONE] endet.
Der Aufbau eines Chunks
Die meisten Chunks tragen ein kleines Stück neu generierten Text in choices[0].delta.content:
data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [{"index": 0, "delta": {"content": "1"}, "finish_reason": null}]}
data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [{"index": 0, "delta": {"content": ", 2"}, "finish_reason": null}]}
Verkettet man jeden delta.content-Wert der Reihe nach, über alle Chunks hinweg, ergibt sich der vollständige Antworttext. Diese Verkettung aufzubauen ist Aufgabe des Clients; die API sendet zu keinem Zeitpunkt den bereits angesammelten Text, sondern nur das inkrementelle Stück, das jeder Chunk hinzufügt.
Der Finish-Chunk
Der letzte Chunk mit Inhalt trägt ein leeres delta und einen echten finish_reason ("stop", oder "tool_calls", wenn das Modell darum bittet, ein Tool aufzurufen, siehe Tool Calling):
data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [{"index": 0, "delta": {}, "finish_reason": "stop"}]}
Der Usage-Chunk
Nach dem Finish-Chunk wird noch ein weiterer Chunk mit einem leeren choices-Array und einem befüllten usage-Objekt gesendet, im selben Format wie das usage-Feld der Antwort ohne Streaming:
data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [], "usage": {"prompt_tokens": 2, "completion_tokens": 3, "total_tokens": 5}}
data: [DONE]
Ein Client, dem nur der sichtbare Text wichtig ist, kann jeden Chunk mit leerem choices-Array gefahrlos ignorieren; ein Client, der die Token-Nutzung oder geschätzte Kosten im Nachhinein anzeigen möchte, sollte gezielt nach diesem Chunk suchen, statt anzunehmen, dass der Finish-Chunk sie enthält.
Einen Stream im Code auslesen
# Python, mit dem offiziellen openai-Paket stream = client.chat.completions.create( model="tai-4.1", messages=[{"role": "user", "content": "Kısa bir şiir yaz"}], stream=True, ) for chunk in stream: if chunk.choices and chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end="", flush=True)
Die offiziellen OpenAI-SDKs (Python und Node) wissen bereits, wie dieses Ereignisformat zu parsen ist, da es dasselbe ist, das ihre eigene API verwendet; nichts tAI-Spezifisches wird im Client benötigt, außer base_url auf https://api.artfical.com/v1 zu setzen, wie auf der Seite Authentifizierung beschrieben.
Ein Stream endet immer sauber
Selbst wenn mitten im Verlauf etwas schiefgeht, die Generierung fehlschlägt, eine Anfrage intern in ein Timeout läuft, was auch immer die Ursache ist, endet der Stream trotzdem mit einem sichtbaren Signal, statt dass die Verbindung einfach ohne Erklärung abbricht. In diesem Fall sehen Sie einen Content-Chunk mit einem kurzen Hinweis in eckigen Klammern, einen Finish-Chunk mit "finish_reason": "stop", und dann [DONE], denselben wohlgeformten Abschluss wie bei einem normalen, erfolgreichen Stream. Ein Client sollte das Eintreffen von [DONE] immer als das endgültige Ende des Turns behandeln und nicht annehmen, dass ein Stream, der ohne dieses Signal endet, trotzdem erfolgreich war; eine abgebrochene Verbindung ohne [DONE] bedeutet, die Anfrage als fehlgeschlagen zu behandeln und sie erneut zu versuchen, genau wie bei einer Anfrage ohne Streaming, die in ein Timeout gelaufen ist.