Streaming de contabilidade de token em um AI API Gateway: uso final, cancelamentos e respostas parciais
O streaming melhora a latência percebida, mas pode interromper a análise e o faturamento do uso da IA se o gateway apenas fizer proxy de bytes. Aqui está um padrão prático de máquina de estados para capturar uso final, fluxos abortados, erros de provedor e respostas parciais.
As respostas do LLM de streaming são fáceis de fazer proxy e difíceis de cobrar corretamente. Se um AI API gateway encaminhar eventos enviados pelo servidor para o cliente, mas tratar os primeiros pedaços como o registro de uso, a análise do locatário sofrerá desvios. O desvio geralmente aparece em disputas como: “o usuário viu apenas metade da resposta”, “o provedor cobrou mais do que nosso painel mostra”, “a cota foi liberada muito cedo” ou “um tempo limite produziu tokens, mas nenhuma linha de fatura”.
A raiz do problema é que as chamadas transmitidas não são um evento. Eles são uma sequência: solicitação aceita, fluxo upstream aberto, bytes entregues, uso final relatado, provedor interrompido, cliente desconectado, tempo limite do gateway esgotado e cobrança liquidada. Um gateway confiável deve modelar esses estados explicitamente em vez de assumir que uma resposta HTTP concluída é o único caminho bem-sucedido.
O modo de falha: o streaming esconde os limites da contabilidade
As conclusões não transmitidas geralmente retornam um objeto de resposta com metadados de uso. Um gateway pode normalizar esse uso, gravar uma linha do razão, atualizar a cota e emitir análises em uma única passagem.
O streaming altera os limites. A experiência do usuário é incremental, mas a verdade do faturamento pode chegar no final, em um evento final específico do provedor, em um delta cumulativo, por meio de uma resposta agregada SDK ou posteriormente por meio de APIs de relatórios do provedor. Se o cliente se desconectar antes do evento de uso final, o gateway poderá ter entregue apenas parte da resposta, enquanto o provedor ainda gerou e faturou mais tokens.
Fato: OpenAI documenta que os chamadores de streaming que desejam dados de uso devem definir stream_options com include_usage. OpenAI também fornece pontos de extremidade de custo e uso em nível de organização, embora observe que o uso e os custos nem sempre podem ser conciliados perfeitamente para fins financeiros.
Fato: Anthropic streaming usa eventos enviados pelo servidor, como message_start, content_block_delta, message_delta e message_stop. Suas message_delta informações de uso são cumulativas, portanto, um gateway não deve adicionar cada delta de uso.
Fato: Gemini e as APIs de streaming no estilo Vertex podem expor pedaços incrementais, enquanto os SDKs também podem fornecer um objeto de resposta agregado. Para gateways, esse caminho agregado pode ser uma fonte melhor para uso completo do que apenas os pedaços visíveis.
Use uma máquina de estado de fluxo, não um sinalizador booleano de sucesso
Uma solicitação transmitida deve ter um registro de uso durável antes do início da chamada upstream. Esse registro deve passar por estados explícitos. Um mínimo prático é:
accepted: o gateway autenticou a chave, atribuiu o inquilino e criou uma linha de razão aberta.first_byte_sent: pelo menos um evento de saída atingiu o cliente downstream.provider_completed: o provedor upstream emitiu um sinal de parada normal ou completou o objeto de resposta.client_aborted: o soquete downstream foi fechado antes da conclusão normal do gateway.provider_error: o provedor upstream retornou um erro após o início do stream ou antes da chegada do uso final.gateway_timeout: o gateway aplicou seu orçamento de latência e encerrou a solicitação.settled: o gateway converteu o uso em custo do locatário e consumo de cota.reconciled: dados posteriores de uso ou custo do provedor confirmaram ou ajustaram a linha.
Este modelo evita um bug analítico comum: marcar cada fluxo que produziu texto como “bem-sucedido e exato”. Um fluxo pode ser útil para o usuário, incompleto do provedor, estimado para faturamento e reconciliação pendente ao mesmo tempo.
Campos contábeis recomendados
Mantenha a linha do horário da solicitação pequena, mas explícita:
{
"request_id": "gw_req_...",
"tenant_id": "tenant_123",
"api_key_id": "key_456",
"provider": "openai|anthropic|gemini|...",
"provider_request_id": null,
"model": "provider-model-id",
"state": "accepted",
"stream": true,
"input_tokens": null,
"output_tokens_billed": null,
"output_tokens_delivered_estimate": 0,
"provider_usage_source": null,
"billing_status": "pending_reconciliation",
"client_abort_at": null,
"provider_completed_at": null,
"settled_at": null,
"error_class": null
}
A separação importante é output_tokens_billed versus output_tokens_delivered_estimate. Os usuários se preocupam com o que chegou ao seu aplicativo. As finanças se importam com o que o provedor cobrou. Esses números podem diferir após desconexões, fluxos de chamadas de ferramentas, tokens de raciocínio ocultos, tokens armazenados em cache, paradas de segurança ou tempos limite de gateway.
Regras de captura específicas do provedor
Um provedor neutro OpenAIcompatível API é útil para desenvolvedores de aplicativos, mas o adaptador de gateway ainda precisa de regras de contabilidade específicas do provedor.
OpenAItransmissão compatível
Para OpenAI rotas, exponha uma opção de gateway que permita relatórios de uso upstream quando houver suporte. Um padrão comum é aceitar um padrão no nível do gateway, como:
{
"stream": true,
"stream_options": {
"include_usage": true
}
}
Se o chamador downstream omitir, o gateway poderá decidir se deve injetá-lo em rotas onde isso for compatível. Documente esse comportamento porque alguns clientes esperam compatibilidade exata de fios e alguns modelos ou upstreams podem não suportar o uso final da mesma maneira.
Recomendação: não liquide os custos do locatário a partir de parcelas iniciais. Mantenha a linha do razão aberta até que o evento de uso final seja capturado, a resposta do provedor termine sem uso ou o fluxo insira um erro ou caminho de cancelamento.
Anthropic transmissão
O uso cumulativo deAnthropic requer uma regra diferente. Se um gateway vir três message_delta eventos com contagens de tokens de saída de 10, 25 e 40, a contagem de saída será 40, não 75.
let latestUsage = null;
for await (const event of anthropicStream) {
if (event.type === "message_delta" && event.usage) {
if (latestUsage && event.usage.output_tokens < latestUsage.output_tokens) {
emit("cumulative_usage_regressed", requestId);
}
latestUsage = event.usage;
}
forwardToClient(event);
}
settleFromLatestCumulativeUsage(latestUsage);
Recomendação: registre o valor de uso cumulativo mais recente e emita um evento de observabilidade se ele regredir. Uma regressão pode indicar erros no analisador, eventos duplicados, alterações de provedor ou fluxos mistos.
Gemini e streaming estilo Vertex
Gemini oferece suporte a blocos de streaming para reduzir a latência percebida. Nos SDKs estilo Vertex, o streaming pode expor um fluxo assíncrono e um objeto de resposta agregado. Um gateway deve preservar esse caminho agregado quando disponível.
const streamingResult = await model.generateContentStream(request);
for await (const chunk of streamingResult.stream) {
forwardChunk(chunk);
countDeliveredBytesOrText(chunk);
}
const aggregated = await streamingResult.response;
settleFromAggregatedUsage(aggregated);
Recomendação: evite criar toda a contabilidade a partir de partes visíveis se SDK fornecer um registro de resposta completo. Pedaços são para latência. O objeto final geralmente é melhor para faturamento e análise.
Trate de desconexões de clientes como eventos contábeis de primeira classe
As desconexões de clientes são onde muitos gateways perdem dinheiro ou cobram demais dos clientes. Uma guia do navegador é fechada, uma rede móvel cai ou um aplicativo cancela uma solicitação. O gateway percebe que o soquete downstream está fechado, mas o provedor upstream ainda pode estar gerando.
O gateway deve fazer uma escolha de política explícita:
- Cancelar o upstream imediatamente: reduz o desperdício de geração e o custo do provedor, mas pode interromper fluxos de trabalho em que o back-end ainda precisa do resultado após a desconexão da IU.
- Continuar o upstream em segundo plano: pode preservar o trabalho dos consumidores do lado do servidor, mas o usuário pode não ver todos os tokens gerados e cobrados.
- Comportamento dependente de rota: cancelar para bate-papo interativo, continuar para fluxos de trabalho semelhantes a trabalhos e tornar a configuração visível para os locatários.
Um padrão prático para streaming interativo é cancelar o upstream quando o cliente downstream se desconecta e, em seguida, marcar a linha do razão como client_aborted. Se o uso final chegar durante o cancelamento, faça o acordo a partir desse uso oficial. Caso contrário, marque a linha estimated ou pending_reconciliation em vez de fingir que é exata.
downstream.on("close", async () => {
if (!providerCompleted) {
ledger.markClientAborted(requestId);
await upstream.abort().catch(() => {
ledger.emit("upstream_cancel_failed", requestId);
});
}
});
Recomendação: exponha rótulos de faturamento transparentes, como final, provider_reconciled, estimated, waived ou pending_reconciliation. Isso é mais defensável do que mostrar todas as chamadas transmitidas como imediatamente exatas.
Aplicação de cota durante um stream
O faturamento preciso geralmente depende do uso final do provedor, mas a aplicação da cota nem sempre pode esperar até o fim. Um locatário com um orçamento rígido não deve ter permissão para transmitir indefinidamente porque o uso exato não está disponível no meio do voo.
Use dois mecanismos juntos:
- Reserva prévia: reserva um máximo estimado com base no modelo, no máximo de tokens solicitados, na política do locatário e no saldo atual.
- Verificações de pressão de streaming: estima a saída entregue durante o fluxo e para se a solicitação cruzar um limite de segurança configurado.
Este é um mecanismo de controle, não a conta final. Os provedores podem contar tokens armazenados em cache, tokens de raciocínio, tokens multimodais ou tokens ocultos de maneira diferente do estimador de um gateway.
Compensação: estimativas em tempo real ajudam a impor orçamentos, mas podem divergir dos tokens cobrados pelo provedor. A liquidação final deve usar o uso oficial do provedor quando disponível, e a reconciliação deve ajustar as estimativas posteriormente.
Eventos de observabilidade que detectam bugs contábeis
As falhas de faturamento de streaming são mais fáceis de depurar quando o gateway emite eventos direcionados em vez de apenas registros de solicitação genéricos. Adicione eventos como:
final_usage_missing: a transmissão terminou sem uso autorizado.cumulative_usage_regressed: contagem cumulativa de tokens retrocedida.stream_ended_without_stop_event: nenhum marcador de parada de provedor normal foi observado.aborted_after_provider_completion: o provedor foi concluído, mas o cliente downstream fechou antes que o gateway terminasse o encaminhamento.settled_from_estimate: o razão de inquilino usou uma estimativa porque o uso final não estava disponível.reconciliation_adjusted_usage: o relatório do provedor alterou posteriormente a linha.
Fato: As convenções semânticas do OpenTelemetry GenAI recomendam o uso de informações de uso retornadas pelo provedor para respostas de streaming, quando disponíveis, e alertam contra relatórios de métricas de uso se as contagens de token não puderem ser obtidas com eficiência ou precisão.
Para análise de uso de IA, isso significa que os painéis devem suportar níveis de confiança. Um gráfico que mistura valores finais, estimados e reconciliados sem rótulos pode parecer limpo, mas enganar as equipes financeiras e de suporte.
Testes de conformidade para contabilidade de streaming
Não confie em testes manuais com um prompt de bate-papo de caminho feliz. Cada adaptador de provedor deve ter testes de conformidade para os casos que quebram os livros contábeis:
- Fluxo normal: o uso final chega, o evento de parada é observado, o razão é liquidado como
final. - Fluxo de chamada de ferramenta: deltas de chamada de ferramenta são encaminhados, o uso é capturado, os metadados estruturados não corrompem a contagem de tokens.
- Parada de segurança ou recusa: o provedor para mais cedo, o uso ainda é liquidado corretamente.
- Desconexão forçada do cliente: downstream fecha após saída parcial; o upstream é cancelado ou continuado de acordo com a política.
- Upstream 5xx após saída parcial: o gateway registra a entrega parcial e não marca a solicitação como um sucesso limpo.
- Tempo limite do gateway antes do uso final: linha torna-se estimada ou reconciliação pendente.
- Evento final ausente: o adaptador emite
final_usage_missinge evita rótulos de cobrança exatos.
Esses testes devem afirmar transições de estado, campos contábeis, eventos de observabilidade emitidos e comportamento downstream. A compatibilidade do fluxo byte por byte não é suficiente; os efeitos colaterais contábeis fazem parte do contrato.
Lista de verificação prática de implementação
- Crie a linha do razão de uso antes de enviar a solicitação upstream.
- Armazene inquilino, chave, usuário, modelo, rota, provedor e identificadores de solicitação no momento da solicitação.
- Ativar relatórios de uso final do provedor onde houver suporte, como OpenAIcompatível
stream_options.include_usage. - Para provedores cumulativos, armazene o valor de uso mais recente em vez de somar eventos.
- Preserva objetos de resposta agregados quando os SDKs os fornecem.
- Acompanhe a saída entregue separadamente do uso faturado pelo provedor.
- Ao desconectar, cancele o upstream de acordo com a política de rota e marque
client_aborted. - Use status de faturamento transparentes: reconciliação final, estimada, pendente, reconciliada pelo provedor ou dispensada.
- Emitir eventos de observabilidade específicos de contabilidade.
- Reconcilie posteriormente com relatórios de uso ou custo do provedor, quando disponíveis, preservando a atribuição do locatário no momento da solicitação.
O que mostrar aos inquilinos
Os locatários não precisam de todos os eventos internos, mas precisam de rótulos honestos. Uma tabela de uso útil pode mostrar:
- Status: final, estimado ou reconciliado.
- Resultado da solicitação: concluído, cliente anulado, erro do provedor ou tempo limite do gateway.
- Saída entregue: texto ou bytes aproximados enviados ao cliente.
- Tokens faturados: uso normalizado pelo provedor usado para custo.
- Ajuste: qualquer delta de reconciliação posterior.
Esse design reduz a ambiguidade do suporte. Se um usuário viu apenas parte de uma resposta, o painel poderá explicar se o provedor já havia concluído, se o gateway cancelou o upstream e se a cobrança é final ou estimada.
Recomendações versus previsões
Recomendações: trate as solicitações transmitidas como máquinas de estado, aguarde o uso final oficial antes da liquidação exata, separe a saída entregue do uso faturado e rotule honestamente as linhas estimadas. Os adaptadores do provedor devem codificar a semântica de uso específica do provedor, em vez de nivelar cada fluxo em um proxy de byte genérico.
Predição: a contabilidade de streaming se tornará mais importante à medida que os modelos expõem mais trabalhos ocultos: tokens de raciocínio, descontos em tokens em cache, processamento multimodal, rastreamentos de uso de ferramentas e paradas de segurança. Os gateways que já separam o uso cobrado pelo provedor da saída visível ao cliente se adaptarão mais facilmente do que os gateways que contam apenas o texto transmitido.
Conclusão acionável
Se o seu gateway suporta streaming, audite um caminho hoje: force a desconexão de um cliente após os primeiros pedaços e inspecione a linha do razão. Se aparecer “sucesso” com contagens de tokens de aparência exata, suas análises provavelmente estão mentindo.
A solução não é abandonar o streaming. Mantenha a experiência rápida do usuário, mas torne a conclusão do fluxo, o cancelamento, os erros do provedor, a falta de uso final e a reconciliação de estados contábeis explícitos. Isso proporciona resultados responsivos às equipes de produtos, custos defensáveis às equipes financeiras e equipes de suporte com evidências suficientes para explicar respostas parciais sem adivinhação.