refactor: declare each lazy litellm attribute once and resolve them through one function (#50523)

This commit is contained in:
Mateo Wang 2026-11-07 09:50:01 -08:00 • committed by GitHub
parent 4ed339b2fc
commit 1f98627d4a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 816 additions and 2659 deletions

View file

@ -81,7 +81,6 @@ from litellm.constants import (
import httpx
from openai import DefaultAsyncHttpxClient, DefaultHttpxClient
# register_async_client_cleanup is lazy-loaded and called on first access
litellm_mode = os.getenv("LITELLM_MODE", "DEV") # "PRODUCTION", "DEV"
@ -98,7 +97,6 @@ failure_callback: List[CALLBACK_TYPES] = []
service_callback: List[CALLBACK_TYPES] = []
audit_log_callbacks: List[CALLBACK_TYPES] = []
batch_line_item_callbacks: Sequence[CALLBACK_TYPES] = ()
# logging_callback_manager is lazy-loaded via __getattr__
_custom_logger_compatible_callbacks_literal = Literal[
"lago",
"openmeter",
@ -507,8 +505,6 @@ skill_search_embedding_model: Optional[str] = None
public_model_groups_links: dict[str, str | dict[str, object]] = {}
#### REQUEST PRIORITIZATION #######
priority_reservation: Optional[Dict[str, Union[float, "PriorityReservationDict"]]] = None
# priority_reservation_settings is lazy-loaded via __getattr__
# Only declare for type checking - at runtime __getattr__ handles it
if TYPE_CHECKING:
priority_reservation_settings: Optional["PriorityReservationSettings"] = None
@ -543,8 +539,6 @@ _google_kms_resource_name: Optional[str] = None
_key_management_system: Optional["KeyManagementSystem"] = None
# Note: KeyManagementSettings must be eagerly imported because _key_management_settings
# is accessed during import time in secret_managers/main.py
# We'll import it after the lazy import system is set up
# We can't define it here because KeyManagementSettings is lazy-loaded
#### PII MASKING ####
output_parse_pii: bool = False
#############################################
@ -1196,8 +1190,6 @@ model_list = list(
model_list_set = set(model_list)
# provider_list is lazy-loaded via __getattr__ to avoid importing LlmProviders at import time
def _build_models_by_provider() -> dict:
return {
@ -1378,10 +1370,6 @@ all_embedding_models = (
####### VIDEO GENERATION MODELS ###################
openai_video_generation_models = ["sora-2"]
# timeout is lazy-loaded via __getattr__
# get_llm_provider is lazy-loaded via __getattr__
# remove_index_from_tool_calls is lazy-loaded via __getattr__
# Import KeyManagementSettings here (before utils import) because _key_management_settings
# is accessed during import time in secret_managers/main.py (via dd_tracing -> datadog -> _service_logger -> utils)
from litellm.types.secret_managers.main import KeyManagementSettings
@ -1391,8 +1379,6 @@ _key_management_settings: KeyManagementSettings = KeyManagementSettings()
# client must be imported immediately as it's used as a decorator at function definition time
from .utils import client
# Note: Most other utils imports are lazy-loaded via __getattr__ to avoid loading utils.py
# (which imports tiktoken) at import time
from .llms.custom_llm import CustomLLM
from .llms.anthropic.common_utils import AnthropicModelInfo
@ -1416,12 +1402,9 @@ from .llms.bedrock.embed.amazon_titan_v2_transformation import (
)
from .llms.topaz.common_utils import TopazModelInfo
# OpenAIOSeriesConfig is lazy loaded - openaiOSeriesConfig will be created on first access
# OpenAIGPTConfig, OpenAIGPT5Config, etc. are lazy loaded - instances will be created on first access
from .llms.xai.common_utils import XAIModelInfo
# PublicAI now uses JSON-based configuration (see litellm/llms/openai_like/providers.json)
# All remaining configs are now lazy loaded - see _lazy_imports_registry.py
# Import LlmProviders here (before main import) because it's imported during import time
# in multiple places including openai.py (via main import)
@ -1650,8 +1633,6 @@ def set_global_gitlab_config(config: Mapping[str, object]) -> None:
global_gitlab_config = config
# Lazy loading system for heavy modules to reduce initial import time and memory usage
if TYPE_CHECKING:
from . import guardrails as guardrails
from litellm.types.utils import ModelInfo as _ModelInfoType
@ -1659,7 +1640,6 @@ if TYPE_CHECKING:
from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler
from litellm.caching.caching import Cache
# Type stubs for lazy-loaded configs to help mypy
from .llms.bedrock.chat.converse_transformation import (
AmazonConverseConfig as AmazonConverseConfig,
)
@ -2088,7 +2068,6 @@ if TYPE_CHECKING:
)
from .llms.gdc.chat.transformation import GDCGeminiConfig as GDCGeminiConfig
# Type stubs for lazy-loaded config instances
openaiOSeriesConfig: OpenAIOSeriesConfig
openAIGPTConfig: OpenAIGPTConfig
openAIGPTAudioConfig: OpenAIGPTAudioConfig
@ -2146,7 +2125,6 @@ if TYPE_CHECKING:
VertexGeminiConfig as _VertexGeminiConfig,
)
# Type stubs for lazy-loaded config classes (to help mypy understand types)
VLLMConfig: Type[_VLLMConfig]
DeepSeekChatConfig: Type[_DeepSeekChatConfig]
TencentChatConfig: Type[_TencentChatConfig]
@ -2423,63 +2401,34 @@ if TYPE_CHECKING:
module_level_aclient: AsyncHTTPHandler
module_level_client: HTTPHandler
# Bedrock tool name mappings instance (lazy-loaded)
from litellm.caching.caching import InMemoryCache
bedrock_tool_name_mappings: InMemoryCache
# Azure exception class (lazy-loaded)
from litellm.llms.azure.common_utils import AzureOpenAIError
# Secret manager types (lazy-loaded)
from litellm.types.secret_managers.main import (
KeyManagementSystem,
KeyManagementSettings, # Not lazy-loaded - needed for _key_management_settings initialization
)
# Custom logger class (lazy-loaded)
from litellm.integrations.custom_logger import CustomLogger
# Datadog LLM observability params (lazy-loaded)
from litellm.types.integrations.datadog_llm_obs import DatadogLLMObsInitParams
# Logging callback manager class and instance (lazy-loaded)
from litellm.litellm_core_utils.logging_callback_manager import (
LoggingCallbackManager,
)
logging_callback_manager: LoggingCallbackManager
# provider_list is lazy-loaded
from litellm.types.utils import LlmProviders
provider_list: List[Union[LlmProviders, str]]
# Note: AmazonConverseConfig and OpenAILikeChatConfig are imported above in TYPE_CHECKING block
# Track if async client cleanup has been registered (for lazy loading)
_async_client_cleanup_registered = False
_AGENT_EXPORTS: Final = frozenset(
{
"agent",
"aagent",
"agent_session",
"aagent_session",
"agent_resume",
"aagent_resume",
"agent_capabilities",
"Harness",
"ClaudeCodeOptions",
"CodexOptions",
"OpenCodeOptions",
"PiOptions",
"DeepAgentsOptions",
"ToolLoopOptions",
}
)
# Eager loading for backwards compatibility with VCR and other HTTP recording tools
# When LITELLM_DISABLE_LAZY_LOADING is set, lazy-loaded attributes are loaded at import time
# For now, this only affects encoding (tiktoken) as it was the only reported issue
@ -2492,9 +2441,7 @@ if os.getenv("LITELLM_DISABLE_LAZY_LOADING", "").lower() in ("1", "true", "yes",
def __getattr__(name: str) -> Any:
"""Lazy import handler with cached registry for improved performance."""
global _async_client_cleanup_registered
# Register async client cleanup on first access (only once)
if not _async_client_cleanup_registered:
from litellm.llms.custom_httpx.async_client_cleanup import (
register_async_client_cleanup,
@ -2503,205 +2450,9 @@ def __getattr__(name: str) -> Any:
register_async_client_cleanup()
_async_client_cleanup_registered = True
# Use cached registry from _lazy_imports instead of importing tuples every time
from ._lazy_imports import get_lazy_import_registry
from ._lazy_imports import resolve_lazy_attribute
registry: Final = get_lazy_import_registry()
return resolve_lazy_attribute(__name__, name)
# Check if name is in registry and call the cached handler function
if name in registry:
handler_func: Final = registry[name]
return handler_func(name)
if name in ("proxy", "guardrails"):
import importlib
return importlib.import_module(f"litellm.{name}")
if name == "harness" or name in _AGENT_EXPORTS:
import importlib
harness_module = importlib.import_module("litellm.harness")
return harness_module if name == "harness" else getattr(harness_module, name)
# Lazy load encoding from main.py to avoid heavy tiktoken import
if name == "encoding":
from ._lazy_imports import get_litellm_globals
_globals = get_litellm_globals()
# Check if already cached
if "encoding" not in _globals:
from .main import encoding as _encoding
_globals["encoding"] = _encoding
return _globals["encoding"]
# Lazy load bedrock_tool_name_mappings instance
if name == "bedrock_tool_name_mappings":
from ._lazy_imports import get_litellm_globals
_globals = get_litellm_globals()
# Check if already cached
if "bedrock_tool_name_mappings" not in _globals:
from .llms.bedrock.chat.invoke_handler import (
bedrock_tool_name_mappings as _bedrock_tool_name_mappings,
)
_globals["bedrock_tool_name_mappings"] = _bedrock_tool_name_mappings
return _globals["bedrock_tool_name_mappings"]
# Lazy load AzureOpenAIError exception class
if name == "AzureOpenAIError":
from ._lazy_imports import get_litellm_globals
_globals = get_litellm_globals()
# Check if already cached
if "AzureOpenAIError" not in _globals:
from .llms.azure.common_utils import AzureOpenAIError as _AzureOpenAIError
_globals["AzureOpenAIError"] = _AzureOpenAIError
return _globals["AzureOpenAIError"]
# Lazy load openaiOSeriesConfig instance
if name == "openaiOSeriesConfig":
from ._lazy_imports import get_litellm_globals
_globals = get_litellm_globals()
if "openaiOSeriesConfig" not in _globals:
# Import the config class and instantiate it
config_class = __getattr__("OpenAIOSeriesConfig")
_globals["openaiOSeriesConfig"] = config_class()
return _globals["openaiOSeriesConfig"]
# Lazy load other config instances
_config_instances: Final = {
"openAIGPTConfig": "OpenAIGPTConfig",
"openAIGPTAudioConfig": "OpenAIGPTAudioConfig",
"openAIGPT5Config": "OpenAIGPT5Config",
"nvidiaNimConfig": "NvidiaNimConfig",
"nvidiaNimEmbeddingConfig": "NvidiaNimEmbeddingConfig",
}
if name in _config_instances:
from ._lazy_imports import get_litellm_globals
_globals = get_litellm_globals()
if name not in _globals:
# Import the config class and instantiate it
config_class = __getattr__(_config_instances[name])
_globals[name] = config_class()
return _globals[name]
# Handle OpenAIO1Config alias
if name == "OpenAIO1Config":
return __getattr__("OpenAIOSeriesConfig")
# Lazy load provider_list
if name == "provider_list":
from ._lazy_imports import get_litellm_globals
_globals = get_litellm_globals()
# Check if already cached
if "provider_list" not in _globals:
# LlmProviders is eagerly imported above, so we can import it directly
from litellm.types.utils import LlmProviders
_globals["provider_list"] = list(LlmProviders)
return _globals["provider_list"]
# Lazy load priority_reservation_settings instance
if name == "priority_reservation_settings":
from ._lazy_imports import get_litellm_globals
_globals = get_litellm_globals()
# Check if already cached
if "priority_reservation_settings" not in _globals:
# Import the class and instantiate it
PriorityReservationSettings: Final = __getattr__("PriorityReservationSettings")
_globals["priority_reservation_settings"] = PriorityReservationSettings()
return _globals["priority_reservation_settings"]
# Lazy load logging_callback_manager instance
if name == "logging_callback_manager":
from ._lazy_imports import get_litellm_globals
_globals = get_litellm_globals()
# Check if already cached
if "logging_callback_manager" not in _globals:
# Import the class and instantiate it
LoggingCallbackManager: Final = __getattr__("LoggingCallbackManager")
_globals["logging_callback_manager"] = LoggingCallbackManager()
return _globals["logging_callback_manager"]
# Lazy load _service_logger module
if name == "_service_logger":
from ._lazy_imports import get_litellm_globals
_globals = get_litellm_globals()
# Check if already cached
if "_service_logger" not in _globals:
# Import the module lazily
import litellm._service_logger
_globals["_service_logger"] = litellm._service_logger
return _globals["_service_logger"]
# Lazy load evals module functions
if name in [
"acreate_eval",
"alist_evals",
"aget_eval",
"aupdate_eval",
"adelete_eval",
"acancel_eval",
"create_eval",
"list_evals",
"get_eval",
"update_eval",
"delete_eval",
"cancel_eval",
"acreate_run",
"alist_runs",
"aget_run",
"acancel_run",
"adelete_run",
"create_run",
"list_runs",
"get_run",
"cancel_run",
"delete_run",
]:
from litellm.evals.main import (
acreate_eval,
alist_evals,
aget_eval,
aupdate_eval,
adelete_eval,
acancel_eval,
create_eval,
list_evals,
get_eval,
update_eval,
delete_eval,
cancel_eval,
acreate_run,
alist_runs,
aget_run,
acancel_run,
adelete_run,
create_run,
list_runs,
get_run,
cancel_run,
delete_run,
)
from types import MappingProxyType
evals_exports: Final[Mapping[str, object]] = MappingProxyType(locals())
return evals_exports[name]
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
# ALL_LITELLM_RESPONSE_TYPES is lazy-loaded via __getattr__ to avoid loading utils at import time
mark_litellm_import_complete()

View file

@ -1,60 +1,14 @@
"""
Lazy Import System
This module implements lazy loading for LiteLLM attributes. Instead of importing
everything when the module loads, we only import things when they're actually used.
How it works:
1. When someone accesses `litellm.some_attribute`, Python calls __getattr__ in __init__.py
2. __getattr__ looks up the attribute name in a registry
3. The registry points to a handler function (like _lazy_import_utils)
4. The handler function imports the module and returns the attribute
5. The result is cached so we don't import it again
This makes importing litellm much faster because we don't load heavy dependencies
until they're actually needed.
"""
"""Resolve the attributes of `litellm` and `litellm.utils` that are imported on first access."""
import importlib
import sys
from collections.abc import Callable, Mapping
from types import ModuleType
from typing import TYPE_CHECKING, Any, Final
from types import MappingProxyType, ModuleType
from typing import TYPE_CHECKING, Final
from typing_extensions import ReadOnly, TypedDict
# Import all the data structures that define what can be lazy-loaded
# These are just lists of names and maps of where to find them
from ._lazy_imports_registry import (
# Import maps
_BEDROCK_TYPES_IMPORT_MAP,
_CACHING_IMPORT_MAP,
_COST_CALCULATOR_IMPORT_MAP,
_DOTPROMPT_IMPORT_MAP,
_LITELLM_LOGGING_IMPORT_MAP,
_LLM_CONFIGS_IMPORT_MAP,
_LLM_PROVIDER_LOGIC_IMPORT_MAP,
_TOKEN_COUNTER_IMPORT_MAP,
_TYPES_IMPORT_MAP,
_TYPES_UTILS_IMPORT_MAP,
_UTILS_IMPORT_MAP,
_UTILS_MODULE_IMPORT_MAP,
# Name tuples
BEDROCK_TYPES_NAMES,
CACHING_NAMES,
COST_CALCULATOR_NAMES,
DOTPROMPT_NAMES,
HTTP_HANDLER_NAMES,
LITELLM_LOGGING_NAMES,
LLM_CLIENT_CACHE_NAMES,
LLM_CONFIG_NAMES,
LLM_PROVIDER_LOGIC_NAMES,
TOKEN_COUNTER_NAMES,
TYPES_NAMES,
TYPES_UTILS_NAMES,
UTILS_MODULE_NAMES,
UTILS_NAMES,
)
from ._lazy_imports_registry import LITELLM_ATTRIBUTES, UTILS_ATTRIBUTES
if TYPE_CHECKING:
import httpx
@ -62,35 +16,6 @@ if TYPE_CHECKING:
from litellm.litellm_core_utils.tokenizer import Encoding as Tokenizer
def get_litellm_globals() -> dict[str, object]:
"""
Get the globals dictionary of the litellm module.
This is where we cache imported attributes so we don't import them twice.
When you do `litellm.some_function`, it gets stored in this dictionary.
"""
return sys.modules["litellm"].__dict__
def _get_utils_globals() -> dict[str, object]:
"""
Get the globals dictionary of the utils module.
This is where we cache imported attributes so we don't import them twice.
When you do `litellm.utils.some_function`, it gets stored in this dictionary.
"""
return sys.modules["litellm.utils"].__dict__
def _get_module_level_client_timeout(litellm_globals: Mapping[str, Any]) -> "float | httpx.Timeout | None":
"""Read the configured `litellm.request_timeout` used for the module level http clients."""
return litellm_globals.get("request_timeout")
# These are special lazy loaders for things that are used internally
# They're separate from the main lazy import system because they have specific use cases
def get_default_encoding() -> "Tokenizer":
from litellm.rust_bridge.tokenizer import get_encoding
@ -100,138 +25,43 @@ def get_default_encoding() -> "Tokenizer":
_get_default_encoding = get_default_encoding
# Lazy loader for get_modified_max_tokens to avoid importing token_counter at module import time
_get_modified_max_tokens_func: "Callable[..., int | None] | None" = None
def _get_modified_max_tokens() -> "Callable[..., int | None]":
"""
Lazily load and cache the get_modified_max_tokens function.
from litellm.litellm_core_utils.token_counter import get_modified_max_tokens
This avoids importing `litellm.litellm_core_utils.token_counter` at `litellm` import time.
The function is cached after the first import.
This is used internally by utils.py functions that need the token counter but shouldn't
trigger its import during module load.
"""
global _get_modified_max_tokens_func
if _get_modified_max_tokens_func is None:
from litellm.litellm_core_utils.token_counter import (
get_modified_max_tokens as _get_modified_max_tokens_imported,
)
_get_modified_max_tokens_func = _get_modified_max_tokens_imported
return _get_modified_max_tokens_func
# Lazy loader for token_counter to avoid importing token_counter module at module import time
_token_counter_new_func: "Callable[..., int] | None" = None
_messages_reach_token_count_func: "Callable[..., bool] | None" = None
return get_modified_max_tokens
def get_token_counter_new() -> "Callable[..., int]":
"""
Lazily load and cache the token_counter function (aliased as token_counter_new).
from litellm.litellm_core_utils.token_counter import token_counter
This avoids importing `litellm.litellm_core_utils.token_counter` at `litellm` import time.
The function is cached after the first import.
This is used internally by utils.py functions that need the token counter but shouldn't
trigger its import during module load.
"""
global _token_counter_new_func
if _token_counter_new_func is None:
from litellm.litellm_core_utils.token_counter import (
token_counter as _token_counter_imported,
)
_token_counter_new_func = _token_counter_imported
return _token_counter_new_func
return token_counter
_get_token_counter_new = get_token_counter_new
def get_messages_reach_token_count() -> "Callable[..., bool]":
"""Lazily load ``messages_reach_token_count`` for the same reason as ``get_token_counter_new``."""
global _messages_reach_token_count_func
if _messages_reach_token_count_func is None:
from litellm.litellm_core_utils.token_counter import (
messages_reach_token_count as _messages_reach_token_count_imported,
)
from litellm.litellm_core_utils.token_counter import messages_reach_token_count
_messages_reach_token_count_func = _messages_reach_token_count_imported
return _messages_reach_token_count_func
return messages_reach_token_count
_get_messages_reach_token_count = get_messages_reach_token_count
# ============================================================================
# MAIN LAZY IMPORT SYSTEM
# ============================================================================
# This registry maps attribute names (like "ModelResponse") to handler functions
# It's built once the first time someone accesses a lazy-loaded attribute
# Example: {"ModelResponse": _lazy_import_utils, "Cache": _lazy_import_caching, ...}
_LAZY_IMPORT_REGISTRY: dict[str, Callable[[str], object]] | None = None
_NOT_LOADED: Final = object()
def get_lazy_import_registry() -> dict[str, Callable[[str], object]]:
"""
Build the registry that maps attribute names to their handler functions.
This is called once, the first time someone accesses a lazy-loaded attribute.
After that, we just look up the handler function in this dictionary.
Returns:
Dictionary like {"ModelResponse": _lazy_import_utils, ...}
"""
global _LAZY_IMPORT_REGISTRY
if _LAZY_IMPORT_REGISTRY is None:
# Build the registry by going through each category and mapping
# all the names in that category to their handler function
_LAZY_IMPORT_REGISTRY = {}
# For each category, map all its names to the handler function
# Example: All names in UTILS_NAMES get mapped to _lazy_import_utils
for name in COST_CALCULATOR_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_cost_calculator
for name in LITELLM_LOGGING_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_litellm_logging
for name in UTILS_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_utils
for name in TOKEN_COUNTER_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_token_counter
for name in LLM_CLIENT_CACHE_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_llm_client_cache
for name in BEDROCK_TYPES_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_bedrock_types
for name in TYPES_UTILS_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_types_utils
for name in CACHING_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_caching
for name in HTTP_HANDLER_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_http_handlers
for name in DOTPROMPT_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_dotprompt
for name in LLM_CONFIG_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_llm_configs
for name in TYPES_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_types
for name in LLM_PROVIDER_LOGIC_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_llm_provider_logic
for name in UTILS_MODULE_NAMES:
_LAZY_IMPORT_REGISTRY[name] = _lazy_import_utils_module
return _LAZY_IMPORT_REGISTRY
def _cached(namespace: str, name: str) -> object:
return vars(sys.modules[namespace]).get(name, _NOT_LOADED)
_get_lazy_import_registry = get_lazy_import_registry
def _cache(namespace: str, name: str, value: object) -> object:
setattr(sys.modules[namespace], name, value)
return value
class _AttributeView(TypedDict):
"""Holds one module attribute so the lazily fetched value is read back as ``object``."""
value: ReadOnly[object]
@ -240,241 +70,88 @@ def _module_attribute(module: ModuleType, attr_name: str) -> object:
return attribute["value"]
def _generic_lazy_import(name: str, import_map: Mapping[str, tuple[str, str]], category: str) -> object:
"""
Generic function that handles lazy importing for most attributes.
def _import(namespace: str, name: str, location: tuple[str, str]) -> object:
cached: Final = _cached(namespace, name)
if cached is not _NOT_LOADED:
return cached
module_path, attr_name = location
module: Final[ModuleType] = importlib.import_module(module_path, package="litellm")
return _cache(namespace, name, _module_attribute(module, attr_name))
This is the workhorse function - it does the actual importing and caching.
Most handler functions just call this with their specific import map.
Steps:
1. Check if the name exists in the import map (if not, raise error)
2. Check if we've already imported it (if yes, return cached value)
3. Look up where to find it (module_path and attr_name from the map)
4. Import the module (Python caches this automatically)
5. Get the attribute from the module
6. Cache it in _globals so we don't import again
7. Return it
def _instance_of(class_name: str) -> Callable[[], object]:
def create() -> object:
cls: Final = resolve_lazy_attribute("litellm", class_name)
assert isinstance(cls, type)
return cls()
Args:
name: The attribute name someone is trying to access (e.g., "ModelResponse")
import_map: Dictionary telling us where to find each attribute
Format: {"ModelResponse": (".utils", "ModelResponse")}
category: Just for error messages (e.g., "Utils", "Cost calculator")
"""
# Step 1: Make sure this attribute exists in our map
if name not in import_map:
raise AttributeError(f"{category} lazy import: unknown attribute {name!r}")
return create
# Step 2: Get the cache (where we store imported things)
_globals: Final = get_litellm_globals()
# Step 3: If we've already imported it, just return the cached version
if name in _globals:
return _globals[name]
def _submodule(module_path: str) -> Callable[[], object]:
return lambda: importlib.import_module(module_path)
# Step 4: Look up where to find this attribute
# The map tells us: (module_path, attribute_name)
# Example: (".utils", "ModelResponse") means "look in .utils module, get ModelResponse"
module_path, attr_name = import_map[name]
# Step 5: Import the module
# Python automatically caches modules in sys.modules, so calling this twice is fast
# If module_path starts with ".", it's a relative import (needs package="litellm")
# Otherwise it's an absolute import (like "litellm.caching.caching")
if module_path.startswith("."):
module = importlib.import_module(module_path, package="litellm")
else:
module = importlib.import_module(module_path)
def _request_timeout() -> "float | httpx.Timeout | None":
import httpx
# Step 6: Get the actual attribute from the module
# Example: getattr(utils_module, "ModelResponse") returns the ModelResponse class
value: Final = _module_attribute(module, attr_name)
timeout: Final = _cached("litellm", "request_timeout")
return timeout if isinstance(timeout, (int, float, httpx.Timeout)) else None
# Step 7: Cache it so we don't have to import again next time
_globals[name] = value
# Step 8: Return it
return value
def _module_level_aclient() -> object:
from litellm.llms.custom_httpx.http_handler import get_async_httpx_client
return get_async_httpx_client(
llm_provider="litellm_module_level_client",
params={"timeout": _request_timeout(), "client_alias": "module level aclient"},
)
# ============================================================================
# HANDLER FUNCTIONS
# ============================================================================
# These functions are called when someone accesses a lazy-loaded attribute.
# Most of them just call _generic_lazy_import with their specific import map.
# The registry (above) maps attribute names to these handler functions.
def _module_level_client() -> object:
from litellm.llms.custom_httpx.http_handler import HTTPHandler
def _lazy_import_utils(name: str) -> object:
"""Handler for utils module attributes (ModelResponse, token_counter, etc.)"""
return _generic_lazy_import(name, _UTILS_IMPORT_MAP, "Utils")
return HTTPHandler(timeout=_request_timeout())
def _lazy_import_cost_calculator(name: str) -> object:
"""Handler for cost calculator functions (completion_cost, cost_per_token, etc.)"""
return _generic_lazy_import(name, _COST_CALCULATOR_IMPORT_MAP, "Cost calculator")
def _provider_list() -> object:
from litellm.types.utils import LlmProviders
return list(LlmProviders)
def _lazy_import_token_counter(name: str) -> object:
"""Handler for token counter utilities"""
return _generic_lazy_import(name, _TOKEN_COUNTER_IMPORT_MAP, "Token counter")
_LITELLM_FACTORIES: Final[Mapping[str, Callable[[], object]]] = MappingProxyType(
{
"in_memory_llm_clients_cache": _instance_of("LLMClientCache"),
"module_level_aclient": _module_level_aclient,
"module_level_client": _module_level_client,
"openaiOSeriesConfig": _instance_of("OpenAIOSeriesConfig"),
"openAIGPTConfig": _instance_of("OpenAIGPTConfig"),
"openAIGPTAudioConfig": _instance_of("OpenAIGPTAudioConfig"),
"openAIGPT5Config": _instance_of("OpenAIGPT5Config"),
"nvidiaNimConfig": _instance_of("NvidiaNimConfig"),
"nvidiaNimEmbeddingConfig": _instance_of("NvidiaNimEmbeddingConfig"),
"priority_reservation_settings": _instance_of("PriorityReservationSettings"),
"logging_callback_manager": _instance_of("LoggingCallbackManager"),
"provider_list": _provider_list,
"proxy": _submodule("litellm.proxy"),
"guardrails": _submodule("litellm.guardrails"),
"harness": _submodule("litellm.harness"),
"_service_logger": _submodule("litellm._service_logger"),
}
)
def _lazy_import_bedrock_types(name: str) -> object:
"""Handler for Bedrock type aliases"""
return _generic_lazy_import(name, _BEDROCK_TYPES_IMPORT_MAP, "Bedrock types")
def _lazy_import_types_utils(name: str) -> object:
"""Handler for types from litellm.types.utils (BudgetConfig, ImageObject, etc.)"""
return _generic_lazy_import(name, _TYPES_UTILS_IMPORT_MAP, "Types utils")
def _lazy_import_caching(name: str) -> object:
"""Handler for caching classes (Cache, DualCache, RedisCache, etc.)"""
return _generic_lazy_import(name, _CACHING_IMPORT_MAP, "Caching")
def _lazy_import_dotprompt(name: str) -> object:
"""Handler for dotprompt integration globals"""
return _generic_lazy_import(name, _DOTPROMPT_IMPORT_MAP, "Dotprompt")
def _lazy_import_types(name: str) -> object:
"""Handler for type classes (GuardrailItem, etc.)"""
return _generic_lazy_import(name, _TYPES_IMPORT_MAP, "Types")
def _lazy_import_llm_configs(name: str) -> object:
"""Handler for LLM config classes (AnthropicConfig, OpenAILikeChatConfig, etc.)"""
return _generic_lazy_import(name, _LLM_CONFIGS_IMPORT_MAP, "LLM config")
def _lazy_import_litellm_logging(name: str) -> object:
"""Handler for litellm_logging module (Logging, modify_integration)"""
return _generic_lazy_import(name, _LITELLM_LOGGING_IMPORT_MAP, "Litellm logging")
def _lazy_import_llm_provider_logic(name: str) -> object:
"""Handler for LLM provider logic functions (get_llm_provider, etc.)"""
return _generic_lazy_import(name, _LLM_PROVIDER_LOGIC_IMPORT_MAP, "LLM provider logic")
def _lazy_import_utils_module(name: str) -> object:
"""
Handler for utils module lazy imports.
This uses a custom implementation because utils module needs to use
_get_utils_globals() instead of get_litellm_globals() for caching.
"""
# Check if this attribute exists in our map
if name not in _UTILS_MODULE_IMPORT_MAP:
raise AttributeError(f"Utils module lazy import: unknown attribute {name!r}")
# Get the cache (where we store imported things) - use utils globals
_globals: Final = _get_utils_globals()
# If we've already imported it, just return the cached version
if name in _globals:
return _globals[name]
# Look up where to find this attribute
module_path, attr_name = _UTILS_MODULE_IMPORT_MAP[name]
# Import the module
if module_path.startswith("."):
module = importlib.import_module(module_path, package="litellm")
else:
module = importlib.import_module(module_path)
# Get the actual attribute from the module
value: Final = _module_attribute(module, attr_name)
# Cache it so we don't have to import again next time
_globals[name] = value
# Return it
return value
# ============================================================================
# SPECIAL HANDLERS
# ============================================================================
# These handlers have custom logic that doesn't fit the generic pattern
def _lazy_import_llm_client_cache(name: str) -> object:
"""
Handler for LLM client cache - has special logic for singleton instance.
This one is different because:
- "LLMClientCache" is the class itself
- "in_memory_llm_clients_cache" is a singleton instance of that class
So we need custom logic to handle both cases.
"""
_globals: Final = get_litellm_globals()
# If already cached, return it
if name in _globals:
return _globals[name]
# Import the class
from litellm.caching.llm_caching_handler import LLMClientCache
# If they want the class itself, return it
if name == "LLMClientCache":
_globals["LLMClientCache"] = LLMClientCache
return LLMClientCache
# If they want the singleton instance, create it (only once)
if name == "in_memory_llm_clients_cache":
instance: Final = LLMClientCache()
_globals["in_memory_llm_clients_cache"] = instance
return instance
raise AttributeError(f"LLM client cache lazy import: unknown attribute {name!r}")
def _lazy_import_http_handlers(name: str) -> object:
"""
Handler for HTTP clients - has special logic for creating client instances.
This one is different because:
- These aren't just imports, they're actual client instances that need to be created
- They need configuration (timeout, etc.) from the module globals
- They use factory functions instead of direct instantiation
"""
_globals: Final = get_litellm_globals()
if name == "module_level_aclient":
# Create an async HTTP client using the factory function
from litellm.llms.custom_httpx.http_handler import get_async_httpx_client
# Get timeout from module config (if set)
async_timeout: Final = _get_module_level_client_timeout(_globals)
params: Final = {"timeout": async_timeout, "client_alias": "module level aclient"}
# Create the client instance
provider_id: Final = "litellm_module_level_client"
async_client: Final = get_async_httpx_client(
llm_provider=provider_id,
params=params,
)
# Cache it so we don't create it again
_globals["module_level_aclient"] = async_client
return async_client
if name == "module_level_client":
# Create a sync HTTP client
from litellm.llms.custom_httpx.http_handler import HTTPHandler
sync_timeout: Final = _get_module_level_client_timeout(_globals)
sync_client: Final = HTTPHandler(timeout=sync_timeout)
# Cache it
_globals["module_level_client"] = sync_client
return sync_client
raise AttributeError(f"HTTP handlers lazy import: unknown attribute {name!r}")
def resolve_lazy_attribute(module_name: str, name: str) -> object:
"""Import, cache and return `name`, the way `module_name.__getattr__` would."""
litellm_location: Final = LITELLM_ATTRIBUTES.get(name)
if litellm_location is not None:
return _import("litellm", name, litellm_location)
utils_location: Final = UTILS_ATTRIBUTES.get(name)
if utils_location is not None:
return _import("litellm.utils", name, utils_location)
factory: Final = _LITELLM_FACTORIES.get(name) if module_name == "litellm" else None
if factory is None:
raise AttributeError(f"module {module_name!r} has no attribute {name!r}")
cached: Final = _cached("litellm", name)
return cached if cached is not _NOT_LOADED else _cache("litellm", name, factory())

File diff suppressed because it is too large Load diff

View file

@ -12025,15 +12025,6 @@ def should_run_mock_completion(
def __getattr__(name: str) -> Any:
"""Lazy import handler for utils module with cached registry for improved performance."""
# Use cached registry from _lazy_imports instead of importing tuples every time
from litellm._lazy_imports import get_lazy_import_registry
from litellm._lazy_imports import resolve_lazy_attribute
registry: Final = get_lazy_import_registry()
# Check if name is in registry and call the cached handler function
if name in registry:
handler_func: Final = registry[name]
return handler_func(name)
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
return resolve_lazy_attribute(__name__, name)

View file

@ -1,5 +1,4 @@
"""Simple tests for lazy import functionality."""
import importlib
import os
import subprocess
import sys
@ -7,38 +6,9 @@ from typing import Final
import pytest
import litellm
from litellm._lazy_imports import (
COST_CALCULATOR_NAMES,
LITELLM_LOGGING_NAMES,
UTILS_NAMES,
TOKEN_COUNTER_NAMES,
CACHING_NAMES,
BEDROCK_TYPES_NAMES,
TYPES_UTILS_NAMES,
LLM_CLIENT_CACHE_NAMES,
HTTP_HANDLER_NAMES,
_lazy_import_cost_calculator,
_lazy_import_litellm_logging,
_lazy_import_utils,
_lazy_import_token_counter,
_lazy_import_bedrock_types,
_lazy_import_types_utils,
_lazy_import_caching,
_lazy_import_llm_client_cache,
_lazy_import_http_handlers,
DOTPROMPT_NAMES,
_lazy_import_dotprompt,
LLM_CONFIG_NAMES,
_lazy_import_llm_configs,
TYPES_NAMES,
_lazy_import_types,
LLM_PROVIDER_LOGIC_NAMES,
_lazy_import_llm_provider_logic,
UTILS_MODULE_NAMES,
_lazy_import_utils_module,
)
import litellm.utils
from litellm._lazy_imports_registry import LITELLM_ATTRIBUTES, UTILS_ATTRIBUTES
from tests.test_litellm_rust.support.child_interpreter import run_child_interpreter
@ -58,314 +28,75 @@ def test_import_litellm_does_not_load_fastapi_or_bpe_table():
assert result.stdout.strip() == ""
def _clear_names_from_globals(names: tuple):
"""Clear all names from litellm globals."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
for name in names:
if name in litellm_globals:
del litellm_globals[name]
def _clear_names_from_utils_globals(names: tuple):
"""Clear all names from litellm.utils globals."""
# Get the actual globals dict, not a copy
utils_globals = sys.modules["litellm.utils"].__dict__
for name in names:
if name in utils_globals:
del utils_globals[name]
def _verify_only_requested_name_imported(name: str, all_names: tuple):
"""Verify that only the requested name is in globals, not the others."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
for other_name in all_names:
if other_name != name:
assert (
other_name not in litellm_globals
), f"{other_name} should not be imported when importing {name}"
def _verify_only_requested_name_imported_in_utils(name: str, all_names: tuple):
"""Verify that only the requested name is in utils globals, not the others."""
# Get the actual globals dict, not a copy
utils_globals = sys.modules["litellm.utils"].__dict__
for other_name in all_names:
if other_name != name:
assert (
other_name not in utils_globals
), f"{other_name} should not be imported when importing {name}"
def test_cost_calculator_lazy_imports():
"""Test that all cost calculator functions can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
# Test each name individually - only that name should be imported
for name in COST_CALCULATOR_NAMES:
# Clear all names before importing just one
_clear_names_from_globals(COST_CALCULATOR_NAMES)
func = _lazy_import_cost_calculator(name)
assert func is not None
assert callable(func)
assert name in litellm_globals
# Verify only the requested name is in globals, not the others
_verify_only_requested_name_imported(name, COST_CALCULATOR_NAMES)
def test_litellm_logging_lazy_imports():
"""Test that all litellm_logging items can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
# Test each name individually - only that name should be imported
for name in LITELLM_LOGGING_NAMES:
# Clear all names before importing just one
_clear_names_from_globals(LITELLM_LOGGING_NAMES)
item = _lazy_import_litellm_logging(name)
assert item is not None
assert name in litellm_globals
# Verify only the requested name is in globals, not the others
_verify_only_requested_name_imported(name, LITELLM_LOGGING_NAMES)
def test_utils_lazy_imports():
"""Test that all utils functions can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
# Test each name individually - only that name should be imported
for name in UTILS_NAMES:
# Clear all names before importing just one
_clear_names_from_globals(UTILS_NAMES)
attr = _lazy_import_utils(name)
assert attr is not None
assert name in litellm_globals
# Verify only the requested name is in globals, not the others
_verify_only_requested_name_imported(name, UTILS_NAMES)
def test_caching_lazy_imports():
"""Test that all caching classes can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
# Test each name individually - only that name should be imported
for name in CACHING_NAMES:
# Clear all names before importing just one
_clear_names_from_globals(CACHING_NAMES)
cls = _lazy_import_caching(name)
assert cls is not None
assert name in litellm_globals
# Verify only the requested name is in globals, not the others
_verify_only_requested_name_imported(name, CACHING_NAMES)
def test_token_counter_lazy_imports():
"""Test that token counter utilities can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
for name in TOKEN_COUNTER_NAMES:
_clear_names_from_globals(TOKEN_COUNTER_NAMES)
func = _lazy_import_token_counter(name)
assert func is not None
assert name in litellm_globals
_verify_only_requested_name_imported(name, TOKEN_COUNTER_NAMES)
def test_bedrock_types_lazy_imports():
"""Test that Bedrock type aliases can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
for name in BEDROCK_TYPES_NAMES:
_clear_names_from_globals(BEDROCK_TYPES_NAMES)
alias = _lazy_import_bedrock_types(name)
assert alias is not None
assert name in litellm_globals
_verify_only_requested_name_imported(name, BEDROCK_TYPES_NAMES)
def test_types_utils_lazy_imports():
"""Test that common types.utils symbols can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
for name in TYPES_UTILS_NAMES:
_clear_names_from_globals(TYPES_UTILS_NAMES)
obj = _lazy_import_types_utils(name)
assert obj is not None
assert name in litellm_globals
_verify_only_requested_name_imported(name, TYPES_UTILS_NAMES)
def test_llm_client_cache_lazy_imports():
"""Test that LLM client cache class and singleton can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
for name in LLM_CLIENT_CACHE_NAMES:
_clear_names_from_globals(LLM_CLIENT_CACHE_NAMES)
obj = _lazy_import_llm_client_cache(name)
assert obj is not None
assert name in litellm_globals
_verify_only_requested_name_imported(name, LLM_CLIENT_CACHE_NAMES)
def test_http_handler_lazy_imports():
"""Test that HTTP handler singletons can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
for name in HTTP_HANDLER_NAMES:
_clear_names_from_globals(HTTP_HANDLER_NAMES)
handler = _lazy_import_http_handlers(name)
assert handler is not None
assert name in litellm_globals
_verify_only_requested_name_imported(name, HTTP_HANDLER_NAMES)
def test_dotprompt_lazy_imports():
"""Test that dotprompt globals can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
for name in DOTPROMPT_NAMES:
_clear_names_from_globals(DOTPROMPT_NAMES)
obj = _lazy_import_dotprompt(name)
assert name in litellm_globals
# Only the setter must be callable; others may be None by default
if name == "set_global_prompt_directory":
assert callable(obj), f"{name} should be callable"
_verify_only_requested_name_imported(name, DOTPROMPT_NAMES)
def test_unknown_attribute_raises_error():
"""Test that unknown attributes raise AttributeError."""
with pytest.raises(AttributeError):
_lazy_import_cost_calculator("unknown")
with pytest.raises(AttributeError):
_lazy_import_litellm_logging("unknown")
with pytest.raises(AttributeError):
_lazy_import_utils("unknown")
with pytest.raises(AttributeError):
_lazy_import_caching("unknown")
with pytest.raises(AttributeError):
_lazy_import_token_counter("unknown")
with pytest.raises(AttributeError):
_lazy_import_llm_client_cache("unknown")
with pytest.raises(AttributeError):
_lazy_import_bedrock_types("unknown")
with pytest.raises(AttributeError):
_lazy_import_types_utils("unknown")
with pytest.raises(AttributeError):
_lazy_import_llm_configs("unknown")
with pytest.raises(AttributeError):
_lazy_import_types("unknown")
with pytest.raises(AttributeError):
_lazy_import_llm_provider_logic("unknown")
with pytest.raises(AttributeError):
_lazy_import_utils_module("unknown")
def test_llm_config_lazy_imports():
"""Test that LLM config classes can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
for name in LLM_CONFIG_NAMES:
_clear_names_from_globals(LLM_CONFIG_NAMES)
obj = _lazy_import_llm_configs(name)
assert obj is not None
assert name in litellm_globals
# Config classes should be classes/types
assert isinstance(obj, type), f"{name} should be a class"
_verify_only_requested_name_imported(name, LLM_CONFIG_NAMES)
def test_types_lazy_imports():
"""Test that type classes can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
for name in TYPES_NAMES:
_clear_names_from_globals(TYPES_NAMES)
obj = _lazy_import_types(name)
assert obj is not None
assert name in litellm_globals
# Type classes should be classes/types
assert isinstance(obj, type), f"{name} should be a class"
_verify_only_requested_name_imported(name, TYPES_NAMES)
def test_llm_provider_logic_lazy_imports():
"""Test that LLM provider logic functions can be lazy imported."""
# Get the actual globals dict, not a copy
litellm_globals = sys.modules["litellm"].__dict__
for name in LLM_PROVIDER_LOGIC_NAMES:
_clear_names_from_globals(LLM_PROVIDER_LOGIC_NAMES)
func = _lazy_import_llm_provider_logic(name)
assert func is not None
assert callable(func)
assert name in litellm_globals
_verify_only_requested_name_imported(name, LLM_PROVIDER_LOGIC_NAMES)
def test_utils_module_lazy_imports():
"""Test that utils module attributes can be lazy imported."""
# Get the actual globals dict, not a copy
utils_globals = sys.modules["litellm.utils"].__dict__
for name in UTILS_MODULE_NAMES:
_clear_names_from_utils_globals(UTILS_MODULE_NAMES)
obj = _lazy_import_utils_module(name)
assert obj is not None
assert name in utils_globals
_verify_only_requested_name_imported_in_utils(name, UTILS_MODULE_NAMES)
def _declared(location: tuple[str, str]) -> object:
module_path, attr_name = location
return getattr(importlib.import_module(module_path, package="litellm"), attr_name)
@pytest.mark.parametrize("name", sorted(LITELLM_ATTRIBUTES))
def test_litellm_attribute_is_the_declared_object(name: str):
assert getattr(litellm, name) is _declared(LITELLM_ATTRIBUTES[name])
@pytest.mark.parametrize("name", sorted(UTILS_ATTRIBUTES))
def test_utils_attribute_is_the_same_object_from_litellm_and_litellm_utils(name: str):
expected: Final = _declared(UTILS_ATTRIBUTES[name])
assert getattr(litellm.utils, name) is expected
assert getattr(litellm, name) is expected
@pytest.mark.parametrize(
("instance_name", "class_name"),
[
("in_memory_llm_clients_cache", "LLMClientCache"),
("openaiOSeriesConfig", "OpenAIOSeriesConfig"),
("openAIGPTConfig", "OpenAIGPTConfig"),
("openAIGPTAudioConfig", "OpenAIGPTAudioConfig"),
("openAIGPT5Config", "OpenAIGPT5Config"),
("nvidiaNimConfig", "NvidiaNimConfig"),
("nvidiaNimEmbeddingConfig", "NvidiaNimEmbeddingConfig"),
("priority_reservation_settings", "PriorityReservationSettings"),
("logging_callback_manager", "LoggingCallbackManager"),
],
)
def test_lazy_instance_is_a_single_instance_of_its_class(instance_name: str, class_name: str):
instance: Final = getattr(litellm, instance_name)
assert type(instance) is getattr(litellm, class_name)
assert getattr(litellm, instance_name) is instance
def test_module_level_http_clients_use_request_timeout(monkeypatch: pytest.MonkeyPatch):
client_names: Final = ("module_level_client", "module_level_aclient")
monkeypatch.setattr(litellm, "request_timeout", 7)
for client_name in client_names:
monkeypatch.delitem(vars(litellm), client_name, raising=False)
try:
assert litellm.module_level_client.timeout == 7
assert litellm.module_level_aclient.timeout == 7
assert litellm.module_level_client is litellm.module_level_client
finally:
for client_name in client_names:
vars(litellm).pop(client_name, None)
def test_provider_list_lists_every_provider():
assert litellm.provider_list == list(litellm.LlmProviders)
@pytest.mark.parametrize("name", ["proxy", "guardrails", "harness", "_service_logger"])
def test_submodule_attribute_is_the_submodule(name: str):
assert getattr(litellm, name) is importlib.import_module(f"litellm.{name}")
@pytest.mark.parametrize("module", [litellm, litellm.utils])
def test_unknown_attribute_raises_attribute_error(module: object):
with pytest.raises(AttributeError, match="not_a_litellm_attribute"):
getattr(module, "not_a_litellm_attribute")
assert not hasattr(module, "not_a_litellm_attribute")
def test_litellm_instances_are_not_attributes_of_litellm_utils():
assert not hasattr(litellm.utils, "module_level_client")
@pytest.mark.parametrize(

View file

@ -1185,7 +1185,6 @@ ALIAS_CASES: Final = (
("litellm", "", "_turn_on_debug", "turn_on_debug", False),
("litellm", "", "_turn_on_json", "turn_on_json", False),
("litellm._lazy_imports", "", "_get_default_encoding", "get_default_encoding", False),
("litellm._lazy_imports", "", "_get_lazy_import_registry", "get_lazy_import_registry", False),
("litellm._lazy_imports", "", "_get_messages_reach_token_count", "get_messages_reach_token_count", False),
("litellm._lazy_imports", "", "_get_token_counter_new", "get_token_counter_new", False),
("litellm._logging", "", "_is_debugging_on", "is_debugging_on", False),