mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-04 02:31:27 +00:00
Merge pull request #41237 from BerriAI/litellm_internal_copy_36887
fix(cost): carry image and video input tokens through the Responses usage bridge (internal copy of #36887)
This commit is contained in:
commit
825e287f63
4 changed files with 38 additions and 0 deletions
|
|
@ -2876,6 +2876,8 @@ class LiteLLMCompletionResponsesConfig:
|
|||
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,
|
||||
image_tokens=prompt_details.image_tokens,
|
||||
video_tokens=prompt_details.video_tokens,
|
||||
cached_tokens_details=(
|
||||
cached_tokens_details if isinstance(cached_tokens_details, CachedTokensDetails) else None
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1194,6 +1194,7 @@ class ResponseAPILoggingUtils:
|
|||
cached_tokens_details=getattr(
|
||||
response_api_usage.input_tokens_details, "cached_tokens_details", None
|
||||
),
|
||||
video_tokens=getattr(response_api_usage.input_tokens_details, "video_tokens", None),
|
||||
cache_write_tokens=getattr(response_api_usage.input_tokens_details, "cache_write_tokens", None),
|
||||
web_search_requests=getattr(response_api_usage.input_tokens_details, "web_search_requests", None),
|
||||
google_maps_grounding_requests=getattr(
|
||||
|
|
|
|||
|
|
@ -1297,7 +1297,9 @@ class InputTokensDetails(BaseLiteLLMOpenAIResponseObject):
|
|||
audio_tokens: int | None = None
|
||||
cached_tokens: int = 0
|
||||
cached_tokens_details: CachedTokensDetails | None = None
|
||||
image_tokens: int | None = None
|
||||
text_tokens: int | None = None
|
||||
video_tokens: int | None = None
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
|
|
|
|||
|
|
@ -2917,6 +2917,39 @@ class TestUsageTransformation:
|
|||
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_preserves_input_modality_tokens(self):
|
||||
"""Regression: the bridge dropped image and video input tokens.
|
||||
|
||||
Vertex reports prompt tokens split by modality, so a Live session that sends
|
||||
camera frames arrives with image_tokens set. InputTokensDetails declared only
|
||||
audio/cached/text, so those tokens were folded into text and lost their
|
||||
attribution, and any per-modality rate could never apply to them.
|
||||
"""
|
||||
usage = Usage(
|
||||
prompt_tokens=300,
|
||||
completion_tokens=10,
|
||||
total_tokens=310,
|
||||
prompt_tokens_details=PromptTokensDetailsWrapper(
|
||||
text_tokens=20, audio_tokens=80, image_tokens=150, video_tokens=50, cached_tokens=0
|
||||
),
|
||||
completion_tokens_details=CompletionTokensDetailsWrapper(text_tokens=10),
|
||||
)
|
||||
|
||||
response_usage = LiteLLMCompletionResponsesConfig._transform_chat_completion_usage_to_responses_usage(
|
||||
chat_completion_response=usage
|
||||
)
|
||||
details = response_usage.input_tokens_details
|
||||
assert details is not None
|
||||
assert getattr(details, "image_tokens", None) == 150
|
||||
assert getattr(details, "video_tokens", None) == 50
|
||||
assert getattr(details, "audio_tokens", None) == 80
|
||||
|
||||
from litellm.responses.utils import ResponseAPILoggingUtils
|
||||
|
||||
back = ResponseAPILoggingUtils._transform_response_api_usage_to_chat_usage(response_usage.model_dump())
|
||||
assert back.prompt_tokens_details.image_tokens == 150
|
||||
assert back.prompt_tokens_details.video_tokens == 50
|
||||
|
||||
def test_transform_usage_with_reasoning_tokens_gemini(self):
|
||||
"""Test that reasoning_tokens from Gemini are properly transformed to output_tokens_details"""
|
||||
# Setup: Simulate Gemini usage with thoughtsTokenCount
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue