diff --git a/litellm/litellm_core_utils/fallback_generalizations.py b/litellm/litellm_core_utils/fallback_generalizations.py index 9b5c369b56e..25ea1bff613 100644 --- a/litellm/litellm_core_utils/fallback_generalizations.py +++ b/litellm/litellm_core_utils/fallback_generalizations.py @@ -53,7 +53,9 @@ O(number of rules); callers must only invoke them on a cache miss. import logging import re +from collections.abc import Mapping from dataclasses import dataclass +from types import MappingProxyType from typing import Final verbose_logger: Final = logging.getLogger("LiteLLM") @@ -209,9 +211,7 @@ class _FallbackGeneralizations: return None return {key: value for model_info in matched for key, value in model_info.items()} - def match_fill_missing( - self, model: str, provider: str - ) -> dict[str, object] | None: # mutable-ok: preserve the existing dict return contract + def match_fill_missing(self, model: str, provider: str) -> Mapping[str, object] | None: if not model or not provider: return None matched = tuple( @@ -221,9 +221,9 @@ class _FallbackGeneralizations: ) if not matched: return None - fill_missing: Final[dict[str, object]] = { # mutable-ok: preserve the existing dict merge input - key: value for model_info in matched for key, value in model_info.items() if key != PROVIDER_KEY - } + fill_missing: Final[Mapping[str, object]] = MappingProxyType( + {key: value for model_info in matched for key, value in model_info.items() if key != PROVIDER_KEY} + ) return fill_missing or None @@ -263,9 +263,7 @@ def match_capability_generalizations(model: str) -> dict | None: return _registry.match_capabilities(model) -def match_fill_missing_generalizations( - model: str, provider: str -) -> dict[str, object] | None: # mutable-ok: preserve the existing dict return contract +def match_fill_missing_generalizations(model: str, provider: str) -> Mapping[str, object] | None: """Return flagged capability rules matching ``model`` for ``provider``. Later rules override earlier ones on key conflicts. Only rules listing