mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-21 00:21:49 +00:00
fix: pass together_ai replay/streaming tests under the thinking contract
Controlled base-vs-head run of the full llms test shard exposed two together_ai anthropic-messages tests broken by the thinking_disabled contract change in this PR: - test_anthropic_messages_replays_tool_loop: an unsigned thinking block in replayed history was being dropped entirely. Unsigned thinking texts now map to the provider-facing reasoning_content field (keeping the signature-400 defense: they still stay out of thinking_blocks). - replay + streaming tests asserted provider reasoning is surfaced without a thinking param on the request; per the PR contract that is suppressed. Updated both to assert the suppression (sending thinking=enabled would fail together's parameter validation via reasoning_effort).
This commit is contained in:
parent
63323a1dfd
commit
b7deea30aa
2 changed files with 24 additions and 2 deletions
|
|
@ -495,6 +495,7 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
has_cache_control_in_text = False
|
||||
tool_calls: list[ChatCompletionAssistantToolCall] = []
|
||||
thinking_blocks: list[ChatCompletionThinkingBlock | ChatCompletionRedactedThinkingBlock] = []
|
||||
unsigned_thinking_texts: list[str] = []
|
||||
if m["role"] == "assistant":
|
||||
if isinstance(m.get("content"), str):
|
||||
assistant_message_str = str(m.get("content", ""))
|
||||
|
|
@ -555,6 +556,15 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
signature=content.get("signature") or "",
|
||||
)
|
||||
thinking_blocks.append(thinking_block)
|
||||
else:
|
||||
# Unsigned text is NOT dropped: it is
|
||||
# replayed as the flat reasoning_content field
|
||||
# below (the provider-visible form), while
|
||||
# staying out of thinking_blocks, so the
|
||||
# signature-400 stays avoided.
|
||||
unsigned_text = str(content.get("thinking") or "")
|
||||
if unsigned_text:
|
||||
unsigned_thinking_texts.append(unsigned_text)
|
||||
elif content.get("type") == "redacted_thinking":
|
||||
redacted_thinking_block = ChatCompletionRedactedThinkingBlock(
|
||||
type="redacted_thinking",
|
||||
|
|
@ -587,6 +597,9 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
if len(thinking_blocks) > 0:
|
||||
assistant_message["thinking_blocks"] = thinking_blocks
|
||||
reasoning_content = reasoning_content_from_thinking_blocks(thinking_blocks)
|
||||
if unsigned_thinking_texts:
|
||||
unsigned = "\n".join(unsigned_thinking_texts)
|
||||
reasoning_content = f"{reasoning_content}\n{unsigned}" if reasoning_content else unsigned
|
||||
if reasoning_content:
|
||||
assistant_message["reasoning_content"] = reasoning_content
|
||||
new_messages.append(assistant_message)
|
||||
|
|
|
|||
|
|
@ -1013,7 +1013,11 @@ def test_anthropic_messages_replays_tool_loop_and_maps_reasoning_to_thinking_blo
|
|||
assert tool_turn["content"] == "Sunny, 18C"
|
||||
|
||||
blocks = {block["type"]: block for block in response["content"]}
|
||||
assert blocks["thinking"]["thinking"] == "Tool said sunny."
|
||||
|
||||
# Contract (thinking param absent): the provider's reasoning is NOT
|
||||
# surfaced as an Anthropic thinking block. The mock response still
|
||||
# carries reasoning, and this asserts it is suppressed.
|
||||
assert "thinking" not in blocks
|
||||
assert blocks["text"]["text"] == "Sunny in SF."
|
||||
assert response["stop_reason"] == "end_turn"
|
||||
|
||||
|
|
@ -1031,6 +1035,9 @@ def test_anthropic_messages_streams_together_tool_call_as_input_json_delta():
|
|||
captured_requests: list[httpx.Request] = []
|
||||
client = _sync_client(captured_requests, _sse_response(*PARALLEL_TOOL_CALL_STREAM))
|
||||
|
||||
# Explicit thinking= would be needed to surface provider reasoning
|
||||
# (the pass-through contract suppresses it when the thinking param is
|
||||
# absent); this test asserts the streaming translation only.
|
||||
events = _anthropic_sse_events(
|
||||
litellm.anthropic.messages.create(
|
||||
model=f"together_ai/{UNMAPPED_MODEL}",
|
||||
|
|
@ -1067,7 +1074,9 @@ def test_anthropic_messages_streams_together_tool_call_as_input_json_delta():
|
|||
for event in events
|
||||
if event["type"] == "content_block_delta" and event["delta"]["type"] == "thinking_delta"
|
||||
)
|
||||
assert thinking_text == "Need weather and time."
|
||||
# thinking param absent in the request: provider reasoning is
|
||||
# suppressed per the contract, so no thinking block may appear.
|
||||
assert thinking_text == ""
|
||||
assert [event["delta"]["stop_reason"] for event in events if event["type"] == "message_delta"] == ["tool_use"]
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue