mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-11 08:38:24 +00:00
Merge 11651dad7a into c9a5777739
This commit is contained in:
commit
2263df016d
4 changed files with 80 additions and 18 deletions
|
|
@ -1129,7 +1129,7 @@ class LiteLLMCompletionStreamingIterator(ResponsesAPIStreamingIterator):
|
|||
"id": self._cached_reasoning_item_id,
|
||||
"type": "reasoning",
|
||||
"status": "in_progress",
|
||||
"summary": None,
|
||||
"summary": [],
|
||||
}
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3436,24 +3436,29 @@ class LiteLLMCompletionResponsesConfig:
|
|||
encrypted_content = LiteLLMCompletionResponsesConfig._encode_thinking_blocks(message)
|
||||
if reasoning_content or encrypted_content:
|
||||
# Only check the first choice for reasoning content
|
||||
# summary and encrypted_content are reasoning-only extras the shared model does not declare
|
||||
return [
|
||||
GenericResponseOutputItem(
|
||||
type="reasoning",
|
||||
id=mint_reasoning_item_id(),
|
||||
status=LiteLLMCompletionResponsesConfig._map_chat_completion_finish_reason_to_responses_status(
|
||||
choice.finish_reason
|
||||
),
|
||||
role="assistant",
|
||||
content=[
|
||||
OutputText(
|
||||
type="output_text",
|
||||
text=text,
|
||||
annotations=[],
|
||||
)
|
||||
for text in (reasoning_content,)
|
||||
if text
|
||||
],
|
||||
encrypted_content=encrypted_content,
|
||||
GenericResponseOutputItem.model_validate(
|
||||
{
|
||||
"type": "reasoning",
|
||||
"id": mint_reasoning_item_id(),
|
||||
"status": LiteLLMCompletionResponsesConfig._map_chat_completion_finish_reason_to_responses_status(
|
||||
choice.finish_reason
|
||||
),
|
||||
"role": "assistant",
|
||||
"content": [
|
||||
OutputText(
|
||||
type="output_text",
|
||||
text=text,
|
||||
annotations=[],
|
||||
)
|
||||
for text in (reasoning_content,)
|
||||
if text
|
||||
],
|
||||
# Required by the Responses schema. The reasoning text rides in content, so it stays empty
|
||||
"summary": [],
|
||||
"encrypted_content": encrypted_content,
|
||||
}
|
||||
)
|
||||
]
|
||||
return []
|
||||
|
|
|
|||
|
|
@ -503,6 +503,39 @@ class TestLiteLLMCompletionResponsesConfig:
|
|||
assert reasoning_items[0].content[0].text == "counting the primes"
|
||||
assert "sig" in reasoning_items[0].encrypted_content
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"message",
|
||||
[
|
||||
pytest.param(
|
||||
Message(content="No, 1001 = 7 x 11 x 13", role="assistant", reasoning_content="Trying small primes"),
|
||||
id="gemini-thought-text",
|
||||
),
|
||||
pytest.param(
|
||||
Message(
|
||||
content="No",
|
||||
role="assistant",
|
||||
reasoning_content="",
|
||||
thinking_blocks=[{"type": "thinking", "thinking": "", "signature": "sig"}],
|
||||
),
|
||||
id="signature-only-thinking",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_reasoning_item_always_carries_a_summary_list(self, message: Message):
|
||||
"""`summary` is required on a Responses reasoning item, and clients that read it
|
||||
(e.g. OpenAI Agents SDK tracing) fail on the missing field"""
|
||||
response: Final = LiteLLMCompletionResponsesConfig.transform_chat_completion_response_to_responses_api_response(
|
||||
request_input="Is 1001 prime?",
|
||||
responses_api_request={},
|
||||
chat_completion_response=ModelResponse(
|
||||
model="gemini-3.8-flash", choices=[Choices(index=0, finish_reason="stop", message=message)]
|
||||
),
|
||||
)
|
||||
|
||||
reasoning_items: Final = [item for item in response.output if item.type == "reasoning"]
|
||||
assert len(reasoning_items) == 1
|
||||
assert reasoning_items[0].summary == []
|
||||
|
||||
def test_transform_chat_completion_response_status_with_stop(self):
|
||||
"""
|
||||
Test that transforming a chat completion response with 'stop' finish_reason
|
||||
|
|
|
|||
|
|
@ -1173,6 +1173,30 @@ async def test_signature_only_thinking_streams_a_replayable_reasoning_item(sync_
|
|||
assert json.loads(reasoning_items[0].encrypted_content)[0]["signature"] == "sig_only"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"stream_chunks",
|
||||
[_reasoning_then_text_chunks, _signed_thinking_and_text_in_one_chunk],
|
||||
ids=["gemini-thought-text", "signature-only-thinking"],
|
||||
)
|
||||
@pytest.mark.parametrize("sync_mode", [True, False])
|
||||
@pytest.mark.asyncio
|
||||
async def test_streamed_reasoning_item_carries_a_summary_list_from_added_to_completed(
|
||||
stream_chunks: StreamChunks, sync_mode: bool
|
||||
):
|
||||
events: Final = await _collect_events(_build_iterator(stream_chunks()), sync_mode)
|
||||
|
||||
added: Final = next(
|
||||
event.item
|
||||
for event in events
|
||||
if getattr(event, "type", None) == ResponsesAPIStreamEvents.OUTPUT_ITEM_ADDED and event.item.type == "reasoning"
|
||||
)
|
||||
completed: Final = next(
|
||||
event for event in events if getattr(event, "type", None) == ResponsesAPIStreamEvents.RESPONSE_COMPLETED
|
||||
)
|
||||
assert added.summary == []
|
||||
assert [item.summary for item in completed.response.output if item.type == "reasoning"] == [[]]
|
||||
|
||||
|
||||
@REASONING_THEN_TEXT_STREAMS
|
||||
@pytest.mark.parametrize("sync_mode", [True, False])
|
||||
@pytest.mark.asyncio
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue