fix: thinking lost on /v1/messages for OpenAI-compatible backends (e.g. sglang)

OpenAI-compatible backends such as sglang already return reasoning_content
over chat/completions, but _route_openai_thinking_to_responses_api_if_needed
rewrote enabled thinking to openai/responses/*. sglang's /v1/responses
reasoning item shape (content vs summary) then triggered 'Unknown items in
responses API response' and dropped the thinking block.

Honor use_chat_completions_url_for_anthropic_messages and keep the
chat/completions route when opted in. Add a regression test.
This commit is contained in:
san-tian 2026-08-27 07:48:27 +00:00
parent cd63c7e5a7
commit 79c9a68305
2 changed files with 31 additions and 0 deletions

View file

@ -334,6 +334,11 @@ class LiteLLMMessagesToCompletionTransformationHandler:
If the user provides a `summary` field in the thinking dict, it is passed
through to the OpenAI reasoning params (opt-in per OpenAI spec).
"""
if litellm.use_chat_completions_url_for_anthropic_messages:
# Honor the chat/completions opt-out; OpenAI-compatible backends
# (e.g. sglang) already return reasoning_content over chat/completions.
return
custom_llm_provider = completion_kwargs.get("custom_llm_provider")
if custom_llm_provider is None:
try:

View file

@ -429,6 +429,32 @@ class TestThinkingParameterTransformation:
class TestThinkingSummaryPreservation:
"""Tests for thinking.summary preservation and reasoning_auto_summary flag."""
def test_use_chat_completions_url_skips_responses_api_routing(self):
"""Enabled thinking + use_chat_completions_url_for_anthropic_messages should NOT
rewrite the model to openai/responses/* (stays on chat/completions)."""
import litellm
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)
original = litellm.use_chat_completions_url_for_anthropic_messages
try:
litellm.use_chat_completions_url_for_anthropic_messages = True
completion_kwargs = {
"model": "openai/gpt-5.1",
"custom_llm_provider": "openai",
"reasoning_effort": "medium",
}
LiteLLMMessagesToCompletionTransformationHandler._route_openai_thinking_to_responses_api_if_needed(
completion_kwargs, thinking={"type": "enabled", "budget_tokens": 5000}
)
# model must remain on chat/completions, not be rewritten to openai/responses/*
assert completion_kwargs["model"] == "openai/gpt-5.1"
assert "responses/" not in completion_kwargs["model"]
finally:
litellm.use_chat_completions_url_for_anthropic_messages = original
def test_thinking_summary_concise_preserved_for_openai(self):
"""User-provided summary='concise' should not be replaced with 'detailed'."""
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (