mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-13 08:52:02 +00:00
Merge a1a73197ce into f82e4c80ac
This commit is contained in:
commit
8b593986c1
5 changed files with 56 additions and 17 deletions
|
|
@ -58,6 +58,7 @@ from litellm.types.llms.openai import (
|
|||
ResponseIncompleteEvent,
|
||||
ResponseInProgressEvent,
|
||||
ResponseInputParam,
|
||||
ResponsePartAddedEvent,
|
||||
ResponsesAPIOptionalRequestParams,
|
||||
ResponsesAPIResponse,
|
||||
ResponsesAPIStreamEvents,
|
||||
|
|
@ -1188,20 +1189,26 @@ class LiteLLMCompletionStreamingIterator(ResponsesAPIStreamingIterator):
|
|||
self._cached_reasoning_item_id = mint_reasoning_item_id()
|
||||
self._reasoning_item_id = self._cached_reasoning_item_id
|
||||
|
||||
self._pending_response_events.append(
|
||||
OutputItemAddedEvent(
|
||||
type=ResponsesAPIStreamEvents.OUTPUT_ITEM_ADDED,
|
||||
output_index=self._reasoning_index(),
|
||||
item=BaseLiteLLMOpenAIResponseObject(
|
||||
**{
|
||||
"id": self._cached_reasoning_item_id,
|
||||
"type": "reasoning",
|
||||
"status": "in_progress",
|
||||
"summary": None,
|
||||
}
|
||||
),
|
||||
)
|
||||
event = OutputItemAddedEvent(
|
||||
type=ResponsesAPIStreamEvents.OUTPUT_ITEM_ADDED,
|
||||
output_index=self._reasoning_index(),
|
||||
item=BaseLiteLLMOpenAIResponseObject(
|
||||
**{
|
||||
"id": self._cached_reasoning_item_id,
|
||||
"type": "reasoning",
|
||||
"status": "in_progress",
|
||||
"summary": [],
|
||||
}
|
||||
),
|
||||
)
|
||||
part_added_event: Final = ResponsePartAddedEvent(
|
||||
type=ResponsesAPIStreamEvents.RESPONSE_PART_ADDED,
|
||||
item_id=self._cached_reasoning_item_id,
|
||||
output_index=self._reasoning_index(),
|
||||
sequence_number=SEQUENCE_NUMBER_STAMPED_ON_EMISSION,
|
||||
part={"type": "summary_text", "text": ""},
|
||||
)
|
||||
self._pending_response_events.extend([event, part_added_event])
|
||||
return
|
||||
|
||||
# Tool-first
|
||||
|
|
|
|||
|
|
@ -2048,6 +2048,7 @@ def build_synthetic_response_events(
|
|||
item_id=item_id,
|
||||
output_index=output_index,
|
||||
summary_index=summary_index,
|
||||
sequence_number=sequence_number,
|
||||
part={**summary_payload, "text": ""},
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1832,8 +1832,9 @@ class ResponsePartAddedEvent(BaseResponsesStreamEvent):
|
|||
type: Literal[ResponsesAPIStreamEvents.RESPONSE_PART_ADDED]
|
||||
item_id: str
|
||||
output_index: int
|
||||
summary_index: int = 0
|
||||
sequence_number: int
|
||||
part: dict
|
||||
summary_index: int = 0
|
||||
|
||||
|
||||
class ReasoningSummaryTextDeltaEvent(BaseResponsesStreamEvent):
|
||||
|
|
|
|||
|
|
@ -4840,8 +4840,8 @@ class TestEnsureOutputItemContentPartAdded:
|
|||
assert completed_event.response.status == "completed"
|
||||
|
||||
def test_reasoning_item_does_not_emit_content_part_added(self):
|
||||
"""Reasoning items should not get a content_part.added event."""
|
||||
from litellm.types.llms.openai import OutputItemAddedEvent
|
||||
"""Reasoning items get a reasoning_summary_part.added event, not a content_part.added one."""
|
||||
from litellm.types.llms.openai import OutputItemAddedEvent, ResponsePartAddedEvent
|
||||
|
||||
iterator = self._make_iterator()
|
||||
chunk = self._make_reasoning_chunk()
|
||||
|
|
@ -4849,8 +4849,9 @@ class TestEnsureOutputItemContentPartAdded:
|
|||
iterator._ensure_output_item_for_chunk(chunk)
|
||||
|
||||
events = iterator._pending_response_events
|
||||
assert len(events) == 1
|
||||
assert len(events) == 2
|
||||
assert isinstance(events[0], OutputItemAddedEvent)
|
||||
assert isinstance(events[1], ResponsePartAddedEvent)
|
||||
assert iterator.sent_content_part_added_event is False
|
||||
|
||||
def test_only_emits_once(self):
|
||||
|
|
|
|||
|
|
@ -1517,6 +1517,35 @@ async def test_plain_text_stream_announces_exactly_one_message_item(sync_mode: b
|
|||
assert event.item_id == message_item_adds[0].item.id
|
||||
|
||||
|
||||
@pytest.mark.parametrize("sync_mode", [True, False])
|
||||
@pytest.mark.asyncio
|
||||
async def test_reasoning_item_opens_with_empty_summary_and_a_summary_part(sync_mode: bool):
|
||||
iterator: Final = _build_iterator(
|
||||
[_reasoning_chunk("let me "), _reasoning_chunk("think"), _chunk("hi", finish_reason="stop")]
|
||||
)
|
||||
events: Final = await _collect_events(iterator, sync_mode)
|
||||
|
||||
types: Final = [event.type for event in events]
|
||||
item_added: Final = next(
|
||||
e for e in events if e.type == ResponsesAPIStreamEvents.OUTPUT_ITEM_ADDED and e.item.type == "reasoning"
|
||||
)
|
||||
part_added: Final = next(e for e in events if e.type == ResponsesAPIStreamEvents.RESPONSE_PART_ADDED)
|
||||
first_delta: Final = types.index(ResponsesAPIStreamEvents.REASONING_SUMMARY_TEXT_DELTA)
|
||||
|
||||
assert item_added.item.summary == []
|
||||
assert (
|
||||
types.index(ResponsesAPIStreamEvents.OUTPUT_ITEM_ADDED)
|
||||
< types.index(ResponsesAPIStreamEvents.RESPONSE_PART_ADDED)
|
||||
< first_delta
|
||||
)
|
||||
assert types.count(ResponsesAPIStreamEvents.RESPONSE_PART_ADDED) == 1
|
||||
assert part_added.item_id == item_added.item.id
|
||||
assert part_added.output_index == item_added.output_index
|
||||
assert part_added.summary_index == 0
|
||||
assert part_added.part == {"type": "summary_text", "text": ""}
|
||||
assert _serialized_sequence_numbers(events) == list(range(len(events)))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("sync_mode", [True, False])
|
||||
@pytest.mark.asyncio
|
||||
async def test_anthropic_tool_search_call_streams_as_tool_search_call_item(sync_mode: bool):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue