From 23e4f00eb38824210bb1ba673c6087b16eda3592 Mon Sep 17 00:00:00 2001 From: Chesars Date: Tue, 10 Mar 2026 18:26:37 -0300 Subject: [PATCH] fix(responses): prioritize Python classes over JSON in get_provider_chat_config - Invert lookup order in get_provider_chat_config so Python classes (with custom overrides) are checked before JSON providers, matching the pattern already used in get_provider_responses_api_config. Prevents regression where providers like Perplexity (declared in providers.json) would silently lose their custom chat config. - Add 'models' to Perplexity Responses API supported params (fallback chain feature documented in Perplexity API). --- .../perplexity/responses/transformation.py | 1 + litellm/utils.py | 37 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/litellm/llms/perplexity/responses/transformation.py b/litellm/llms/perplexity/responses/transformation.py index 51e43f2cb69..ad85b88d7d4 100644 --- a/litellm/llms/perplexity/responses/transformation.py +++ b/litellm/llms/perplexity/responses/transformation.py @@ -29,6 +29,7 @@ class PerplexityResponsesConfig(OpenAIResponsesAPIConfig): "tools", "reasoning", "instructions", + "models", ] @property diff --git a/litellm/utils.py b/litellm/utils.py index 689155e5e03..585e946fe6e 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -8060,17 +8060,8 @@ class ProviderConfigManager: Returns the provider config for a given provider. Uses O(1) dictionary lookup for fast provider resolution. + Python classes take priority over JSON (they have custom overrides). """ - # Check JSON providers FIRST (these override standard mappings) - from litellm.llms.openai_like.dynamic_config import create_config_class - from litellm.llms.openai_like.json_loader import JSONProviderRegistry - - if JSONProviderRegistry.exists(provider.value): - provider_config = JSONProviderRegistry.get(provider.value) - if provider_config is None: - raise ValueError(f"Provider {provider.value} not found") - return create_config_class(provider_config)() - # Handle OpenAI special cases (O-series and GPT-5 models) if provider == LlmProviders.OPENAI: if litellm.openaiOSeriesConfig.is_model_o_series_model(model=model): @@ -8084,18 +8075,24 @@ class ProviderConfigManager: ProviderConfigManager._build_provider_config_map() ) - # O(1) dictionary lookup + # O(1) dictionary lookup — Python classes first (custom overrides take priority) config_entry = ProviderConfigManager._PROVIDER_CONFIG_MAP.get(provider) - if config_entry is None: - return None + if config_entry is not None: + config_factory, needs_model = config_entry + if needs_model: + return config_factory(model) # type: ignore + else: + return config_factory() # type: ignore - # Unpack factory function and whether it needs model parameter - # This avoids expensive inspect.signature() calls at runtime - config_factory, needs_model = config_entry - if needs_model: - return config_factory(model) # type: ignore - else: - return config_factory() # type: ignore + # Fall back to JSON providers (generic OpenAI-compatible) + from litellm.llms.openai_like.dynamic_config import create_config_class + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + if JSONProviderRegistry.exists(provider.value): + provider_config = JSONProviderRegistry.get(provider.value) + if provider_config is None: + raise ValueError(f"Provider {provider.value} not found") + return create_config_class(provider_config)() @staticmethod def get_provider_embedding_config(