diff --git a/docs/my-website/docs/reasoning_content.md b/docs/my-website/docs/reasoning_content.md index f9cab01639d..5ddb5aefd47 100644 --- a/docs/my-website/docs/reasoning_content.md +++ b/docs/my-website/docs/reasoning_content.md @@ -20,6 +20,7 @@ Supported Providers: - Vertex AI (`vertex_ai/`) - Perplexity (`perplexity/`) - Mistral AI (Magistral models) (`mistral/`) +- Groq (`groq/`) LiteLLM will standardize the `reasoning_content` in the response and `thinking_blocks` in the assistant message. diff --git a/litellm/llms/groq/chat/transformation.py b/litellm/llms/groq/chat/transformation.py index 86fa323f9e3..165301efb5c 100644 --- a/litellm/llms/groq/chat/transformation.py +++ b/litellm/llms/groq/chat/transformation.py @@ -6,6 +6,8 @@ from typing import Any, Coroutine, List, Literal, Optional, Tuple, Union, cast, import httpx from pydantic import BaseModel +import litellm +from litellm._logging import verbose_logger from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj from litellm.secret_managers.main import get_secret_str from litellm.types.llms.openai import ( @@ -55,6 +57,10 @@ class GroqChatConfig(OpenAILikeChatConfig): if key != "self" and value is not None: setattr(self.__class__, key, value) + @property + def custom_llm_provider(self) -> Optional[str]: + return "groq" + @classmethod def get_config(cls): return super().get_config() @@ -65,6 +71,15 @@ class GroqChatConfig(OpenAILikeChatConfig): base_params.remove("max_retries") except ValueError: pass + + try: + if litellm.supports_reasoning( + model=model, custom_llm_provider=self.custom_llm_provider + ): + base_params.append("reasoning_effort") + except Exception as e: + verbose_logger.debug(f"Error checking if model supports reasoning: {e}") + return base_params @overload diff --git a/litellm/main.py b/litellm/main.py index 9c2aa678369..d0377490942 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -356,7 +356,7 @@ async def acompletion( logprobs: Optional[bool] = None, top_logprobs: Optional[int] = None, deployment_id=None, - reasoning_effort: Optional[Literal["minimal", "low", "medium", "high"]] = None, + reasoning_effort: Optional[Literal["none", "minimal", "low", "medium", "high", "default"]] = None, safety_identifier: Optional[str] = None, # set api_base, api_version, api_key base_url: Optional[str] = None, @@ -897,7 +897,7 @@ def completion( # type: ignore # noqa: PLR0915 logit_bias: Optional[dict] = None, user: Optional[str] = None, # openai v1.0+ new params - reasoning_effort: Optional[Literal["minimal", "low", "medium", "high"]] = None, + reasoning_effort: Optional[Literal["none", "minimal", "low", "medium", "high", "default"]] = None, response_format: Optional[Union[dict, Type[BaseModel]]] = None, seed: Optional[int] = None, tools: Optional[List] = None, diff --git a/tests/llm_translation/test_groq.py b/tests/llm_translation/test_groq.py index dd1ae0aed6d..9a9dae9ee89 100644 --- a/tests/llm_translation/test_groq.py +++ b/tests/llm_translation/test_groq.py @@ -1,6 +1,16 @@ -from base_llm_unit_tests import BaseLLMChatTest +import os +import sys +import pytest + +# sys.path.insert( +# 0, os.path.abspath("../..") +# ) # Adds the parent directory to the system path + +from base_llm_unit_tests import BaseLLMChatTest +from litellm.llms.groq.chat.transformation import GroqChatConfig + class TestGroq(BaseLLMChatTest): def get_base_completion_call_args(self) -> dict: return { @@ -10,3 +20,9 @@ class TestGroq(BaseLLMChatTest): def test_tool_call_no_arguments(self, tool_call_no_arguments): """Test that tool calls with no arguments is translated correctly. Relevant issue: https://github.com/BerriAI/litellm/issues/6833""" pass + + @pytest.mark.parametrize("model", ["groq/qwen/qwen3-32b", "groq/openai/gpt-oss-20b", "groq/openai/gpt-oss-120b"]) + def test_reasoning_effort_in_supported_params(self, model): + """Test that reasoning_effort is in the list of supported parameters for Groq""" + supported_params = GroqChatConfig().get_supported_openai_params(model=model) + assert "reasoning_effort" in supported_params