fix: Fix Responses API streaming tests usage field names and cost (#16236)

This commit fixes two bugs in Responses API streaming tests:

1. **Usage field naming bug**: Tests were using `input_tokens` and
   `output_tokens` but the Usage object uses `prompt_tokens` and
   `completion_tokens`.

2. **Missing cost in streaming usage**: When `include_cost_in_streaming_usage`
   was enabled, the cost was calculated and added to ResponseAPIUsage, but was
   lost during the transformation to the Usage object.

Changes:
- Updated test assertions to use correct field names (prompt_tokens, completion_tokens)
- Added cost preservation logic in FakeStreamerResponsesAPIIterator
- Modified _transform_response_api_usage_to_chat_usage() to preserve cost attribute

All streaming tests now pass successfully.
This commit is contained in:
Cesar Garcia 2025-11-04 20:57:59 -03:00 • committed by GitHub
parent 7878ebd2a2
commit 78ed5126a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 29 additions and 7 deletions

View file

@ -325,6 +325,22 @@ class MockResponsesAPIStreamingIterator(BaseResponsesAPIStreamingIterator):
for i in range(0, len(full_text), self.CHUNK_SIZE)
]
# Add cost to usage object if include_cost_in_streaming_usage is True
if litellm.include_cost_in_streaming_usage and logging_obj is not None:
usage_obj: Optional[ResponseAPIUsage] = getattr(
transformed, "usage", None
)
if usage_obj is not None:
try:
cost: Optional[float] = logging_obj._response_cost_calculator(
result=transformed
)
if cost is not None:
setattr(usage_obj, "cost", cost)
except Exception:
# If cost calculation fails, continue without cost
pass
# append the completed event
self._events = deltas + [
ResponseCompletedEvent(

View file

@ -381,9 +381,15 @@ class ResponseAPILoggingUtils:
cached_tokens=response_api_usage.input_tokens_details.cached_tokens,
audio_tokens=response_api_usage.input_tokens_details.audio_tokens,
)
return Usage(
usage = Usage(
prompt_tokens=prompt_tokens,
completion_tokens=completion_tokens,
total_tokens=prompt_tokens + completion_tokens,
prompt_tokens_details=prompt_tokens_details,
)
# Preserve cost attribute if it exists on ResponseAPIUsage
if hasattr(response_api_usage, "cost") and response_api_usage.cost is not None:
setattr(usage, "cost", response_api_usage.cost)
return usage

View file

@ -189,12 +189,12 @@ class BaseResponsesAPITest(ABC):
response_completed_event.response.usage,
)
assert (
response_completed_event.response.usage.input_tokens > 0
and response_completed_event.response.usage.input_tokens < 100
response_completed_event.response.usage.prompt_tokens > 0
and response_completed_event.response.usage.prompt_tokens < 100
)
assert (
response_completed_event.response.usage.output_tokens > 0
and response_completed_event.response.usage.output_tokens < 2000
response_completed_event.response.usage.completion_tokens > 0
and response_completed_event.response.usage.completion_tokens < 2000
)
assert (
response_completed_event.response.usage.total_tokens > 0
@ -204,8 +204,8 @@ class BaseResponsesAPITest(ABC):
# total tokens should be the sum of input and output tokens
assert (
response_completed_event.response.usage.total_tokens
== response_completed_event.response.usage.input_tokens
+ response_completed_event.response.usage.output_tokens
== response_completed_event.response.usage.prompt_tokens
+ response_completed_event.response.usage.completion_tokens
)
# assert the response completed event includes cost when include_cost_in_streaming_usage is True