Sem streaming, a aplicação espera o modelo terminar e recebe uma resposta completa. Com streaming, o servidor envia eventos enquanto o conteúdo é gerado. O usuário vê a primeira parte antes, embora o tempo total do modelo possa continuar parecido. Essa diferença costuma melhorar uma interface conversacional, mas cria trabalho que não existe numa chamada JSON comum.
A aplicação precisa ler um fluxo, interpretar eventos, acumular partes na ordem, reconhecer o término e decidir o que fazer se a conexão cair no meio. Também precisa manter a experiência acessível: atualizar a tela em velocidade razoável, permitir cancelamento e não anunciar como concluída uma resposta incompleta.
Este guia usa o padrão de eventos enviados pelo servidor, comum em APIs compatíveis com OpenAI. O detalhe dos eventos varia por endpoint e provedor. Na Roteia, o catálogo informa quais modelos declaram streaming; uma chamada com stream: true é rejeitada antes do débito quando o modelo selecionado não oferece a capacidade.
O que muda entre resposta completa e fluxo
Numa resposta completa, o servidor devolve cabeçalhos, um corpo JSON e encerra a requisição. O cliente só renderiza quando todo o corpo chegou. No fluxo, a conexão permanece aberta e carrega uma sequência de eventos. Cada evento pode conter um fragmento de texto, uma atualização de tool call, metadados ou um marcador de término. O cliente não deve supor que cada pacote de rede coincide com um evento completo.
O benefício principal é o tempo até o primeiro conteúdo. Uma geração de quinze segundos ainda pode levar quinze segundos, mas começar a aparecer no segundo dois. Isso reduz a sensação de tela travada e permite que a pessoa interrompa cedo se percebeu que pediu a coisa errada. Para tarefas invisíveis, como classificação em lote ou extração curta, o ganho de interface pode não justificar a complexidade.
Streaming não é uma modalidade do modelo nem áudio em tempo real. É uma forma de transportar a saída de uma requisição. APIs de voz interativa podem usar WebSocket ou WebRTC e têm contratos próprios; não trate tudo que chega aos poucos como o mesmo protocolo.
Como os eventos SSE chegam ao cliente
Server-Sent Events usam uma resposta HTTP mantida aberta, normalmente com conteúdo text/event-stream. Os eventos são separados por linhas em branco e campos como data: carregam o payload. Em chat completions compatível, cada payload costuma ser JSON com um delta. O texto final nasce da concatenação dos deltas, não de substituir a resposta anterior pelo evento mais recente.
Leitores prontos ajudam, mas um parser manual precisa lidar com fragmentação. Uma leitura pode terminar no meio de uma linha; outra pode conter vários eventos de uma vez. Guarde o restante incompleto, processe apenas blocos fechados e faça parse de cada campo data. O término pode vir em um evento específico ou marcador definido pelo contrato.
Use decodificação incremental para não quebrar caracteres multibyte de português. Atualize o estado da interface em lotes curtos em vez de renderizar cada byte. Isso evita excesso de trabalho no navegador e mantém o cursor, leitor de tela e botão de cancelar utilizáveis.
curl -N https://api.roteia.ai/v1/chat/completions \
-H "Authorization: Bearer $ROTEIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "COLE_UM_ID_COM_STREAMING_DO_CATALOGO",
"stream": true,
"messages": [{"role":"user","content":"Explique SSE em três pontos."}]
}'Primeiro conteúdo, resposta final e uso são métricas diferentes
Meça pelo menos três momentos: envio da requisição, chegada do primeiro delta útil e conclusão do fluxo. O primeiro intervalo descreve a espera percebida; o segundo, o tempo total. Uma otimização pode melhorar um e piorar o outro. Guarde também status, modelo efetivamente usado e identificador da requisição para ligar a experiência do cliente ao registro operacional.
A contagem de tokens pode aparecer apenas perto do fim, dependendo do contrato e do provedor. O usage do upstream é a fonte preferencial quando chega. Se um fluxo parcial ou interrompido terminar sem esse dado, a Roteia usa hoje uma estimativa conservadora: estima os tokens de entrada pelo conteúdo enviado e os de saída pelos caracteres recebidos. Essa estimativa pode entrar no cálculo da cobrança, mas não tem a mesma precisão do usage informado pelo provedor; por isso, trate-a como aproximação no seu próprio relatório de custos.
Não confunda resposta visualmente longa com chamada saudável. Um fluxo pode começar rápido, pausar por muitos segundos e terminar. Registre intervalos entre eventos ou, no mínimo, percentis de conclusão para encontrar essas caudas.
Cancelamento e erro no meio do fluxo
O usuário precisa conseguir cancelar. No navegador, um AbortController pode encerrar o fetch; no servidor, propague o sinal quando a biblioteca permitir. Depois do cancelamento, marque a mensagem como interrompida e não a reutilize como se fosse resposta completa. O consumo já gerado até aquele ponto pode continuar existindo conforme o upstream.
Antes do primeiro byte, um erro HTTP ainda pode ser tratado como qualquer resposta JSON. Depois que o status e parte do corpo foram enviados, não dá para trocar silenciosamente para outro modelo e fingir uma única resposta: texto parcial e nova geração podem se contradizer. A Roteia só tenta um fallback antes de a resposta começar; após o stream iniciar, não há troca segura no meio.
Retry automático exige idempotência e contexto. Repetir uma geração inteira após queda pode cobrar outra chamada e devolver texto diferente. Para uma interface, ofereça “tentar novamente” deixando claro que é uma nova resposta. Para automação com efeito externo, nunca repita a ação só porque o texto de confirmação não chegou.
- Diferencie falha antes do primeiro evento de interrupção após conteúdo parcial.
- Preserve o texto parcial com estado visual de incompleto quando isso ajudar o usuário.
- Não execute tool call até receber e validar todos os argumentos.
- Associe cancelamento e erro ao identificador da requisição.
Streaming com tools e JSON exige estado
Em tool calling, nome e argumentos podem chegar em partes. Tentar executar ao receber o primeiro fragmento produz JSON inválido ou parâmetros incompletos. Acumule os deltas por identificador da chamada, espere o motivo de término aplicável, faça parse e só então valide permissão e schema. Chamadas paralelas precisam de acumuladores separados.
Structured output também não é JSON válido a cada evento. Um prefixo como {"cliente": é incompleto por natureza. A interface pode mostrar progresso, mas o consumidor estrutural deve esperar o objeto terminar e passar por validação. Se a aplicação precisa de campos parciais acionáveis, desenhe eventos próprios no seu backend em vez de interpretar JSON pela metade.
Moderação de saída fica mais difícil porque o conteúdo chega antes de uma revisão completa. Para casos de risco alto, avalie segurar trechos, moderar incrementalmente ou abandonar streaming. Experiência mais rápida não supera requisito de segurança.
Checklist para colocar o fluxo em produção
Comece confirmando no catálogo que o modelo e a rota aceitam streaming. Teste uma resposta curta, uma longa, cancelamento, tempo limite, desconexão e erro do upstream. Faça o teste através do mesmo proxy e da mesma infraestrutura de produção: buffers de servidor, CDN e compressão podem atrasar eventos e transformar um fluxo correto no backend em uma entrega de uma vez só.
Defina limites de duração e inatividade. Uma conexão aberta sem eventos não deve ocupar recurso para sempre. Envie uma mensagem de interface que diferencie “gerando”, “cancelado”, “falhou” e “concluído”. Em acessibilidade, evite anunciar cada fragmento por leitor de tela; agrupe atualizações e disponibilize a resposta final como região legível.
Por fim, compare com o modo sem streaming. Se o caso é uma extração de 200 milissegundos consumida por máquina, a resposta completa é mais simples. Use streaming onde o primeiro conteúdo muda a experiência ou permite cancelamento útil, não como padrão automático para qualquer chamada.
Dúvidas frequentes
O que é streaming em uma API de IA?
É a entrega da resposta em eventos enquanto o modelo gera, em vez de esperar o corpo completo. Em APIs de chat, isso costuma usar SSE e deltas que o cliente acumula até o evento de término.
Streaming deixa o modelo mais rápido?
Ele reduz o tempo até o primeiro conteúdo percebido, mas não garante redução no tempo total da geração. Meça primeiro delta e conclusão separadamente para saber o efeito no seu fluxo.
Usar resposta incremental reduz o consumo de tokens?
Não automaticamente. A forma de entrega não muda o conteúdo gerado. Cancelar pode interromper geração, mas o custo deve ser conferido no uso registrado pelo provedor ou gateway.
Posso fazer retry quando o stream cai?
Pode iniciar uma nova chamada, mas ela pode gerar outra resposta e novo custo. Não junte silenciosamente texto parcial com a repetição. Em operações com efeito externo, proteja a ação com idempotência e confirmação própria.
Todo modelo da Roteia aceita streaming?
Não. A capacidade varia por modelo. Confira o campo de streaming no catálogo; a rota valida o pedido e rejeita stream: true quando o modelo selecionado não declara suporte.
Onde confirmar
Plataforma de terceiro muda de tela e de limite sem avisar. Confira na fonte oficial antes de tomar decisão baseada nesta página.
