From e45492006e2a5e97c0cb7324dbf26d83c0c60d65 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 18:08:35 +0000 Subject: [PATCH] fix(fireworks_ai): default supports_tool_choice=True for unmapped models Fireworks models absent from the cost map defaulted supports_function_calling to True but left supports_tool_choice unset, so tool_choice was rejected with UnsupportedParamsError even though the upstream request would succeed. Default supports_tool_choice to True in get_provider_info, mirroring supports_function_calling, while still letting an explicit cost-map value override it. Fixes #35382 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../llms/fireworks_ai/chat/transformation.py | 5 ++++ .../test_fireworks_ai_chat_transformation.py | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/litellm/llms/fireworks_ai/chat/transformation.py b/litellm/llms/fireworks_ai/chat/transformation.py index eeae8c76888..ee37b96a001 100644 --- a/litellm/llms/fireworks_ai/chat/transformation.py +++ b/litellm/llms/fireworks_ai/chat/transformation.py @@ -439,18 +439,23 @@ class FireworksAIConfig(FireworksAIMixin, OpenAIGPTConfig): supports_function_calling_value = self._get_model_cost_capability( model=model, capability="supports_function_calling" ) + supports_tool_choice_value = self._get_model_cost_capability(model=model, capability="supports_tool_choice") supports_reasoning_value = self._get_model_cost_capability(model=model, capability="supports_reasoning") supports_vision_value = self._get_model_cost_capability(model=model, capability="supports_vision") supports_pdf_input_value = self._get_model_cost_capability(model=model, capability="supports_pdf_input") provider_specific_model_info: ProviderSpecificModelInfo = { "supports_function_calling": True, + "supports_tool_choice": True, "supports_prompt_caching": True, # https://docs.fireworks.ai/guides/prompt-caching } if supports_function_calling_value is not None: provider_specific_model_info["supports_function_calling"] = supports_function_calling_value + if supports_tool_choice_value is not None: + provider_specific_model_info["supports_tool_choice"] = supports_tool_choice_value + # Only include supports_reasoning if True if supports_reasoning_value: provider_specific_model_info["supports_reasoning"] = supports_reasoning_value diff --git a/tests/test_litellm/llms/fireworks_ai/chat/test_fireworks_ai_chat_transformation.py b/tests/test_litellm/llms/fireworks_ai/chat/test_fireworks_ai_chat_transformation.py index 94945ed4bfb..c37b7ab2b5a 100644 --- a/tests/test_litellm/llms/fireworks_ai/chat/test_fireworks_ai_chat_transformation.py +++ b/tests/test_litellm/llms/fireworks_ai/chat/test_fireworks_ai_chat_transformation.py @@ -20,6 +20,7 @@ from litellm.types.utils import ( Message, ModelResponse, ) +from litellm.utils import supports_tool_choice @pytest.fixture(autouse=True) @@ -467,6 +468,30 @@ def test_unmapped_model_fallback_function_calling(): assert info["supports_function_calling"] is True +def test_unmapped_model_fallback_tool_choice(monkeypatch): + """A Fireworks model absent from the cost map must still advertise tool_choice, matching supports_function_calling. Regression for #35382 (Kimi K3).""" + monkeypatch.setenv("LITELLM_LOCAL_MODEL_COST_MAP", "True") + litellm.model_cost = litellm.get_model_cost_map(url="") + + config = FireworksAIConfig() + model = "accounts/fireworks/models/kimi-k3" + + info = config.get_provider_info(model) + assert info["supports_tool_choice"] is True + assert supports_tool_choice(model=model, custom_llm_provider="fireworks_ai") is True + assert "tool_choice" in config.get_supported_openai_params(model) + + +def test_provider_info_tool_choice_false_override(monkeypatch): + """An explicit supports_tool_choice=False in the cost map still wins over the Fireworks default.""" + config = FireworksAIConfig() + model = "fireworks_ai/test-no-tool-choice" + monkeypatch.setitem(litellm.model_cost, model, {"supports_tool_choice": False}) + + info = config.get_provider_info(model) + assert info["supports_tool_choice"] is False + + def test_transform_messages_helper_strips_thinking_blocks(): """thinking_blocks must not be forwarded to Fireworks chat completions.""" config = FireworksAIConfig()