fix(translator): merge input/cache token usage reported on Anthropic message_delta - #2292
Conversation
|
@pjdurden Hi, thanks for working on this, I originally planned to open a PR for this after filing the issue, but you got to it first. This addresses the main case. One thing I think we should be careful about is merging usage at field level rather than replacing the whole usage snapshot. In real environments, |
|
Thanks, that makes sense and you are right that field presence matters here. Pushed an update that merges per field instead of replacing the whole usage snapshot. It now keeps the latest known value for raw input, cache_read and cache_creation, and only overwrites the ones the message_delta actualy reports (non-zero), then recomputes the unified input_tokens sum. So a delta that carries only cache_read no longer zeros out the input_tokens already set on message_start. output_tokens is taken unconditionally from message_delta since that is always the final value there. I cant distinguish an omitted field from an explicit zero, since the upstream usage fields are plain ints rather than pointers, so non-zero is the best proxy for presence. If you would rather gate this behind a backend flag instead of always-on merging, happy to switch to that. Added a regression test where message_start sets input=1000 and the delta reports only cache_read=500, asserting the merged total stays 1500 instead of collapsing to 500. |
|
Thanks! @pjdurden can you fix the DCO? |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2292 +/- ##
==========================================
+ Coverage 84.86% 84.87% +0.01%
==========================================
Files 145 145
Lines 21518 21534 +16
==========================================
+ Hits 18261 18277 +16
Misses 2161 2161
Partials 1096 1096 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…message_delta Anthropic Messages streaming usage extraction read input and cache token counts only from message_start, and on message_delta it updated output tokens alone. Some Anthropic-compatible backends instead report the final input_tokens / cache_creation_input_tokens / cache_read_input_tokens on the message_delta event, so those counts were dropped and recorded as zero, corrupting usage metrics and any downstream cost/quota accounting. Merge the input and cache fields when message_delta carries them, reusing the same ExtractTokenUsageFromExplicitCaching path as message_start. The fields are only merged when non-zero so a standard delta carrying output tokens only does not clobber the message_start baseline. Fixes envoyproxy#2290 Signed-off-by: pjdurden <prajjwalchittori1@gmail.com>
Signed-off-by: pjdurden <prajjwalchittori1@gmail.com>
ee0ef8d to
527375a
Compare
…message_delta (envoyproxy#2292) **Description** Anthropic Messages streaming usage extraction reads input and cache token counts from `message_start`, and on `message_delta` it only updates `output_tokens`. Some Anthropic-compatable backends report the final `input_tokens`, `cache_creation_input_tokens` and `cache_read_input_tokens` on the `message_delta` event instead. In that case the input and cache counts get dropped and recorded as zero, which corrupts usage metrics and any downstream cost or quota accounting that depends on them. This runs the `message_delta` usage through the same `ExtractTokenUsageFromExplicitCaching` path already used for `message_start` and merges it with `Override`. The fields are only merged when non-zero, so a standard delta that carries `output_tokens` alone doesnt overwrite the `message_start` baseline with zeros. **Related Issues/PRs (if applicable)** Fixes envoyproxy#2290 **Special notes for reviewers (if applicable)** Added two streaming subtests (cache-creation and cache-read variants) using the values from the issue: `input_tokens` 4522 + cache 4511 gives 9033 input total and 9038 total. They fail on main and pass with this change. The existing streaming and non-streaming usage tests are untouched. --------- Signed-off-by: pjdurden <prajjwalchittori1@gmail.com> Co-authored-by: Ignasi Barrera <ignasi@tetrate.io> Signed-off-by: Daniel Chernovsky <daniel.chernovsky@doubleverify.com>
Description
Anthropic Messages streaming usage extraction reads input and cache token counts from
message_start, and onmessage_deltait only updatesoutput_tokens. Some Anthropic-compatable backends report the finalinput_tokens,cache_creation_input_tokensandcache_read_input_tokenson themessage_deltaevent instead. In that case the input and cache counts get dropped and recorded as zero, which corrupts usage metrics and any downstream cost or quota accounting that depends on them.This runs the
message_deltausage through the sameExtractTokenUsageFromExplicitCachingpath already used formessage_startand merges it withOverride. The fields are only merged when non-zero, so a standard delta that carriesoutput_tokensalone doesnt overwrite themessage_startbaseline with zeros.Related Issues/PRs (if applicable)
Fixes #2290
Special notes for reviewers (if applicable)
Added two streaming subtests (cache-creation and cache-read variants) using the values from the issue:
input_tokens4522 + cache 4511 gives 9033 input total and 9038 total. They fail on main and pass with this change. The existing streaming and non-streaming usage tests are untouched.