From f97b503faf082205caad792310eb5eb1defd570f Mon Sep 17 00:00:00 2001 From: shrey kharbanda Date: Thu, 24 Sep 2026 02:03:19 +0000 Subject: [PATCH] feat(openai_like): honour unsupported_params in JSON providers, declare Sail's --- litellm/llms/openai_like/dynamic_config.py | 6 +++- litellm/llms/openai_like/json_loader.py | 1 + litellm/llms/openai_like/providers.json | 3 +- .../llms/openai_like/test_sail_provider.py | 33 +++++++++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/litellm/llms/openai_like/dynamic_config.py b/litellm/llms/openai_like/dynamic_config.py index 19e29bcdcb2..9362f20cf48 100644 --- a/litellm/llms/openai_like/dynamic_config.py +++ b/litellm/llms/openai_like/dynamic_config.py @@ -94,7 +94,11 @@ def create_config_class(provider: SimpleProviderConfig): that don't support function calling.""" from litellm.utils import supports_function_calling, supports_reasoning - supported_params: Final = super().get_supported_openai_params(model=model) + supported_params: Final = [ + param + for param in super().get_supported_openai_params(model=model) + if param not in provider.unsupported_params + ] _supports_fc: Final = supports_function_calling(model=model, custom_llm_provider=provider.slug) diff --git a/litellm/llms/openai_like/json_loader.py b/litellm/llms/openai_like/json_loader.py index 5cdaff90d24..4bee08b03c5 100644 --- a/litellm/llms/openai_like/json_loader.py +++ b/litellm/llms/openai_like/json_loader.py @@ -22,6 +22,7 @@ class SimpleProviderConfig: self.constraints = data.get("constraints", {}) self.special_handling = data.get("special_handling", {}) self.supported_endpoints = data.get("supported_endpoints", []) + self.unsupported_params: Final = tuple(data.get("unsupported_params", ())) class JSONProviderRegistry: diff --git a/litellm/llms/openai_like/providers.json b/litellm/llms/openai_like/providers.json index 3d496047334..bd9f3b415df 100644 --- a/litellm/llms/openai_like/providers.json +++ b/litellm/llms/openai_like/providers.json @@ -208,6 +208,7 @@ "supported_endpoints": ["/v1/chat/completions", "/v1/responses", "/v1/messages"], "param_mappings": { "max_tokens": "max_completion_tokens" - } + }, + "unsupported_params": ["stop", "seed", "frequency_penalty", "presence_penalty", "logit_bias", "logprobs", "top_logprobs"] } } diff --git a/tests/test_litellm/llms/openai_like/test_sail_provider.py b/tests/test_litellm/llms/openai_like/test_sail_provider.py index e7a3c2005ea..6fffe0c81f0 100644 --- a/tests/test_litellm/llms/openai_like/test_sail_provider.py +++ b/tests/test_litellm/llms/openai_like/test_sail_provider.py @@ -250,6 +250,39 @@ class TestSailRequestShape: assert not route.called + @pytest.mark.respx() + def test_sail_unsupported_params_dropped_with_drop_params(self, respx_mock: respx.Router): + respx_mock.post(SAIL_CHAT_COMPLETIONS).respond(json=_chat_completion_payload()) + + litellm.completion( + model=MODEL, + messages=[{"role": "user", "content": "hi"}], + stop=["x"], + seed=1, + frequency_penalty=0.5, + drop_params=True, + ) + + body = json.loads(respx_mock.calls[0].request.content) + assert "stop" not in body + assert "seed" not in body + assert "frequency_penalty" not in body + assert body["model"] == "zai-org/GLM-5.3" + assert body["messages"] == [{"role": "user", "content": "hi"}] + + @pytest.mark.respx(assert_all_called=False) + def test_sail_unsupported_params_raise_without_drop_params(self, respx_mock: respx.Router): + route = respx_mock.post(SAIL_CHAT_COMPLETIONS) + + with pytest.raises(litellm.UnsupportedParamsError): + litellm.completion( + model=MODEL, + messages=[{"role": "user", "content": "hi"}], + stop=["x"], + ) + + assert not route.called + @pytest.mark.asyncio @pytest.mark.respx() async def test_sail_anthropic_messages_posts_to_messages_endpoint(self, respx_mock: respx.Router):