Guide och insikt

Strömmande tokenredovisning i en AI API-gateway: slutlig användning, avbokningar och partiella svar

Streaming förbättrar upplevd latens, men det kan bryta AI-användningsanalyser och fakturering om gatewayen bara proxar byte. Här är ett praktiskt tillståndsmaskinmönster för att fånga slutlig användning, avbrutna strömmar, leverantörsfel och partiella svar.

Strömmande LLM-svar är lätta att proxy och svåra att fakturera korrekt. Om en AI API-gateway vidarebefordrar serversända händelser till klienten men behandlar de första bitarna som användningsposten, kommer klientanalyserna att glida. Avvikelsen uppträder vanligtvis i tvister som: "användaren såg bara halva svaret", "leverantören fakturerade mer än vad vår instrumentpanel visar", "kvoten släpptes för tidigt" eller "en timeout gav tokens men ingen fakturarad."

Rotproblemet är att streamade samtal inte är en händelse. De är en sekvens: begäran accepterad, uppströmsström öppnad, bytes levererade, slutlig användning rapporterad, leverantör stoppad, klient frånkopplad, gateway tog timeout och fakturering klar. En pålitlig gateway bör modellera dessa tillstånd explicit istället för att anta att ett slutfört HTTP-svar är den enda framgångsrika vägen.

Fejlläget: streaming döljer redovisningsgränsen

Icke-strömmade slutföranden returnerar vanligtvis ett svarsobjekt med användningsmetadata. En gateway kan normalisera den användningen, skriva en redovisningsrad, uppdatera kvoten och avge analyser i en omgång.

Streaming ändrar gränsen. Användarupplevelsen är inkrementell, men faktureringssanningen kan komma i slutet, i en leverantörsspecifik sluthändelse, i ett kumulativt delta, genom ett aggregerat SDK-svar eller senare genom API:er för leverantörsrapportering. Om klienten kopplar bort före den slutliga användningshändelsen kan gatewayen ha levererat bara en del av svaret medan leverantören fortfarande genererade och fakturerade fler tokens.

Fakta: OpenAI dokumenterar att strömmande uppringare som vill ha användningsdata bör ställa in stream_options med include_usage. OpenAI tillhandahåller också användnings- och kostnadsslutpunkter på organisationsnivå, samtidigt som det noteras att användning och kostnader kanske inte alltid stämmer överens för ekonomiska ändamål.

Fakta: Antropisk strömning använder serversända händelser som meddelande_start, innehållsblock_delta, meddelande_delta och meddelande_stopp. Dess message_delta användningsinformation är kumulativ, så en gateway får inte lägga till varje användningsdelta.

Fakta: Streaming-API:er i stil med Gemini och Vertex kan exponera inkrementella bitar medan SDK:er också kan tillhandahålla ett aggregerat svarsobjekt. För gateways kan den aggregerade sökvägen vara en bättre källa för fullbordad användning än bara de synliga bitarna.

Använd en strömtillståndsmaskin, inte en boolesk framgångsflagga

En streamad begäran bör ha en hållbar användningspost innan uppströmssamtalet startar. Den posten bör röra sig genom explicita tillstånd. Ett praktiskt minimum är:

  • accepterad: gatewayen autentiserade nyckeln, tillskrev hyresgästen och skapade en öppen redovisningsrad.
  • first_byte_sent: minst en utdatahändelse nådde nedströmsklienten.
  • provider_completed: uppströmsleverantören avgav en normal stoppsignal eller ett färdigt svarsobjekt.
  • client_aborted: nedströmsuttaget stängdes innan normal gateway färdigställdes.
  • provider_error: uppströmsleverantören returnerade ett fel efter att streamen började eller innan den slutliga användningen kom.
  • gateway_timeout: gatewayen genomförde sin latensbudget och avslutade begäran.
  • avgjord: gatewayen omvandlade användningen till hyresgästkostnad och kvotförbrukning.
  • avstämt: senare leverantörsanvändning eller kostnadsdata bekräftade eller justerade raden.

Denna modell förhindrar en vanlig analysbugg: markerar varje stream som producerade text som "lyckad och exakt." En ström kan vara användbar för användaren, ofullständig från leverantören, uppskattad för fakturering och pågående avstämning samtidigt.

Rekommenderade reskontrafält

Håll raden för begäran-tid liten men tydlig:

{
  "request_id": "gw_req_...",
  "tenant_id": "tenant_123",
  "api_key_id": "key_456",
  "provider": "openai|antropisk|tvillingarna|...",
  "provider_request_id": null,
  "model": "leverantör-modell-id",
  "state": "accepterat",
  "ström": sant,
  "input_tokens": null,
  "output_tokens_billed": null,
  "output_tokens_delivered_estimate": 0,
  "provider_usage_source": null,
  "billing_status": "väntande_avstämning",
  "client_abort_at": null,
  "provider_completed_at": null,
  "settled_at": null,
  "error_class": null
}

Den viktiga separationen är output_tokens_billed kontra output_tokens_delivered_estimate. Användarna bryr sig om vad som nådde deras ansökan. Finans bryr sig om vad leverantören fakturerar. Dessa siffror kan skilja sig efter frånkopplingar, verktygssamtalströmmar, dolda resonemangstokens, cachade tokens, säkerhetsstopp eller gateway-timeout.

Leverantörsspecifika fångstregler

Ett leverantörsneutralt OpenAI-kompatibelt API är användbart för applikationsutvecklare, men gatewayadaptern behöver fortfarande leverantörsspecifika redovisningsregler.

OpenAI-kompatibel streaming

För OpenAI-rutter, exponera ett gatewayalternativ som möjliggör uppströmsanvändningsrapportering där det stöds. Ett vanligt mönster är att acceptera en standard på gatewaynivå som:

{
  "ström": sant,
  "stream_options": {
    "inkludera_användning": sant
  }
}

Om nedströmsuppringaren utelämnar det, kan gatewayen bestämma om den ska injiceras för rutter där det är kompatibelt. Dokumentera detta beteende eftersom vissa klienter förväntar sig exakt trådkompatibilitet och vissa modeller eller uppströms kanske inte stöder slutlig användning på samma sätt.

Rekommendation: betala inte hyresgästkostnader från tidiga delar. Håll reskontraraden öppen tills den slutliga användningshändelsen registreras, leverantörens svar avslutas utan användning eller strömmen anger en fel- eller avbokningsväg.

Antropisk streaming

Anthropics kumulativa användning kräver en annan regel. Om en gateway ser tre meddelande_delta-händelser med utdatatokental på 10, 25 och 40, är utdataantalet 40, inte 75.

låt 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);
    }
    senasteUsage = händelse.användning;
  }
  forwardToClient(händelse);
}
settleFromLatest CumulativeUsage(latestUsage);

Rekommendation: registrera det senaste kumulativa användningsvärdet och avge en observerbarhetshändelse om den går tillbaka. En regression kan indikera parserbuggar, dubblerade händelser, leverantörsbyten eller blandade strömmar.

Strömmande i Gemini och Vertex-stil

Gemini stöder streaming-bitar för att minska upplevd latens. I Vertex-stil SDK:er kan streaming exponera både en asynkron ström och ett aggregerat svarsobjekt. En gateway bör bevara den aggregerade sökvägen när den är tillgänglig.

const streamingResult = await model.generateContentStream(request);
for await (konst bit av streamingResult.stream) {
  forwardChunk(chunk);
  countDeliveredBytesOrText(chunk);
}
const aggregerad = väntar på streamingResult.response;
settleFromAggregatedUsage(aggregated);

Rekommendation: undvik att bygga all redovisning från synliga delar om SDK:n ger en komplett svarspost. Bitar är för latens. Det slutliga objektet är ofta bättre för fakturering och analys.

Hantera klientavbrott som förstklassiga redovisningshändelser

Klientavbrott är där många gateways förlorar pengar eller överdebiterar kunder. En webbläsarflik stängs, ett mobilnät avbryts eller en applikation avbryter en begäran. Gatewayen märker att nedströmsuttaget är stängt, men uppströmsleverantören kanske fortfarande genererar.

Gatewayen bör göra ett explicit policyval:

  • Avbryt uppströms omedelbart: minskar slöseri med generering och leverantörskostnader, men kan bryta arbetsflöden där backend fortfarande behöver resultatet efter att gränssnittet kopplats bort.
  • Fortsätt uppströms i bakgrunden: kan bevara arbetet för konsumenter på serversidan, men användaren kanske inte ser alla tokens som genereras och faktureras.
  • Ruttberoende beteende: avbryt för interaktiv chatt, fortsätt för jobbliknande arbetsflöden och gör inställningen synlig för hyresgäster.

En praktisk standard för interaktiv streaming är att avbryta uppströms när nedströmsklienten kopplar från, och sedan markera reskontraraden som client_aborted. Om den slutliga användningen anländer under avbokningen, löser du dig från den auktoritativa användningen. Om inte, markera raden estimated eller pending_reconciliation istället för att låtsas att den är exakt.

downstream.on("close", async () => {
  if (!providerCompleted) {
    ledger.markClientAborted(requestId);
    await upstream.abort().catch(() => {
      ledger.emit("upstream_cancel_failed", requestId);
    });
  }
});

Rekommendation: exponera genomskinliga faktureringsetiketter som final, provider_reconciled, estimated, waived eller pending_reconciliation. Detta är mer försvarbart än att visa varje streamat samtal som omedelbart exakt.

Kvottillämpning under en stream

Korrekt fakturering beror vanligtvis på den slutliga leverantörsanvändningen, men kvottillämpningen kan inte alltid vänta till slutet. En hyresgäst med en hård budget bör inte tillåtas streama på obestämd tid eftersom exakt användning inte är tillgänglig under flygningen.

Använd två mekanismer tillsammans:

  1. Reservation i förväg: reservera ett uppskattat maximum baserat på modell, begärda maxpoletter, hyresgästpolicy och aktuellt saldo.
  2. Strömmande tryckkontroller: uppskatta levererad uteffekt under streamen och stoppa om begäran passerar en konfigurerad säkerhetsgräns.

Detta är en kontrollmekanism, inte den slutliga notan. Leverantörer kan räkna cachade tokens, resonemangstokens, multimodala tokens eller dolda tokens annorlunda än en gateways skattare.

Avvägning: realtidsuppskattningar hjälper till att genomdriva budgetar, men de kan avvika från leverantörsfakturerade tokens. Slutavräkning bör använda auktoritativ leverantörsanvändning när det är tillgängligt, och avstämning bör justera uppskattningar senare.

Observerbarhetshändelser som fångar redovisningsfel

Strömmande faktureringsfel är lättare att felsöka när gatewayen avger riktade händelser istället för bara generiska förfrågningsloggar. Lägg till händelser som:

  • final_usage_missing: strömmen avslutades utan auktoritativ användning.
  • cumulative_usage_regressed: kumulativt antal token flyttas bakåt.
  • stream_ended_without_stop_event: ingen normal leverantörsstoppmarkör observerades.
  • aborted_after_provider_completion: leverantören slutförde, men nedströmsklienten stängdes innan gatewayen avslutade vidarebefordran.
  • settled_from_estimate: hyresboken använde en uppskattning eftersom slutlig användning inte var tillgänglig.
  • reconciliation_adjusted_usage: leverantörsrapportering ändrade senare raden.

Fakta: OpenTelemetry GenAI semantiska konventioner rekommenderar att du använder leverantörsreturerad användningsinformation för streamingsvar när det är tillgängligt, och varnar för att rapportera användningsstatistik om tokenantal inte kan erhållas effektivt eller korrekt.

För AI-användningsanalys betyder det att instrumentpaneler bör stödja konfidensnivåer. Ett diagram som blandar slutliga, uppskattade och avstämda värden utan etiketter kan se rent ut men vilseleda ekonomi- och supportteam.

Konformitetstester för strömningsredovisning

Förlita dig inte på manuell testning med en chattprompt. Varje leverantörsadapter bör ha överensstämmelsetest för de fall som bryter reskontra:

  • Normal ström: slutlig användning anländer, stopphändelse observeras, reskontran avgörs som slutlig.
  • Verktygsanropsström: verktygsanropsdelta vidarebefordras, användning fångas, strukturerad metadata skadar inte tokenräkningen.
  • Säkerhets- eller vägranstopp: leverantören slutar tidigt, användningen avgörs fortfarande korrekt.
  • Tvingad klientnedkoppling: nedströms stänger efter partiell utmatning; uppströms avbryts eller fortsätter enligt policy.
  • Uppströms 5xx efter partiell utmatning: gateway registrerar delleverans och markerar inte begäran som en ren framgång.
  • Gateway timeout före slutlig användning: raden blir uppskattad eller väntar på avstämning.
  • Sista händelse saknas: adaptern avger final_usage_missing och undviker exakta faktureringsetiketter.

Dessa tester bör bekräfta tillståndsövergångar, reskontrafält, emitterade observerbarhetshändelser och nedströms beteende. Byte-för-byte-strömkompatibilitet är inte tillräckligt; redovisningsbiverkningarna är en del av kontraktet.

