fix(responses): only emit cache_write_tokens when reported

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
shivam 2026-09-10 22:10:06 +00:00
parent 302a8d43da
commit 67fc9e4e3d
3 changed files with 16 additions and 32 deletions

View file

@ -2320,15 +2320,9 @@ def _combine_cached_tokens_details(
return (current_value or 0) + (new_value or 0)
return CachedTokensDetails(
text_tokens=_sum_optional(
current.text_tokens if current is not None else None, new.text_tokens
),
audio_tokens=_sum_optional(
current.audio_tokens if current is not None else None, new.audio_tokens
),
image_tokens=_sum_optional(
current.image_tokens if current is not None else None, new.image_tokens
),
text_tokens=_sum_optional(current.text_tokens if current is not None else None, new.text_tokens),
audio_tokens=_sum_optional(current.audio_tokens if current is not None else None, new.audio_tokens),
image_tokens=_sum_optional(current.image_tokens if current is not None else None, new.image_tokens),
)
@ -2355,9 +2349,7 @@ def _combine_prompt_tokens_details(combined: Usage, usage: Usage) -> None:
current_val + new_val,
)
new_cached_tokens_details: Final = getattr(
usage.prompt_tokens_details, "cached_tokens_details", None
)
new_cached_tokens_details: Final = getattr(usage.prompt_tokens_details, "cached_tokens_details", None)
if isinstance(new_cached_tokens_details, CachedTokensDetails):
combined.prompt_tokens_details.cached_tokens_details = _combine_cached_tokens_details(
getattr(combined.prompt_tokens_details, "cached_tokens_details", None),

View file

@ -2683,30 +2683,20 @@ class LiteLLMCompletionResponsesConfig:
if hasattr(usage, "prompt_tokens_details") and usage.prompt_tokens_details is not None:
prompt_details: Final = usage.prompt_tokens_details
cached_tokens_details: Final = getattr(prompt_details, "cached_tokens_details", None)
response_usage.input_tokens_details = InputTokensDetails(
cached_tokens=(
prompt_details.cached_tokens
if hasattr(prompt_details, "cached_tokens") and prompt_details.cached_tokens is not None
else 0
),
text_tokens=(
prompt_details.text_tokens
if hasattr(prompt_details, "text_tokens") and prompt_details.text_tokens is not None
else None
),
audio_tokens=(
prompt_details.audio_tokens
if hasattr(prompt_details, "audio_tokens") and prompt_details.audio_tokens is not None
else None
),
cache_write_tokens=(
getattr(prompt_details, "cache_write_tokens", None)
or getattr(prompt_details, "cache_creation_tokens", None)
),
cache_write_tokens: Final = getattr(prompt_details, "cache_write_tokens", None) or getattr(
prompt_details, "cache_creation_tokens", None
)
input_tokens_details: Final = InputTokensDetails(
cached_tokens=prompt_details.cached_tokens if prompt_details.cached_tokens is not None else 0,
text_tokens=prompt_details.text_tokens,
audio_tokens=prompt_details.audio_tokens,
cached_tokens_details=(
cached_tokens_details if isinstance(cached_tokens_details, CachedTokensDetails) else None
),
)
if cache_write_tokens is not None:
setattr(input_tokens_details, "cache_write_tokens", cache_write_tokens)
response_usage.input_tokens_details = input_tokens_details
# Translate completion_tokens_details to output_tokens_details
if hasattr(usage, "completion_tokens_details") and usage.completion_tokens_details is not None:

View file

@ -2605,6 +2605,7 @@ class TestUsageTransformation:
assert response_usage.input_tokens_details is not None
assert response_usage.input_tokens_details.cached_tokens == 5
assert response_usage.input_tokens_details.text_tokens == 8
assert "cache_write_tokens" not in response_usage.input_tokens_details.model_dump()
def test_transform_usage_with_cached_tokens_gemini(self):
"""Test that cached_tokens from Gemini are properly transformed to input_tokens_details"""
@ -2667,6 +2668,7 @@ class TestUsageTransformation:
assert response_usage.input_tokens_details is not None
assert response_usage.input_tokens_details.cached_tokens == 100
assert getattr(response_usage.input_tokens_details, "cache_write_tokens", None) == 800
assert response_usage.input_tokens_details.model_dump()["cache_write_tokens"] == 800
def test_transform_usage_with_reasoning_tokens_gemini(self):
"""Test that reasoning_tokens from Gemini are properly transformed to output_tokens_details"""