Streaming (SSE)
Quando você passa "stream": true na chamada de chat/completions, o Tokia retorna a resposta em tempo real via Server-Sent Events (SSE), token por token. Isso permite exibir texto na tela enquanto o modelo ainda está gerando — a experiência de “digitação ao vivo” que todo chat de IA usa.
Como funciona
Em vez de esperar a resposta completa (que pode levar segundos), o servidor envia pequenos chunks assim que cada token fica pronto. Cada chunk é um evento SSE no formato:
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Olá"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"!"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]- Cada linha
data:contém um JSON com o delta (trecho novo) delta.contenttem o texto parcial do token gerado- Quando
finish_reasonvira"stop", a geração terminou - A linha
data: [DONE]indica fim do stream
Python
from openai import OpenAI
client = OpenAI(
api_key="sk-...",
base_url="https://api.usetokia.com/v1",
)
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Conte uma piada curta"}],
stream=True,
)
for chunk in stream:
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
print() # nova linha ao finalPython async
import asyncio
from openai import AsyncOpenAI
client = AsyncOpenAI(
api_key="sk-...",
base_url="https://api.usetokia.com/v1",
)
async def main():
stream = await client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Conte uma piada curta"}],
stream=True,
)
async for chunk in stream:
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
asyncio.run(main())TypeScript / Node.js
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.TOKIA_KEY,
baseURL: "https://api.usetokia.com/v1",
});
const stream = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Conte uma piada curta" }],
stream: true,
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content;
if (content) {
process.stdout.write(content);
}
}No browser (fetch + ReadableStream)
const response = await fetch("https://api.usetokia.com/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": "Bearer sk-...",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Olá!" }],
stream: true,
}),
});
const reader = response.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = decoder.decode(value, { stream: true });
for (const line of text.split("\n")) {
if (!line.startsWith("data: ") || line === "data: [DONE]") continue;
const json = JSON.parse(line.slice(6));
const content = json.choices?.[0]?.delta?.content;
if (content) {
document.getElementById("output")!.textContent += content;
}
}
}cURL
curl -N https://api.usetokia.com/v1/chat/completions \
-H "Authorization: Bearer $TOKIA_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Olá!"}],
"stream": true
}'O flag -N desabilita o buffer do cURL, fazendo os tokens aparecerem em tempo real no terminal.
stream_options: uso e tokens
Para receber o total de tokens consumidos no final do stream, passe stream_options:
{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Olá"}],
"stream": true,
"stream_options": {
"include_usage": true
}
}O último chunk antes de [DONE] terá o campo usage com prompt_tokens, completion_tokens e total_tokens.
Tratamento de erros em streaming
Erros podem acontecer antes do stream começar (HTTP 4xx/5xx normal) ou durante o stream (conexão cortada). Trate ambos:
from openai import OpenAI, APIError
client = OpenAI(api_key="sk-...", base_url="https://api.usetokia.com/v1")
try:
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Olá"}],
stream=True,
)
for chunk in stream:
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
except APIError as e:
print(f"\nErro da API: {e.status_code} - {e.message}")
except Exception as e:
print(f"\nErro de conexão: {e}")Quando usar streaming
- Use streaming quando o resultado é exibido ao usuário em tempo real (chatbots, copilots, assistentes)
- Não use streaming quando você precisa do resultado completo antes de processar (classificação, extração de dados, pipelines batch)
- Streaming não altera o preço — o custo por token é o mesmo
- O timeout é mais longo em streaming (o servidor aguarda enquanto tokens estão sendo gerados)
Próximos passos
- /v1/chat/completions — referência completa do endpoint
- Tool Calling — como usar function calling com streaming
- Structured Outputs — JSON mode e JSON Schema