Merge pull request #18327 from BerriAI/litellm_add_image_tokens_in_chat_completion

Add image tokens in chat completion
This commit is contained in:
Sameer Kankute 2025-12-22 16:59:30 +05:30 committed by GitHub
commit 5bd014fd3f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 57 additions and 0 deletions

View file

@ -1476,6 +1476,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
cached_tokens: Optional[int] = None
audio_tokens: Optional[int] = None
text_tokens: Optional[int] = None
image_tokens: Optional[int] = None
prompt_tokens_details: Optional[PromptTokensDetailsWrapper] = None
reasoning_tokens: Optional[int] = None
response_tokens: Optional[int] = None
@ -1526,6 +1527,8 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
audio_tokens = detail.get("tokenCount", 0)
elif detail["modality"] == "TEXT":
text_tokens = detail.get("tokenCount", 0)
elif detail["modality"] == "IMAGE":
image_tokens = detail.get("tokenCount", 0)
if "thoughtsTokenCount" in usage_metadata:
reasoning_tokens = usage_metadata["thoughtsTokenCount"]
# Also add reasoning tokens to response_tokens_details
@ -1546,6 +1549,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
cached_tokens=cached_tokens,
audio_tokens=audio_tokens,
text_tokens=text_tokens,
image_tokens=image_tokens,
)
completion_tokens = response_tokens or completion_response["usageMetadata"].get(

View file

@ -614,6 +614,59 @@ def test_vertex_ai_usage_metadata_with_image_tokens_auto_calculated_text():
assert result.completion_tokens_details.reasoning_tokens == 158
def test_vertex_ai_usage_metadata_with_image_tokens_in_prompt():
"""Test promptTokensDetails with IMAGE modality for multimodal inputs
This test verifies the fix for issue #18182 where image_tokens were missing
from prompt_tokens_details when calling Gemini models with image inputs.
Example scenario: User sends a text prompt + image, and Gemini generates an image response.
The promptTokensDetails should include both TEXT and IMAGE token counts.
In this test case, candidatesTokenCount is INCLUSIVE of thoughtsTokenCount because:
promptTokenCount (533) + candidatesTokenCount (1337) = totalTokenCount (1870)
"""
v = VertexGeminiConfig()
usage_metadata = {
"promptTokenCount": 533,
"candidatesTokenCount": 1337, # INCLUSIVE of thoughtsTokenCount
"totalTokenCount": 1870,
"promptTokensDetails": [
{"modality": "IMAGE", "tokenCount": 527},
{"modality": "TEXT", "tokenCount": 6}
],
"candidatesTokensDetails": [
{"modality": "IMAGE", "tokenCount": 1120}
],
"thoughtsTokenCount": 217
}
usage_metadata = UsageMetadata(**usage_metadata)
result = v._calculate_usage(completion_response={"usageMetadata": usage_metadata})
print("result", result)
# Verify basic token counts
assert result.prompt_tokens == 533
# candidatesTokenCount is INCLUSIVE, so completion_tokens = candidatesTokenCount
assert result.completion_tokens == 1337
assert result.total_tokens == 1870
# Verify prompt_tokens_details includes both text and image tokens
assert result.prompt_tokens_details.text_tokens == 6
assert result.prompt_tokens_details.image_tokens == 527
# Verify completion_tokens_details
assert result.completion_tokens_details.image_tokens == 1120
assert result.completion_tokens_details.reasoning_tokens == 217
# Verify the math: prompt_tokens = text + image
# 533 = 6 (text) + 527 (image)
assert (
result.prompt_tokens_details.text_tokens
+ result.prompt_tokens_details.image_tokens
== result.prompt_tokens
)
def test_vertex_ai_map_thinking_param_with_budget_tokens_0():
"""
If budget_tokens is 0, do not set includeThoughts to True