Vejledning og indsigt

Streaming af tokenregnskab i en AI API-gateway: endelig brug, annulleringer og delvise svar

Streaming forbedrer den opfattede latenstid, men det kan bryde AI-brugsanalyse og fakturering, hvis gatewayen kun proxyer bytes. Her er et praktisk tilstandsmaskine-mønster til at fange endelig brug, afbrudte streams, udbyderfejl og delvise svar.

Streaming af LLM-svar er nemme at proxy og svære at fakturere korrekt. Hvis en AI API-gateway videresender server-sendte hændelser til klienten, men behandler de første bidder som brugsposten, vil lejeranalysen glide. Afvigelsen opstår normalt i tvister som: "brugeren så kun halvdelen af svaret", "udbyderen fakturerede mere end vores dashboard viser", "kvoten blev frigivet for tidligt" eller "en timeout producerede tokens, men ingen fakturalinje."

Hovedproblemet er, at streamede opkald ikke er én begivenhed. De er en sekvens: anmodning accepteret, upstream stream åbnet, bytes leveret, endelig brug rapporteret, udbyder stoppet, klient afbrudt, gateway timeout, og fakturering afgjort. En pålidelig gateway bør modellere disse tilstande eksplicit i stedet for at antage, at et gennemført HTTP-svar er den eneste succesfulde sti.

Fejltilstanden: streaming skjuler regnskabsgrænsen

Ikke-streamede fuldførelser returnerer normalt ét svarobjekt med brugsmetadata. En gateway kan normalisere denne brug, skrive en hovedbogsrække, opdatere kvote og udsende analyser på én gang.

Streaming ændrer grænsen. Brugeroplevelsen er inkrementel, men faktureringssandheden kan komme til sidst, i en udbyderspecifik sluthændelse, i et kumulativt delta, gennem et aggregeret SDK-svar eller senere gennem udbyderrapporterings-API'er. Hvis klienten afbryder forbindelsen før den endelige brugshændelse, har gatewayen muligvis kun leveret en del af svaret, mens udbyderen stadig genererede og fakturerede flere tokens.

Faktum: OpenAI dokumenterer, at streaming-opkaldere, der ønsker brugsdata, skal indstille stream_options med include_usage. OpenAI leverer også forbrugs- og omkostningsendepunkter på organisationsniveau, samtidig med at det bemærkes, at forbrug og omkostninger muligvis ikke altid passer perfekt til økonomiske formål.

Fakta: Antropisk streaming bruger serversendte hændelser såsom message_start, content_block_delta, message_delta og message_stop. Dens message_delta-brugsoplysninger er kumulative, så en gateway må ikke lægge hvert brugsdelta sammen.

Fakta: Streaming-API'er i Gemini- og Vertex-stil kan afsløre trinvise bidder, mens SDK'er også kan levere et aggregeret svarobjekt. For gateways kan den aggregerede sti være en bedre kilde til fuldført brug end de synlige bidder alene.

Brug en strømtilstandsmaskine, ikke et boolsk succesflag

En streamet anmodning skal have en holdbar brugsregistrering, før upstream-opkaldet starter. Denne registrering bør bevæge sig gennem eksplicitte tilstande. Et praktisk minimum er:

  • accepteret: gatewayen godkendte nøglen, tildelte lejeren og oprettede en åben hovedbogsrække.
  • first_byte_sent: mindst én outputhændelse nåede downstream-klienten.
  • provider_completed: opstrømsudbyderen udsendte et normalt stopsignal eller et afsluttet svarobjekt.
  • client_aborted: downstream-socket lukket før normal gateway-afslutning.
  • provider_error: opstrømsudbyderen returnerede en fejl, efter streamen begyndte, eller før den endelige brug ankom.
  • gateway_timeout: Gatewayen håndhævede sit latensbudget og afsluttede anmodningen.
  • afregnet: gatewayen konverterede forbrug til lejeromkostninger og kvoteforbrug.
  • afstemt: senere udbyderbrug eller omkostningsdata bekræftet eller justeret rækken.

Denne model forhindrer en almindelig analysefejl: markering af hver strøm, der producerede tekst, som "vellykket og nøjagtig." En strøm kan være nyttig for brugeren, ufuldstændig fra udbyderen, estimeret til fakturering og afventende afstemning på samme tid.

Anbefalede finansfelter

Hold rækken for anmodningstid lille, men eksplicit:

{ "request_id": "gw_req_...", "tenant_id": "tenant_123", "api_key_id": "key_456", "provider": "openai|antropisk|gemini|...", "provider_request_id": null, "model": "udbyder-model-id", "state": "accepteret", "stream": sandt, "input_tokens": null, "output_tokens_billed": null, "output_tokens_delivered_estimate": 0, "provider_usage_source": null, "billing_status": "afventende_afstemning", "client_abort_at": null, "provider_completed_at": null, "settled_at": null, "error_class": null }

Den vigtige adskillelse er output_tokens_billed versus output_tokens_delivered_estimate. Brugerne bekymrer sig om, hvad der nåede deres ansøgning. Finans bekymrer sig om, hvad udbyderen fakturerede. Disse tal kan variere efter afbrydelser, værktøjsopkaldsstreams, skjulte ræsonnementstokens, cachede tokens, sikkerhedsstop eller gateway-timeouts.

Udbyderspecifikke optagelsesregler

En udbyderneutral OpenAI-kompatibel API er nyttig for applikationsudviklere, men gateway-adapteren har stadig brug for udbyderspecifikke regnskabsregler.

OpenAI-kompatibel streaming

For OpenAI-ruter skal du blotlægge en gateway-indstilling, der muliggør opstrømsbrugsrapportering, hvor det understøttes. Et almindeligt mønster er at acceptere en standard på gateway-niveau såsom:

{ "stream": sandt, "stream_options": { "include_usage": sand } }

Hvis downstream-opkalderen udelader det, kan gatewayen beslutte, om det skal injicere det til ruter, hvor det er kompatibelt. Dokumenter denne adfærd, fordi nogle klienter forventer nøjagtig ledningskompatibilitet, og nogle modeller eller upstreams understøtter muligvis ikke endelig brug på samme måde.

Anbefaling: Afreg ikke lejeromkostninger fra tidlige bidder. Hold hovedbogsrækken åben, indtil den endelige brugshændelse er fanget, udbyderens svar slutter uden brug, eller streamen indtaster en fejl- eller annulleringssti.

Antropisk streaming

Anthropics kumulative brug kræver en anden regel. Hvis en gateway ser tre message_delta hændelser med output token-tællinger på 10, 25 og 40, er output-tællingen 40, ikke 75.

let latestUsage = null;
for afvent (const event of anthropicStream) {
  if (event.type === "message_delta" && event.usage) {
    if (latestUsage && event.usage.output_tokens < latestUsage.output_tokens) {
      emit("kumulativ_forbrug_regresseret", requestId);
    }
    latestUsage = begivenhed.brug;
  }
  forwardToClient(hændelse);
}
settleFromLatest CumulativeUsage(latestUsage);

Anbefaling: Registrer den seneste kumulative brugsværdi, og udsend en observerbarhedshændelse, hvis den regresserer. En regression kan indikere parser-fejl, duplikerede hændelser, udbyderændringer eller blandede streams.

Streaming i Gemini og Vertex-stil

Gemini understøtter streaming chunks for at reducere opfattet latens. I Vertex-stil SDK'er kan streaming afsløre både en asynkron stream og et aggregeret svarobjekt. En gateway bør bevare den aggregerede sti, når den er tilgængelig.

const streamingResult = await model.generateContentStream(request);
for afvent (konst. del af streamingResult.stream) {
  forwardChunk(chunk);
  countDeliveredBytesOrText(chunk);
}
const aggregeret = afvent streamingResult.response;
settleFromAggregatedUsage(aggregeret);

Anbefaling: undgå at opbygge alt regnskab fra synlige bidder, hvis SDK'et giver en fuldført svarpost. Chunks er til latenstid. Det endelige objekt er ofte bedre til fakturering og analyser.

Håndter klientafbrydelser som førsteklasses regnskabsbegivenheder

Kundeafbrydelser er, hvor mange gateways taber penge eller overbeviser kunder. En browserfane lukkes, et mobilnetværk falder, eller en applikation annullerer en anmodning. Gatewayen bemærker, at downstream-socket er lukket, men upstream-udbyderen genererer muligvis stadig.

Gatewayen bør træffe et eksplicit politikvalg:

  • Annuller upstream med det samme: reducerer spildproduktion og udbyderomkostninger, men kan bryde arbejdsgange, hvor backend stadig har brug for resultatet, efter at brugergrænsefladen afbrydes.
  • Fortsæt opstrøms i baggrunden: kan bevare arbejde for forbrugere på serversiden, men brugeren kan muligvis ikke se alle tokens genereret og faktureret.
  • Ruteafhængig adfærd: Annuller for interaktiv chat, fortsæt for joblignende arbejdsgange, og gør indstillingen synlig for lejere.

