Contabilità dei token in streaming in un gateway API AI: utilizzo finale, cancellazioni e risposte parziali
Lo streaming migliora la latenza percepita, ma può compromettere l'analisi e la fatturazione dell'utilizzo dell'intelligenza artificiale se il gateway esegue solo il proxy dei byte. Di seguito è riportato un pratico modello di macchina a stati per acquisire l'utilizzo finale, flussi interrotti, errori del provider e risposte parziali.
Le risposte LLM in streaming sono facili da proxy e difficili da fatturare correttamente. Se un gateway API AI inoltra gli eventi inviati dal server al client ma tratta i primi blocchi come record di utilizzo, l'analisi del tenant andrà alla deriva. La deriva di solito si manifesta in controversie del tipo: "l'utente ha visto solo metà della risposta", "il fornitore ha fatturato più di quanto indicato nella nostra dashboard", "la quota è stata rilasciata troppo presto" o "un timeout ha prodotto token ma nessuna riga di fattura".
Il problema principale è che le chiamate in streaming non costituiscono un evento. Sono una sequenza: richiesta accettata, flusso upstream aperto, byte consegnati, utilizzo finale riportato, provider interrotto, client disconnesso, gateway timeout e fatturazione saldata. Un gateway affidabile dovrebbe modellare esplicitamente questi stati invece di presumere che una risposta HTTP completata sia l'unico percorso riuscito.
La modalità di fallimento: lo streaming nasconde il confine contabile
I completamenti non trasmessi in streaming solitamente restituiscono un oggetto di risposta con metadati di utilizzo. Un gateway può normalizzare tale utilizzo, scrivere una riga nel registro, aggiornare la quota ed emettere analisi in un unico passaggio.
Lo streaming cambia i confini. L'esperienza utente è incrementale, ma i dati reali sulla fatturazione possono arrivare alla fine, in un evento finale specifico del provider, in un delta cumulativo, tramite una risposta SDK aggregata o successivamente tramite le API di reporting del provider. Se il client si disconnette prima dell'evento di utilizzo finale, il gateway potrebbe aver fornito solo parte della risposta mentre il provider continuava a generare e fatturare più token.
Fatto: OpenAI documenta che i chiamanti in streaming che desiderano dati sull'utilizzo dovrebbero impostare stream_options con include_usage. OpenAI fornisce inoltre endpoint di utilizzo e di costo a livello di organizzazione, pur sottolineando che l'utilizzo e i costi potrebbero non sempre conciliarsi perfettamente per scopi finanziari.
Fatto: lo streaming antropico utilizza eventi inviati dal server come message_start, content_block_delta, message_delta e message_stop. Le informazioni sull'utilizzo di message_delta sono cumulative, quindi un gateway non deve sommare insieme ogni delta di utilizzo.
Fatto: le API di streaming in stile Gemini e Vertex possono esporre blocchi incrementali mentre gli SDK possono anche fornire un oggetto di risposta aggregato. Per i gateway, quel percorso aggregato può essere una fonte migliore per l'utilizzo completato rispetto ai soli blocchi visibili.
Utilizza una macchina a stati del flusso, non un flag di successo booleano
Una richiesta trasmessa in streaming deve avere un record di utilizzo durevole prima dell'inizio della chiamata upstream. Quel record dovrebbe spostarsi attraverso stati espliciti. Un minimo pratico è:
accettato: il gateway ha autenticato la chiave, ha attribuito il tenant e ha creato una riga nel registro aperto.first_byte_sent: almeno un evento di output ha raggiunto il client downstream.provider_completed: il provider upstream ha emesso un normale segnale di stop o un oggetto di risposta completato.client_aborted: il socket downstream è stato chiuso prima del normale completamento del gateway.provider_error: il provider upstream ha restituito un errore dopo l'inizio dello streaming o prima dell'arrivo dell'utilizzo finale.gateway_timeout: il gateway ha applicato il proprio budget di latenza e ha terminato la richiesta.risolto: il gateway ha convertito l'utilizzo in costo del tenant e consumo della quota.riconciliato: successivo utilizzo del fornitore o dati di costo confermati o modificati la riga.
Questo modello previene un bug di analisi comune: contrassegnare ogni flusso che ha prodotto testo come "riuscito ed esatto". Uno streaming può essere utile all'utente, incompleto dal fornitore, stimato per la fatturazione e in attesa di riconciliazione allo stesso tempo.
Campi contabili consigliati
Mantieni la riga request-time piccola ma esplicita:
{ "request_id": "gw_req_...", "tenant_id": "tenant_123", "api_key_id": "chiave_456", "provider": "openai|anthropic|gemini|...", "provider_request_id": nullo, "modello": "id-modello-provider", "stato": "accettato", "flusso": vero, "input_tokens": nullo, "output_tokens_billed": null, "output_tokens_delivered_estimate": 0, "provider_usage_source": null, "billing_status": "riconciliazione_in sospeso", "client_abort_at": null, "provider_completed_at": null, "stabilito_at": null, "class_errore": null }
La separazione importante è output_tokens_billed rispetto a output_tokens_delivered_estimate. Agli utenti interessa ciò che ha raggiunto la loro applicazione. Alla finanza interessa ciò che il fornitore ha fatturato. Tali numeri possono variare in seguito a disconnessioni, flussi di chiamate allo strumento, token di ragionamento nascosti, token memorizzati nella cache, soste di sicurezza o timeout del gateway.
Regole di acquisizione specifiche del provider
Un'API compatibile con OpenAI indipendente dal provider è utile per gli sviluppatori di applicazioni, ma l'adattatore gateway necessita comunque di regole contabili specifiche del provider.
Streaming compatibile con OpenAI
Per i percorsi OpenAI, esporre un'opzione gateway che consenta il reporting sull'utilizzo upstream, ove supportato. Un modello comune è accettare un valore predefinito a livello di gateway come:
{ "flusso": vero, "stream_opzioni": { "include_usage": vero } }
Se il chiamante downstream lo omette, il gateway può decidere se inserirlo per i percorsi in cui ciò è compatibile. Documenta questo comportamento perché alcuni client si aspettano un'esatta compatibilità dei cavi e alcuni modelli o upstream potrebbero non supportare l'utilizzo finale allo stesso modo.
Raccomandazione: non liquidare i costi dell'affittuario a partire dalle prime fasi. Mantieni aperta la riga del registro finché non viene acquisito l'evento di utilizzo finale, la risposta del fornitore termina senza utilizzo o il flusso immette un percorso di errore o annullamento.
Streaming antropico
L'utilizzo cumulativo di Anthropic richiede una regola diversa. Se un gateway vede tre eventi message_delta con conteggi di token di output pari a 10, 25 e 40, il conteggio di output è 40, non 75.
let latestUsage = null;
for wait (evento const di antropicStream) {
if (event.type === "message_delta" && event.usage) {
if (latestUsage && event.usage.output_tokens < latestUsage.output_tokens) {
emit("cumulative_usage_regressed", requestId);
}
latestUsage = evento.usage;
}
forwardToClient(evento);
}
sedimentFromLatestCumulativeUsage(latestUsage);
Raccomandazione: registra l'ultimo valore di utilizzo cumulativo ed emette un evento di osservabilità se regredisce. Una regressione può indicare bug del parser, eventi duplicati, modifiche al provider o flussi misti.
Streaming in stile Gemini e Vertex
Gemini supporta lo streaming di blocchi per ridurre la latenza percepita. Negli SDK di tipo Vertex, lo streaming può esporre sia un flusso asincrono che un oggetto di risposta aggregato. Un gateway dovrebbe preservare quel percorso aggregato quando disponibile.
const streamingResult = attendono model.generateContentStream(request);
for wait (const pezzo di streamingResult.stream) {
avantiPezzo(pezzo);
countDeliveredBytesOrText(chunk);
}
const aggregato = attende streamingResult.response;
sedimentFromAggregatedUsage(aggregato);
Raccomandazione: evita di creare tutta la contabilità da blocchi visibili se l'SDK fornisce un record di risposta completo. I blocchi servono per la latenza. L'oggetto finale è spesso migliore per la fatturazione e l'analisi.
Gestire le disconnessioni dei clienti come eventi contabili di prima classe
Le disconnessioni dei clienti sono il luogo in cui molti gateway perdono denaro o fanno pagare troppo ai clienti. Una scheda del browser si chiude, una rete mobile si interrompe o un'applicazione annulla una richiesta. Il gateway rileva che il socket downstream è chiuso, ma il provider upstream potrebbe ancora generare dati.
Il gateway dovrebbe fare una scelta politica esplicita:
- Annulla immediatamente l'upstream: riduce gli sprechi di generazione e i costi del fornitore, ma potrebbe interrompere i flussi di lavoro in cui il backend necessita ancora del risultato dopo la disconnessione dell'interfaccia utente.
- Continua a monte in background: può preservare il lavoro per i consumatori lato server, ma l'utente potrebbe non vedere tutti i token generati e fatturati.
- Comportamento dipendente dal percorso: annulla per la chat interattiva, continua per flussi di lavoro simili a quelli lavorativi e rendi l'impostazione visibile agli inquilini.
Un'impostazione pratica predefinita per lo streaming interattivo consiste nell'annullare l'upstream quando il client downstream si disconnette, quindi contrassegnare la riga del registro come client_aborted. Se l'utilizzo finale arriva durante la cancellazione, stabilisci l'utilizzo in base a tale utilizzo autorevole. In caso contrario, contrassegna la riga come stimato o pending_reconciliation anziché fingere che sia esatta.
downstream.on("chiudi", asincrono () => {
if (!providerCompleted) {
ledger.markClientAborted(requestId);
attendono upstream.abort().catch(() => {
ledger.emit("upstream_cancel_failed", requestId);
});
}
});
Raccomandazione: esponi etichette di fatturazione trasparenti come finale, provider_reconciled, stimato, rinunciato o pending_reconciliation. Questo è più difendibile che mostrare ogni chiamata in streaming come immediatamente esatta.
Applicazione della quota durante uno streaming
La fatturazione accurata dipende solitamente dall'utilizzo finale del provider, ma l'applicazione della quota non può sempre attendere fino alla fine. A un tenant con un budget limitato non dovrebbe essere consentito di eseguire lo streaming a tempo indeterminato perché l'utilizzo esatto non è disponibile durante il volo.
Utilizza due meccanismi insieme:
- Prenotazione preliminare: prenota un importo massimo stimato in base al modello, al numero massimo di token richiesti, alla politica del locatario e al saldo attuale.
- Controlli della pressione dello streaming: stima l'output consegnato durante lo streaming e si interrompe se la richiesta supera un limite di sicurezza configurato.
Si tratta di un meccanismo di controllo, non del conto finale. I provider possono contare i token memorizzati nella cache, i token di ragionamento, i token multimodali o i token nascosti in modo diverso dallo stimatore di un gateway.
Compromesso: le stime in tempo reale aiutano a far rispettare i budget, ma possono divergere dai token fatturati dal fornitore. La liquidazione finale dovrebbe utilizzare l'utilizzo del fornitore autorevole, quando disponibile, e la riconciliazione dovrebbe adeguare le stime in un secondo momento.
Eventi di osservabilità che rilevano bug contabili
È più semplice eseguire il debug degli errori di fatturazione in streaming quando il gateway emette eventi mirati anziché solo log di richieste generiche. Aggiungi eventi come:
final_usage_missing: streaming terminato senza utilizzo autorevole.cumulative_usage_regressed: conteggio cumulativo dei token spostato indietro.stream_ended_without_stop_event: non è stato osservato alcun normale indicatore di fermata del provider.aborted_after_provider_completion: il provider ha completato, ma il client downstream si è chiuso prima che il gateway terminasse l'inoltro.settled_from_estimate: il registro dell'inquilino ha utilizzato una stima perché l'utilizzo finale non era disponibile.reconciliation_adjusted_usage: il reporting del fornitore ha successivamente modificato la riga.
Fatto: le convenzioni semantiche di OpenTelemetry GenAI consigliano di utilizzare le informazioni sull'utilizzo restituite dal provider per le risposte in streaming quando disponibili e mettono in guardia dal segnalare le metriche di utilizzo se i conteggi dei token non possono essere ottenuti in modo efficiente o accurato.
Per l'analisi dell'utilizzo dell'intelligenza artificiale, ciò significa che le dashboard dovrebbero supportare i livelli di confidenza. Un grafico che mescola valori finali, stimati e riconciliati senza etichette può sembrare pulito ma fuorviare i team finanziari e di supporto.
Test di conformità per la contabilità in streaming
Non fare affidamento sui test manuali con una richiesta di chat di percorso felice. Ogni adattatore del provider dovrebbe disporre di test di conformità per i casi che violano i registri:
- Flusso normale: arriva l'utilizzo finale, viene osservato l'evento interrotto, il registro viene stabilito come
finale. - Flusso di chiamate allo strumento: i delta delle chiamate allo strumento vengono inoltrati, l'utilizzo viene acquisito, i metadati strutturati non danneggiano il conteggio dei token.
- Arresto di sicurezza o rifiuto: il fornitore si interrompe anticipatamente, l'utilizzo si regola comunque correttamente.
- Disconnessione forzata del client: il downstream si chiude dopo l'output parziale; upstream viene annullato o continuato secondo la politica.
- Upstream 5xx dopo output parziale: il gateway registra la consegna parziale e non contrassegna la richiesta come un successo netto.
- Timeout del gateway prima dell'utilizzo finale: la riga viene stimata o è in attesa di riconciliazione.
- Evento finale mancante: l'adattatore emette
final_usage_missinged evita etichette di fatturazione esatte.
Questi test dovrebbero accertare le transizioni di stato, i campi del registro, gli eventi di osservabilità emessi e il comportamento a valle. La compatibilità del flusso byte per byte non è sufficiente; gli effetti collaterali contabili fanno parte del contratto.
Lista di controllo pratica dell'implementazione
- Crea la riga del registro di utilizzo prima di inviare la richiesta upstream.
- Archivia tenant, chiave, utente, modello, percorso, provider e identificatori di richiesta al momento della richiesta.
- Abilita il reporting sull'utilizzo finale del provider, ove supportato, come
stream_options.include_usagecompatibile con OpenAI. - Per i provider cumulativi, memorizza il valore di utilizzo più recente invece di sommare gli eventi.
- Conserva gli oggetti di risposta aggregati quando gli SDK li forniscono.
- Monitora l'output consegnato separatamente dall'utilizzo fatturato dal fornitore.
- Alla disconnessione, annulla l'upstream in base alla politica del percorso e contrassegna
client_aborted. - Utilizza stati di fatturazione trasparenti: finale, stimato, riconciliazione in attesa, fornitore riconciliato o rinunciato.
- Emettere eventi di osservabilità specifici della contabilità.
- Riconciliazione successiva con i report sull'utilizzo o sui costi del provider, se disponibili, preservando l'attribuzione del tenant in base al momento della richiesta.
Cosa mostrare agli inquilini
Gli inquilini non hanno bisogno di ogni evento interno, ma hanno bisogno di etichette oneste. Una tabella di utilizzo utile potrebbe mostrare:
- Stato: definitivo, stimato o riconciliato.
- Risultato della richiesta: completata, client interrotto, errore del provider o timeout del gateway.
- Output consegnato: testo approssimativo o byte inviati al client.
- Token fatturati: utilizzo normalizzato dal fornitore utilizzato per i costi.
- Rettifica: qualsiasi delta di riconciliazione successivo.
Questo design riduce le ambiguità del supporto. Se un utente ha visto solo una parte della risposta, la dashboard può spiegare se il fornitore l'ha già completata, se il gateway ha annullato a monte e se l'addebito è definitivo o stimato.
Consigli e previsioni
Consigli: tratta le richieste trasmesse in streaming come macchine a stati, attendi l'utilizzo finale autorevole prima della liquidazione esatta, separa l'output consegnato dall'utilizzo fatturato ed etichetta le righe stimate in modo onesto. Gli adattatori del provider dovrebbero codificare la semantica di utilizzo specifica del provider anziché appiattire ogni flusso in un proxy di byte generico.
Previsione: la contabilità in streaming diventerà più importante man mano che i modelli espongono più lavoro nascosto: token di ragionamento, sconti sui token memorizzati nella cache, elaborazione multimodale, tracce di utilizzo degli strumenti e fermate di sicurezza. I gateway che già separano l'utilizzo fatturato dal provider dall'output visibile al client si adatteranno più facilmente rispetto ai gateway che conteggiano solo il testo trasmesso in streaming.
Conclusione attuabile
Se il tuo gateway supporta lo streaming, controlla un percorso oggi stesso: forza la disconnessione di un client dopo i primi blocchi e controlla la riga del registro. Se dice "successo" con conteggi di token dall'aspetto esatto, probabilmente le tue analisi mentono.
La soluzione è non abbandonare lo streaming. Mantieni l'esperienza utente veloce, ma rendi espliciti gli stati contabili di completamento del flusso, annullamento, errori del provider, mancato utilizzo finale e riconciliazione. Ciò offre ai team di prodotto risultati reattivi, ai team finanziari costi difendibili e ai team di supporto prove sufficienti per spiegare risposte parziali senza tirare a indovinare.