diff --git a/litellm/utils.py b/litellm/utils.py index 2125875ee1d..801bcee7d56 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -8404,6 +8404,17 @@ class ProviderConfigManager: model: str, provider: LlmProviders, ) -> Optional[BaseAnthropicMessagesConfig]: + return ProviderConfigManager._get_provider_anthropic_messages_config_cached( + model=model, provider=provider + ) + + @staticmethod + @lru_cache(maxsize=DEFAULT_MAX_LRU_CACHE_SIZE) + def _get_provider_anthropic_messages_config_cached( + model: str, + provider: LlmProviders, + ) -> Optional[BaseAnthropicMessagesConfig]: + model_lower = model.lower() if litellm.LlmProviders.ANTHROPIC == provider: return litellm.AnthropicMessagesConfig() # The 'BEDROCK' provider corresponds to Amazon's implementation of Anthropic Claude v3. @@ -8413,14 +8424,14 @@ class ProviderConfigManager: return BedrockModelInfo.get_bedrock_provider_config_for_messages_api(model) elif litellm.LlmProviders.VERTEX_AI == provider: - if "claude" in model.lower(): + if "claude" in model_lower: from litellm.llms.vertex_ai.vertex_ai_partner_models.anthropic.experimental_pass_through.transformation import ( VertexAIPartnerModelsAnthropicMessagesConfig, ) return VertexAIPartnerModelsAnthropicMessagesConfig() elif litellm.LlmProviders.AZURE_AI == provider: - if "claude" in model.lower(): + if "claude" in model_lower: from litellm.llms.azure_ai.anthropic.messages_transformation import ( AzureAnthropicMessagesConfig, ) diff --git a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_messages_config.py b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_messages_config.py index 214e5f07978..b8cd65d3c99 100644 --- a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_messages_config.py +++ b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_messages_config.py @@ -311,3 +311,29 @@ def test_transform_anthropic_messages_request_removes_scope_from_cache_control() # scope removed from message content assert "scope" not in result["messages"][0]["content"][0]["cache_control"] assert result["messages"][0]["content"][0]["cache_control"]["type"] == "ephemeral" + + +def test_provider_config_manager_reuses_vertex_anthropic_messages_config_instance(): + """ + Regression test: repeated provider config lookups for the same Vertex Claude model + should return the same config instance (which preserves auth cache state). + """ + import litellm + from litellm.utils import ProviderConfigManager + + ProviderConfigManager._get_provider_anthropic_messages_config_cached.cache_clear() + try: + first_config = ProviderConfigManager.get_provider_anthropic_messages_config( + model="claude-opus-4-6", + provider=litellm.LlmProviders.VERTEX_AI, + ) + second_config = ProviderConfigManager.get_provider_anthropic_messages_config( + model="claude-opus-4-6", + provider=litellm.LlmProviders.VERTEX_AI, + ) + + assert isinstance(first_config, VertexAIPartnerModelsAnthropicMessagesConfig) + assert isinstance(second_config, VertexAIPartnerModelsAnthropicMessagesConfig) + assert first_config is second_config + finally: + ProviderConfigManager._get_provider_anthropic_messages_config_cached.cache_clear()