En praktisk standard for interaktiv streaming er at annullere upstream, når downstream-klienten afbryder forbindelsen, og derefter markere finansrækken som client_aborted. Hvis den endelige brug ankommer under annulleringen, skal du afregne fra den autoritative brug. Hvis ikke, skal du markere rækken estimeret eller pending_reconciliation i stedet for at lade som om, den er nøjagtig.

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

Anbefaling: Vis gennemsigtige faktureringsetiketter såsom final, provider_reconciled, estimeret, waived eller pending_reconciliation. Dette er mere forsvarligt end at vise hvert streamet opkald som umiddelbart nøjagtigt.

Kvotehåndhævelse under en stream

Nøjagtig fakturering afhænger normalt af den endelige udbyderbrug, men kvotehåndhævelse kan ikke altid vente til slutningen. En lejer med et hårdt budget bør ikke have lov til at streame på ubestemt tid, fordi den nøjagtige brug ikke er tilgængelig midt på flyvningen.

Brug to mekanismer sammen:

  1. Preflight reservation: reserver et estimeret maksimum baseret på model, anmodede maks. tokens, lejerpolitik og nuværende saldo.
  2. Tjek af streamingtryk: estimer leveret output under streamen og stop, hvis anmodningen krydser en konfigureret sikkerhedsgrænse.

Dette er en kontrolmekanisme, ikke den endelige regning. Udbydere kan tælle cachelagrede tokens, ræsonnementstokens, multimodale tokens eller skjulte tokens anderledes end en gateways estimator.

Afvejning: Realtidsestimater hjælper med at håndhæve budgetter, men de kan afvige fra udbyderfakturerede tokens. Endelig afregning bør bruge autoritativ udbyderbrug, når den er tilgængelig, og afstemning bør justere estimater senere.

Observationshændelser, der fanger regnskabsfejl

Streaming-faktureringsfejl er nemmere at fejlfinde, når gatewayen udsender målrettede hændelser i stedet for kun generiske anmodningslogfiler. Tilføj begivenheder såsom:

  • final_usage_missing: Stream sluttede uden autoritativ brug.
  • cumulative_usage_regressed: kumulativt antal tokens flyttet tilbage.
  • stream_ended_without_stop_event: ingen normal udbyderstopmarkør blev observeret.
  • aborted_after_provider_completion: udbyderen fuldførte, men downstream-klienten lukkede, før gatewayen afsluttede videresendelsen.
  • afregnet_fra_estimate: lejerregnskabet brugte et estimat, fordi den endelige brug ikke var tilgængelig.
  • reconciliation_adjusted_usage: udbyderrapportering ændrede senere rækken.

Faktum: OpenTelemetry GenAI semantiske konventioner anbefaler at bruge udbyder returnerede brugsoplysninger til streamingsvar, når de er tilgængelige, og advarer mod at rapportere brugsmetrics, hvis tokenantal ikke kan opnås effektivt eller præcist.

For AI-brugsanalyse betyder det, at dashboards skal understøtte konfidensniveauer. Et diagram, der blander endelige, estimerede og afstemte værdier uden etiketter, kan se rent ud, men vildlede økonomi- og supportteams.

Konformitetstest for streaming-regnskab

Bliv ikke afhængig af manuel test med en happy-path chat-prompt. Hver udbyderadapter skal have overensstemmelsestests for de sager, der bryder hovedbøger:

  • Normal strøm: endelig brug ankommer, stop hændelse observeret, hovedbog afregnes som endelig.
  • Værktøjsopkaldsstrøm: Værktøjsopkaldsdeltaer videresendes, brug registreres, strukturerede metadata ødelægger ikke tokenoptælling.
  • Sikkerheds- eller afvisningsstop: Udbyderen stopper tidligt, brugen afvikles stadig korrekt.
  • Tvungen klientafbrydelse: nedstrøms lukker efter delvis output; upstream annulleres eller fortsættes i henhold til politikken.
  • Upstream 5xx efter delvis output: Gateway registrerer delvis levering og markerer ikke anmodningen som en ren succes.
  • Gateway-timeout før endelig brug: rækken bliver estimeret eller afventer afstemning.
  • Manglende sidste hændelse: adapter udsender final_usage_missing og undgår nøjagtige faktureringsetiketter.

Disse tests skal bekræfte tilstandsovergange, hovedbogsfelter, udsendte observerbarhedshændelser og downstream-adfærd. Byte-for-byte stream-kompatibilitet er ikke nok; de regnskabsmæssige bivirkninger er en del af kontrakten.

Tjekliste for praktisk implementering

  • Opret brugsreskontro-rækken, før du sender upstream-anmodningen.
  • Butikslejer, nøgle, bruger, model, rute, udbyder og anmodnings-id'er på anmodningstidspunktet.
  • Aktiver udbyderens endelige brugsrapportering, hvor det understøttes, såsom OpenAI-kompatibel stream_options.include_usage.
  • For kumulative udbydere skal du gemme den seneste brugsværdi i stedet for at summere hændelser.
  • Bevar aggregerede svarobjekter, når SDK'er leverer dem.
  • Spor leveret output separat fra udbyderfaktureret brug.
  • Ved afbrydelse skal du annullere opstrøms i henhold til rutepolitikken og markere client_aborted.
  • Brug gennemsigtige faktureringsstatusser: endelig, estimeret, afventende afstemning, udbyder afstemt eller frafaldet.
  • Udgiv regnskabsspecifikke observerbarhedshændelser.
  • Afstem senere med udbyderbrugs- eller omkostningsrapporter, når de er tilgængelige, samtidig med at lejertilskrivning på anmodningstid bevares.

Hvad skal man vise lejere

Lejere har ikke brug for alle interne begivenheder, men de har brug for ærlige etiketter. En nyttig brugstabel kan vise:

  • Status: endelig, estimeret eller afstemt.
  • Anmodningsresultat: fuldført, klient afbrudt, udbyderfejl eller gateway-timeout.
  • Leveret output: omtrentlig tekst eller bytes sendt til klienten.
  • Fakturerede tokens: udbydernormaliseret brug brugt til omkostninger.
  • Justering: enhver senere afstemningsdelta.

Dette design reducerer support-uklarhed. Hvis en bruger kun så en del af et svar, kan dashboardet forklare, om udbyderen allerede havde gennemført, om gatewayen blev annulleret opstrøms, og om debiteringen er endelig eller estimeret.

Anbefalinger versus forudsigelser

Anbefalinger: Behandl streamede anmodninger som statsmaskiner, vent på autoritativ endelig brug før nøjagtig afregning, adskil leveret output fra faktureret brug, og mærk estimerede rækker ærligt. Udbyderadaptere bør indkode udbyderspecifik brugssemantik i stedet for at udjævne hver stream til en generisk byte-proxy.

Forudsigelse: Streamingregnskab vil blive vigtigere, efterhånden som modeller afslører mere skjult arbejde: ræsonnementstokens, cache-tokenrabatter, multimodal behandling, sporing af værktøjsbrug og sikkerhedsstop. Gateways, der allerede adskiller udbyderfaktureret brug fra klientsynligt output, tilpasser sig lettere end gateways, der kun tæller streamet tekst.

Aktiv konklusion

Hvis din gateway understøtter streaming, skal du kontrollere én sti i dag: Tving en klient afbrydelse efter de første par bidder, og inspicér hovedbogsrækken. Hvis der står "succes" med nøjagtigt udseende token-tællinger, lyver dine analyser sandsynligvis.

Løsningen er ikke at opgive streaming. Bevar den hurtige brugeroplevelse, men gør strømafslutning, annullering, udbyderfejl, manglende endelig brug og afstemning eksplicitte regnskabstilstande. Det giver produktteams responsivt output, finansiere teams forsvarlige omkostninger og supportteams nok beviser til at forklare delvise svar uden at gætte.

Relateret læsning

FAQ

Ofte stillede spørgsmål

Skal en gateway-regning streame svar fra estimerede token-antal?
Brug estimater for kvotebeskyttelse i realtid, når det er nødvendigt, men afregn nøjagtige lejeromkostninger fra udbyderretureret brug, når det er tilgængeligt. Hvis den endelige brug mangler, skal du mærke rækken som estimeret eller afventende afstemning.
Hvorfor kan leverede output-tokens afvige fra fakturerede tokens?
Klienten kan afbryde forbindelsen, gatewayen kan timeout, udbyderen kan tælle skjulte ræsonnementer eller multimodale tokens, eller en udbyder kan afslutte genereringen, efter at brugeren holder op med at modtage bytes. Spor leveret output separat fra udbyderfaktureret brug.
Hvad er den mest almindelige antropiske streaming-regnskabsfejl?
Opsummering af kumulative brugshændelser. Antropiske message_delta-forbrugstællinger er kumulative, så gatewayen bør gemme den seneste værdi i stedet for at tilføje hver hændelse.
Hvad skal der ske, når en browser afbryder forbindelsen under en stream?
For interaktive ruter er en praktisk standard at annullere opstrømsanmodningen, markere hovedbogsrækken som client_aborted og kun afregne fra autoritativ udbyderbrug, hvis den ankommer. Ellers markerer rækken estimeret eller afventende afstemning.