mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-28 01:32:17 +00:00
fix(responses): propagate chat bridge stream errors
This commit is contained in:
parent
97dbd8efcb
commit
1656e7ea64
2 changed files with 105 additions and 0 deletions
|
|
@ -1368,6 +1368,21 @@ class OpenAiResponsesToChatCompletionStreamIterator(BaseModelResponseIterator):
|
|||
)
|
||||
]
|
||||
)
|
||||
elif event_type in (ResponsesAPIStreamEvents.RESPONSE_FAILED, ResponsesAPIStreamEvents.ERROR):
|
||||
from litellm.responses.streaming_iterator import _error_event_fields, _status_code_for_error_fields
|
||||
|
||||
error_payload: Final = (
|
||||
parsed_chunk.get("response", {}).get("error")
|
||||
if event_type == ResponsesAPIStreamEvents.RESPONSE_FAILED
|
||||
else parsed_chunk.get("error")
|
||||
)
|
||||
error_message, error_type, error_code = _error_event_fields(error_payload)
|
||||
raise litellm.APIError(
|
||||
status_code=_status_code_for_error_fields(error_type, error_code),
|
||||
message=error_message,
|
||||
llm_provider="openai",
|
||||
model="responses",
|
||||
)
|
||||
elif event_type == "response.output_item.added":
|
||||
# New output item added
|
||||
output_item = parsed_chunk.get("item", {})
|
||||
|
|
@ -1498,6 +1513,29 @@ class OpenAiResponsesToChatCompletionStreamIterator(BaseModelResponseIterator):
|
|||
)
|
||||
else:
|
||||
raise ValueError(f"Chat provider: Invalid text delta {parsed_chunk}")
|
||||
elif event_type == ResponsesAPIStreamEvents.REFUSAL_DELTA:
|
||||
refusal: Final = parsed_chunk.get("delta")
|
||||
if isinstance(refusal, str):
|
||||
return ModelResponseStream(
|
||||
choices=[
|
||||
StreamingChoices(
|
||||
index=0,
|
||||
delta=Delta(refusal=refusal),
|
||||
finish_reason=None,
|
||||
)
|
||||
]
|
||||
)
|
||||
raise ValueError(f"Chat provider: Invalid refusal delta {parsed_chunk}")
|
||||
elif event_type == ResponsesAPIStreamEvents.REFUSAL_DONE:
|
||||
return ModelResponseStream(
|
||||
choices=[
|
||||
StreamingChoices(
|
||||
index=0,
|
||||
delta=Delta(),
|
||||
finish_reason=None,
|
||||
)
|
||||
]
|
||||
)
|
||||
elif event_type == "response.reasoning_summary_text.delta":
|
||||
content_part = parsed_chunk.get("delta", None)
|
||||
if content_part:
|
||||
|
|
|
|||
|
|
@ -3796,6 +3796,73 @@ def test_response_incomplete_stream_event_without_details_defaults_to_length():
|
|||
assert result.choices[0].finish_reason == "length"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("event", "expected_status"),
|
||||
[
|
||||
(
|
||||
{
|
||||
"type": "response.failed",
|
||||
"response": {
|
||||
"error": {
|
||||
"type": "server_error",
|
||||
"code": "server_error",
|
||||
"message": "generation failed",
|
||||
}
|
||||
},
|
||||
},
|
||||
500,
|
||||
),
|
||||
(
|
||||
{
|
||||
"type": "error",
|
||||
"error": {
|
||||
"type": "invalid_request_error",
|
||||
"code": "invalid_prompt",
|
||||
"message": "prompt was rejected",
|
||||
},
|
||||
},
|
||||
400,
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_response_stream_errors_raise_litellm_api_errors(event, expected_status):
|
||||
from litellm.completion_extras.litellm_responses_transformation.transformation import (
|
||||
OpenAiResponsesToChatCompletionStreamIterator,
|
||||
)
|
||||
|
||||
iterator = OpenAiResponsesToChatCompletionStreamIterator(
|
||||
streaming_response=iter([f"data: {json.dumps(event)}"]), sync_stream=True
|
||||
)
|
||||
|
||||
with pytest.raises(litellm.APIError) as exc_info:
|
||||
next(iterator)
|
||||
|
||||
assert exc_info.value.status_code == expected_status
|
||||
assert event.get("error", event.get("response", {}).get("error"))["message"] in str(exc_info.value)
|
||||
|
||||
|
||||
def test_response_refusal_stream_events_preserve_refusal_delta_without_duplication():
|
||||
from litellm.completion_extras.litellm_responses_transformation.transformation import (
|
||||
OpenAiResponsesToChatCompletionStreamIterator,
|
||||
)
|
||||
|
||||
iterator = OpenAiResponsesToChatCompletionStreamIterator(
|
||||
streaming_response=iter(
|
||||
[
|
||||
'data: {"type":"response.refusal.delta","delta":"I cannot help with that."}',
|
||||
'data: {"type":"response.refusal.done","refusal":"I cannot help with that."}',
|
||||
]
|
||||
),
|
||||
sync_stream=True,
|
||||
)
|
||||
|
||||
delta = next(iterator)
|
||||
done = next(iterator)
|
||||
|
||||
assert delta.choices[0].delta.get("refusal") == "I cannot help with that."
|
||||
assert done.choices[0].delta.get("refusal") is None
|
||||
|
||||
|
||||
def test_assistant_message_with_tool_calls_keeps_its_content():
|
||||
"""Regression for https://github.com/BerriAI/litellm/issues/24985.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue