mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-04 02:31:27 +00:00
fix(sdk): stop mirroring reasoning_content in provider_specific_fields (#30110)
The dict-to-response conversion path mirrored reasoning_content into provider_specific_fields, while live provider transforms (Anthropic's _build_provider_specific_fields) only set it top-level on the Message. Cache-replayed messages therefore serialized differently from live ones, breaking disk cache key stability for multi-turn conversations with extended thinking. The mirror was added for DeepSeek before Message.reasoning_content existed as a top-level attribute. The top-level field is still set by the converter, so DeepSeek's request-side promotion is unaffected. Fixes #27337.
This commit is contained in:
parent
993650fdf8
commit
ea29b28f40
2 changed files with 36 additions and 5 deletions
|
|
@ -633,11 +633,6 @@ def convert_to_model_response_object( # noqa: PLR0915
|
|||
thinking_blocks = choice["message"]["thinking_blocks"]
|
||||
provider_specific_fields["thinking_blocks"] = thinking_blocks
|
||||
|
||||
if reasoning_content:
|
||||
provider_specific_fields["reasoning_content"] = (
|
||||
reasoning_content
|
||||
)
|
||||
|
||||
message = Message(
|
||||
content=content,
|
||||
role=choice["message"]["role"] or "assistant",
|
||||
|
|
|
|||
|
|
@ -2425,6 +2425,42 @@ class TestConvertToModelResponseObjectCompletion:
|
|||
assert result.choices[0].message.content == "The answer is 4."
|
||||
assert result.choices[0].message.reasoning_content == "2+2=4"
|
||||
|
||||
def test_reasoning_content_not_mirrored_into_provider_specific_fields(self):
|
||||
"""Mirroring reasoning_content into provider_specific_fields made
|
||||
cache-replayed messages diverge from live Anthropic messages, which
|
||||
only set it top-level, breaking cache key stability (issue #27337)."""
|
||||
response_object = {
|
||||
"id": "chatcmpl-5",
|
||||
"model": "claude-sonnet-4-5",
|
||||
"choices": [
|
||||
{
|
||||
"finish_reason": "stop",
|
||||
"index": 0,
|
||||
"message": {
|
||||
"content": "The answer is 4.",
|
||||
"role": "assistant",
|
||||
"reasoning_content": "2+2=4",
|
||||
"thinking_blocks": [
|
||||
{
|
||||
"type": "thinking",
|
||||
"thinking": "2+2=4",
|
||||
"signature": "sig",
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
],
|
||||
"usage": {"prompt_tokens": 5, "completion_tokens": 10, "total_tokens": 15},
|
||||
}
|
||||
|
||||
result = convert_to_model_response_object(
|
||||
response_object=response_object,
|
||||
model_response_object=ModelResponse(),
|
||||
)
|
||||
message = result.choices[0].message
|
||||
assert message.reasoning_content == "2+2=4"
|
||||
assert "reasoning_content" not in (message.provider_specific_fields or {})
|
||||
|
||||
def test_response_none_raises(self):
|
||||
with pytest.raises(Exception):
|
||||
convert_to_model_response_object(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue