Streaming
Imposti "stream": true e lo stesso endpoint restituisce la risposta in modo incrementale tramite server-sent events invece di attendere che tutto sia terminato.
Perché usare lo streaming
Una richiesta non in streaming si blocca finché il modello non ha terminato di generare l'intera risposta, per poi restituirla tutta in una volta. Per una risposta breve, questo raramente si nota. Per una più lunga, significa attendere diversi secondi (a volte di più) fissando il nulla prima che compaia qualsiasi testo. Lo streaming risolve il problema inviando la risposta pezzo per pezzo, man mano che il modello la produce, così un client può iniziare a visualizzare il testo entro una frazione di secondo dall'invio della richiesta invece di attendere il tutto. Questa è la differenza tra un'interfaccia di chat che sembra istantanea e una che sembra bloccarsi a ogni messaggio. È opzionale e non costa nulla in più da usare.
Attivarlo
{
"model": "tai-4.1",
"messages": [{"role": "user", "content": "1'den 5'e kadar say"}],
"stream": true
}
Il Content-Type della risposta diventa text/event-stream invece di application/json. Ogni riga di evento ha il prefisso data: , e la connessione resta aperta, inviando un evento per ogni frammento di nuovo contenuto, finché lo stream non termina con una riga letterale data: [DONE].
La struttura di un chunk
La maggior parte dei chunk trasporta un piccolo frammento di testo appena generato 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}]}
Concatenando ogni valore delta.content in ordine, su tutti i chunk, si ricostruisce il testo completo della risposta. Costruire questa concatenazione è compito del client; l'API non invia mai il testo accumulato, solo il frammento incrementale aggiunto da ciascun chunk.
Il chunk finale
L'ultimo chunk che trasporta contenuto ha un delta vuoto e un finish_reason reale ("stop", oppure "tool_calls" se il modello sta chiedendo di chiamare uno strumento, vedere Chiamata di strumenti):
data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [{"index": 0, "delta": {}, "finish_reason": "stop"}]}
Il chunk di usage
Dopo il chunk finale, viene inviato un altro chunk con un array choices vuoto e un oggetto usage popolato, con la stessa struttura del campo usage della risposta non in 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]
Un client interessato solo al testo visibile può ignorare tranquillamente qualsiasi chunk con un array choices vuoto; un client che vuole mostrare l'utilizzo di token o il costo stimato a posteriori dovrebbe cercare specificamente questo chunk invece di supporre che sia il chunk finale a trasportarlo.
Leggere uno stream nel codice
# Python, usando il pacchetto ufficiale openai 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)
Gli SDK ufficiali di OpenAI (Python e Node) sanno già come analizzare questa forma di evento, poiché è la stessa usata dalla loro stessa API; non è richiesto nulla di specifico per tAI nel client oltre a puntare base_url verso https://api.artfical.com/v1, come trattato nella pagina Autenticazione.
Uno stream termina sempre in modo pulito
Anche se qualcosa va storto a metà, la generazione fallisce, una richiesta va in timeout internamente, qualunque sia la causa, lo stream termina comunque con un segnale visibile invece che con la semplice caduta della connessione senza spiegazioni. In quel caso vedrà un chunk di contenuto con un breve avviso tra parentesi quadre, un chunk finale con "finish_reason": "stop", e poi [DONE], la stessa conclusione ben formata di uno stream normale andato a buon fine. Un client dovrebbe sempre considerare l'arrivo di [DONE] come la fine definitiva del turno, e non dovrebbe supporre che uno stream terminato senza di esso sia andato a buon fine; una connessione caduta senza [DONE] significa considerare la richiesta come fallita e riprovare, allo stesso modo di una richiesta non in streaming andata in timeout.