From 6b85e0b4da1d13702929f5e5c14a1784b754f68d Mon Sep 17 00:00:00 2001 From: Jean IBARZ Date: Fri, 10 Apr 2026 20:46:24 +0200 Subject: [PATCH] fix(together_ai): support reasoning_effort for gpt-oss models together_ai hosts gpt-oss-120b/20b which support reasoning, but TogetherAIConfig never advertised reasoning_effort as a supported OpenAI param. Calling completion(reasoning_effort=...) raised UnsupportedParamsError even though the underlying model accepts it. Mirror the deepinfra pattern: read supports_reasoning from the model info and append reasoning_effort when true. Also set supports_reasoning on the gpt-oss entries in the model registry so get_model_info reports the capability. Fixes #25132 --- litellm/llms/together_ai/chat.py | 6 +- ...odel_prices_and_context_window_backup.json | 1 + model_prices_and_context_window.json | 1 + .../test_together_ai_chat_transformation.py | 56 +++++++++++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/test_litellm/llms/together_ai/test_together_ai_chat_transformation.py diff --git a/litellm/llms/together_ai/chat.py b/litellm/llms/together_ai/chat.py index e8a784d2779..14206eae107 100644 --- a/litellm/llms/together_ai/chat.py +++ b/litellm/llms/together_ai/chat.py @@ -8,8 +8,8 @@ Docs: https://docs.together.ai/reference/completions-1 from typing import Optional -from litellm.utils import get_model_info from litellm._logging import verbose_logger +from litellm.utils import get_model_info from ..openai.chat.gpt_transformation import OpenAIGPTConfig @@ -22,11 +22,13 @@ class TogetherAIConfig(OpenAIGPTConfig): Docs: https://docs.together.ai/docs/json-mode """ supports_function_calling: Optional[bool] = None + supports_reasoning: Optional[bool] = None try: model_info = get_model_info(model, custom_llm_provider="together_ai") supports_function_calling = model_info.get( "supports_function_calling", False ) + supports_reasoning = model_info.get("supports_reasoning", False) except Exception as e: verbose_logger.debug(f"Error getting supported openai params: {e}") pass @@ -40,6 +42,8 @@ class TogetherAIConfig(OpenAIGPTConfig): optional_params.remove("tool_choice") optional_params.remove("function_call") optional_params.remove("response_format") + if supports_reasoning is True and "reasoning_effort" not in optional_params: + optional_params.append("reasoning_effort") return optional_params def map_openai_params( diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index f7189a60a31..256f35751bf 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -28668,6 +28668,7 @@ "source": "https://www.together.ai/models/gpt-oss-20b", "supports_function_calling": true, "supports_parallel_function_calling": true, + "supports_reasoning": true, "supports_response_schema": true, "supports_tool_choice": true }, diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 3ffc0ec7c58..8d6fe8c8725 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -28653,6 +28653,7 @@ "source": "https://www.together.ai/models/gpt-oss-20b", "supports_function_calling": true, "supports_parallel_function_calling": true, + "supports_reasoning": true, "supports_response_schema": true, "supports_tool_choice": true }, diff --git a/tests/test_litellm/llms/together_ai/test_together_ai_chat_transformation.py b/tests/test_litellm/llms/together_ai/test_together_ai_chat_transformation.py new file mode 100644 index 00000000000..ff8d4f7a5ff --- /dev/null +++ b/tests/test_litellm/llms/together_ai/test_together_ai_chat_transformation.py @@ -0,0 +1,56 @@ +import os +import sys + +# Add litellm to path +sys.path.insert(0, os.path.abspath("../../../..")) +import litellm +from litellm.llms.together_ai.chat import TogetherAIConfig + + +def _use_local_model_cost_map() -> None: + os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True" + litellm.model_cost = litellm.get_model_cost_map(url="") + + +def test_together_ai_gpt_oss_supports_reasoning_effort(): + """ + gpt-oss models on together_ai support reasoning. Regression test for #25132. + """ + _use_local_model_cost_map() + + supported_params = TogetherAIConfig().get_supported_openai_params( + model="together_ai/openai/gpt-oss-120b" + ) + assert "reasoning_effort" in supported_params + + supported_params_20b = TogetherAIConfig().get_supported_openai_params( + model="together_ai/openai/gpt-oss-20b" + ) + assert "reasoning_effort" in supported_params_20b + + +def test_together_ai_non_reasoning_model_does_not_expose_reasoning_effort(): + """ + Non-reasoning together_ai models should not advertise reasoning_effort. + """ + _use_local_model_cost_map() + + supported_params = TogetherAIConfig().get_supported_openai_params( + model="together_ai/meta-llama/Llama-3-70b-chat-hf" + ) + assert "reasoning_effort" not in supported_params + + +def test_together_ai_gpt_oss_reasoning_effort_flows_through_get_optional_params(): + """ + End-to-end: the exact call from issue #25132 must not raise + UnsupportedParamsError, and reasoning_effort must land in optional_params. + """ + _use_local_model_cost_map() + + optional_params = litellm.get_optional_params( + model="openai/gpt-oss-120b", + custom_llm_provider="together_ai", + reasoning_effort="low", + ) + assert optional_params.get("reasoning_effort") == "low"