Checklista för praktisk implementering

  • Skapa användningsreskontran innan du skickar uppströmsbegäran.
  • Butiksidentifierare för hyresgäst, nyckel, användare, modell, rutt, leverantör och begäran vid begäran.
  • Aktivera rapportering av slutanvändning för leverantörer där det stöds, till exempel OpenAI-kompatibel stream_options.include_usage.
  • För kumulativa leverantörer, lagra det senaste användningsvärdet istället för att summera händelser.
  • Bevara aggregerade svarsobjekt när SDK tillhandahåller dem.
  • Spåra levererade utdata separat från leverantörsfakturerad användning.
  • Vid frånkoppling, avbryt uppströms enligt ruttpolicy och markera client_aborted.
  • Använd transparenta faktureringsstatus: slutlig, beräknad, väntande avstämning, leverantör avstämd eller avstått från.
  • Släpp ut redovisningsspecifika observerbarhetshändelser.
  • Sammanställ senare mot leverantörsanvändning eller kostnadsrapporter när de är tillgängliga, samtidigt som hyresgästtillskrivningen bevaras vid begäran.

Vad ska man visa hyresgäster

Hyresgäster behöver inte alla interna evenemang, men de behöver ärliga etiketter. En användbar användningstabell kan visa:

  • Status: slutlig, uppskattad eller avstämd.
  • Begärans resultat: slutfört, klienten avbruten, leverantörsfel eller gateway-timeout.
  • Leverat utdata: ungefärlig text eller byte som skickas till klienten.
  • Fakturerade tokens: leverantörsnormaliserad användning som används för kostnad.
  • Justering: eventuellt senare avstämningsdelta.

Denna design minskar stödets oklarhet. Om en användare bara såg en del av ett svar kan instrumentpanelen förklara om leverantören redan hade slutfört, om gatewayen avbröts uppströms och om debiteringen är slutgiltig eller beräknad.

Rekommendationer kontra förutsägelser

Rekommendationer: behandla strömmade förfrågningar som tillståndsmaskiner, vänta på auktoritativ slutanvändning innan exakt avräkning, separera levererad utdata från fakturerad användning och märk uppskattade rader ärligt. Leverantörsadaptrar bör koda leverantörsspecifik användningssemantik snarare än att platta ut varje ström till en generisk byteproxy.

Prognos: Strömmande redovisning kommer att bli viktigare när modeller avslöjar mer dolt arbete: resonemangstokens, cachade tokenrabatter, multimodal bearbetning, spårning av verktygsanvändning och säkerhetsstopp. Gateways som redan skiljer leverantörsfakturerad användning från klientsynlig utdata kommer att anpassas lättare än gateways som bara räknar streamad text.

Aktiv slutsats

Om din gateway stöder streaming, granska en sökväg idag: tvinga en klient att koppla från efter de första bitarna och inspektera huvudbokraden. Om det står "framgång" med exakta tokenantal, ljuger din analys förmodligen.

Lösningen är att inte överge streaming. Behåll den snabba användarupplevelsen, men gör strömslutförande, avbokning, leverantörsfel, saknad slutanvändning och avstämning explicita redovisningslägen. Det ger produktteam responsiv produktion, ekonomiteam försvarbara kostnader och supportteam tillräckligt med bevis för att förklara partiella svar utan att gissa.

Relaterad läsning

FAQ

Vanliga frågor

Ska en gateway-faktura strömma svar från uppskattat antal token?
Använd uppskattningar för kvotskydd i realtid vid behov, men bestäm exakt hyresgästkostnad från leverantörens återlämnad användning när det är tillgängligt. Om slutlig användning saknas, märk raden som beräknad eller väntande avstämning.
Varför kan levererade utdata-tokens skilja sig från fakturerade tokens?
Klienten kan koppla från, gatewayen kan ta timeout, leverantören kan räkna dolda resonemang eller multimodala tokens, eller så kan en leverantör avsluta genereringen efter att användaren slutat ta emot bytes. Spåra levererade utdata separat från leverantörsfakturerad användning.
Vilket är det vanligaste antropiska strömningsbokföringsfelet?
Summering av kumulativa användningshändelser. Antalet antropiska message_delta-användningar är kumulativa, så gatewayen bör lagra det senaste värdet istället för att lägga till varje händelse.
Vad ska hända när en webbläsare kopplas från under en stream?
För interaktiva rutter är en praktisk standard att avbryta uppströmsförfrågan, markera reskontraraden som client_aborted och endast avräkna från auktoritativ leverantörsanvändning om den anländer. Markera annars raden beräknad eller väntande avstämning.