record_message_usage(
stats: SessionStats,
message: object,
*,
fallback_model: str = | Name | Type | Description |
|---|---|---|
stats* | SessionStats | Accumulator that receives the request. |
message* | object | Streamed model message or chunk. |
fallback_model | str | Default: ''Model to use when response metadata does not name one. |
fallback_provider | str | Default: '' |
request_metadata | Mapping[str, Any] | None | Default: None |
kind | UsageKind | Default: 'assistant' |
recorded_requests | dict[str, RecordedRequest] | None | Default: None |
Record usage attached to one streamed model message.
A request is entered in recorded_requests only once usable token metadata
has been recorded for it. Callers retain that ledger across stream rounds so
one API call stays one row, however its usage arrives.
A streamed chunk and a completed message report usage differently, so they
are handled differently. A completed AIMessage carries the request's
whole usage and is idempotent: replaying it must not count twice. A chunk
carries whatever the provider chose to emit at that point in the stream --
Anthropic and OpenAI attach the full usage to one chunk, while Google emits
an incremental delta on every chunk, which the consumer is expected to sum.
Skipping a chunk whose ID was already seen would drop every Google chunk
after the first, losing most of the request's output tokens and cost.
Summing them as separate requests would be wrong in the other direction, so a later chunk instead revises the request already recorded: its earlier contribution is retracted and re-recorded with the running totals. One API call therefore counts once, with one per-model row, no matter how many chunks carried its usage. Google also names the model only on its final chunk, so the model is upgraded when a message supplies one and otherwise left alone -- without that, one call would straddle a fallback-model row and a real-model row.
Provider to use when response metadata omits it.
Stream metadata identifying the provider configured for this specific request, when available.
Request class used by the type breakdown.
Ledger of requests this stream consumer has already recorded, keyed by message ID. Mutated in place.