Streaming
Defina "stream": true e o mesmo endpoint devolve a resposta de forma incremental através de eventos enviados pelo servidor, em vez de esperar que tudo termine.
Porquê usar streaming
Um pedido sem streaming bloqueia até o modelo ter terminado de gerar toda a resposta, e só depois a devolve de uma vez. Para uma resposta curta, isso raramente se nota. Para uma mais longa, significa esperar vários segundos (por vezes mais) a olhar para o vazio antes de aparecer qualquer texto. O streaming resolve isto enviando a resposta peça a peça, à medida que o modelo a produz, para que um cliente possa começar a apresentar texto numa fração de segundo após o pedido sair, em vez de esperar pelo conjunto todo. É essa a diferença entre uma interface de chat que parece instantânea e uma que parece estar presa em cada mensagem. É opcional e não custa nada extra utilizá-lo.
Ativar o streaming
{
"model": "tai-4.1",
"messages": [{"role": "user", "content": "1'den 5'e kadar say"}],
"stream": true
}
O Content-Type da resposta passa a ser text/event-stream em vez de application/json. Cada linha de evento tem o prefixo data: , e a ligação mantém-se aberta, enviando um evento por cada fragmento de conteúdo novo, até o stream terminar com uma linha literal data: [DONE].
O formato de um chunk
A maioria dos chunks transporta um pequeno fragmento de texto recém-gerado em 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}]}
Concatenar cada valor de delta.content pela ordem, ao longo de todos os chunks, reconstrói o texto completo da resposta. Construir essa concatenação é tarefa do cliente; a API não envia o texto acumulado em nenhum momento, apenas o fragmento incremental que cada chunk acrescenta.
O chunk final
O último chunk com conteúdo transporta um delta vazio e um finish_reason real ("stop", ou "tool_calls" se o modelo estiver a pedir para chamar uma ferramenta, consulte Chamada de ferramentas):
data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [{"index": 0, "delta": {}, "finish_reason": "stop"}]}
O chunk de utilização
Depois do chunk final, é enviado mais um chunk com um array choices vazio e um objeto usage preenchido, com o mesmo formato do campo usage da resposta sem 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]
Um cliente que apenas se preocupa com o texto visível pode ignorar em segurança qualquer chunk com um array choices vazio; um cliente que queira mostrar a utilização de tokens ou o custo estimado depois de terminado deve procurar especificamente este chunk, em vez de assumir que o chunk final o transporta.
Ler um stream em código
# Python, usando o pacote oficial 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)
Os SDKs oficiais da OpenAI (Python e Node) já sabem interpretar este formato de eventos, uma vez que é o mesmo que a própria API deles usa; não é necessário nada específico da tAI no cliente, além de apontar base_url para https://api.artfical.com/v1, como abordado na página Autenticação.
Um stream termina sempre de forma limpa
Mesmo que algo corra mal a meio, a geração falha, um pedido expira internamente, seja qual for a causa, o stream continua a terminar com um sinal visível em vez de a ligação simplesmente cair sem explicação. Nesse caso verá um chunk de conteúdo com um pequeno aviso entre parênteses retos, um chunk final com "finish_reason": "stop", e depois [DONE], o mesmo final bem formado de um stream normal e bem-sucedido. Um cliente deve sempre tratar a chegada de [DONE] como o fim definitivo do turno, e não deve assumir que um stream que termina sem isso foi bem-sucedido; uma ligação que cai sem [DONE] significa tratar o pedido como falhado e tentar novamente, tal como faria para um pedido sem streaming que expirou.