Streaming com APIs de IA (SSE): resposta em tempo real na prática
Se você já usou ChatGPT, já viu streaming em ação: os tokens aparecendo aos poucos. É assim que dá para construir UX de IA decente — e é mais simples do que parece.
O que acontece por baixo
A API usa Server-Sent Events (SSE): o servidor mantém a conexão aberta e vai mandando pedaços da resposta. Com o SDK da OpenAI (compatível com a maioria dos gateways), é só stream=True:
from openai import OpenAI
client = OpenAI(base_url="https://api.exemplo.com/v1", api_key="sua-chave")
resposta = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Explique o que é SSE em 3 frases"}],
stream=True,
)
for chunk in resposta:
parte = chunk.choices[0].delta.content
if parte:
print(parte, end="", flush=True)
print()
No frontend (JavaScript), consumir o stream exige decodificar o SSE:
O fetch com stream: true devolve os bytes crus — é preciso decodificá-los, separar as linhas data: e parar no marcador de fim [DONE]:
async function main() {
const resposta = await fetch("https://api.exemplo.com/v1/chat/completions", {
method: "POST",
headers: { "Content-Type": "application/json", "Authorization": "Bearer SUA_CHAVE" },
body: JSON.stringify({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "O que é streaming?" }],
stream: true,
}),
});
if (!resposta.ok) throw new Error(`HTTP ${resposta.status}`);
const leitor = resposta.body.getReader();
const decodificador = new TextDecoder();
let buffer = "";
while (true) {
const { done, value } = await leitor.read();
if (done) break;
buffer += decodificador.decode(value, { stream: true });
const linhas = buffer.split("\n");
buffer = linhas.pop(); // guarda o resto incompleto do próximo chunk
for (const linha of linhas) {
if (!linha.startsWith("data:")) continue;
const dados = linha.slice(5).trim();
if (!dados || dados === "[DONE]") return;
const parte = JSON.parse(dados).choices[0].delta.content ?? "";
// mostre `parte` na tela, token a token
}
}
}
main().catch(console.error); // rode em ambiente com suporte a fetch (navegador moderno ou Node 18+)
Por que isso importa:
- Percepção de velocidade — o primeiro token chega em frações de segundo; o usuário não espera uma tela congelada enquanto o texto completo é gerado;
- Menos timeout de leitura — em gerações longas, o cliente não fica esperando a resposta inteira (o que estouraria o timeout de leitura). Atenção: se você usa um proxy reverso (ex.: Nginx), ajuste o
proxy_read_timeoutpara não cortar a conexão SSE; - UX profissional — é o padrão de qualquer produto de IA sério.
Cuidado: no servidor (FastAPI/Node), repasse o stream ao frontend em vez de acumular e enviar tudo depois. E sempre trate o fim do stream ([DONE]) e erros de conexão — com retry/backoff, por exemplo.
Streaming é o divisor de águas entre um "protótipo que trava" e um "produto que responde".
Quer testar esses modelos no seu projeto? A ModelKiwi dá acesso a GPT, Claude e Gemini com recarga via PIX (sem cartão internacional) e créditos grátis para começar: https://www.modelkiwi.com. Fale com a gente no WhatsApp: +5521999500402.