refactor: migrate utils.py lazy imports to registry pattern

- Refactored utils.py __getattr__ to use cached registry pattern (similar to __init__.py)
- Added UTILS_MODULE_NAMES tuple and _UTILS_MODULE_IMPORT_MAP to _lazy_imports_registry.py
- Added _get_utils_globals() helper function to _lazy_imports.py
- Added _lazy_import_utils_module() handler function for utils module lazy imports
- Updated _get_lazy_import_registry() to include utils module lazy imports
- Removed redundant _get_utils_globals() from utils.py (now in _lazy_imports.py)
- Added comprehensive tests for utils module lazy imports in test_lazy_imports.py

This refactoring:
- Reduces code duplication (from 670+ lines to ~10 lines in __getattr__)
- Improves maintainability (new lazy imports just need registry entry)
- Maintains consistency with __init__.py lazy import pattern
- All existing functionality preserved and tested
This commit is contained in:
Alexsander Hamir 2026-01-05 09:19:00 -08:00
parent d8d10f5e25
commit 64242d216a
4 changed files with 240 additions and 674 deletions

View file

@ -35,6 +35,7 @@ from ._lazy_imports_registry import (
LLM_CONFIG_NAMES,
TYPES_NAMES,
LLM_PROVIDER_LOGIC_NAMES,
UTILS_MODULE_NAMES,
# Import maps
_UTILS_IMPORT_MAP,
_COST_CALCULATOR_IMPORT_MAP,
@ -47,6 +48,7 @@ from ._lazy_imports_registry import (
_TYPES_IMPORT_MAP,
_LLM_CONFIGS_IMPORT_MAP,
_LLM_PROVIDER_LOGIC_IMPORT_MAP,
_UTILS_MODULE_IMPORT_MAP,
)
@ -59,6 +61,16 @@ def _get_litellm_globals() -> dict:
"""
return sys.modules["litellm"].__dict__
def _get_utils_globals() -> dict:
"""
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__
# 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
@ -185,6 +197,8 @@ def _get_lazy_import_registry() -> dict[str, Callable[[str], Any]]:
_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
@ -306,6 +320,43 @@ def _lazy_import_llm_provider_logic(name: str) -> Any:
"""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) -> Any:
"""
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 = _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 = getattr(module, attr_name)
# Cache it so we don't have to import again next time
_globals[name] = value
# Return it
return value
# ============================================================================
# SPECIAL HANDLERS
# ============================================================================

View file

@ -294,6 +294,80 @@ LLM_PROVIDER_LOGIC_NAMES = (
"remove_index_from_tool_calls",
)
# Utils module names that support lazy loading via _lazy_import_utils_module
# These are attributes accessed from litellm.utils module
UTILS_MODULE_NAMES = (
"encoding",
"BaseVectorStore",
"CredentialAccessor",
"exception_type",
"get_error_message",
"_get_response_headers",
"get_llm_provider",
"_is_non_openai_azure_model",
"get_supported_openai_params",
"LiteLLMResponseObjectHandler",
"_handle_invalid_parallel_tool_calls",
"convert_to_model_response_object",
"convert_to_streaming_response",
"convert_to_streaming_response_async",
"get_api_base",
"ResponseMetadata",
"_parse_content_for_reasoning",
"LiteLLMLoggingObject",
"redact_message_input_output_from_logging",
"CustomStreamWrapper",
"BaseGoogleGenAIGenerateContentConfig",
"BaseOCRConfig",
"BaseSearchConfig",
"BaseTextToSpeechConfig",
"BedrockModelInfo",
"CohereModelInfo",
"MistralOCRConfig",
"Rules",
"AsyncHTTPHandler",
"HTTPHandler",
"get_num_retries_from_retry_policy",
"reset_retry_policy",
"get_secret",
"get_coroutine_checker",
"get_litellm_logging_class",
"get_set_callbacks",
"get_litellm_metadata_from_kwargs",
"map_finish_reason",
"process_response_headers",
"delete_nested_value",
"is_nested_path",
"_get_base_model_from_litellm_call_metadata",
"get_litellm_params",
"_ensure_extra_body_is_safe",
"get_formatted_prompt",
"get_response_headers",
"update_response_metadata",
"executor",
"BaseAnthropicMessagesConfig",
"BaseAudioTranscriptionConfig",
"BaseBatchesConfig",
"BaseContainerConfig",
"BaseEmbeddingConfig",
"BaseImageEditConfig",
"BaseImageGenerationConfig",
"BaseImageVariationConfig",
"BasePassthroughConfig",
"BaseRealtimeConfig",
"BaseRerankConfig",
"BaseVectorStoreConfig",
"BaseVectorStoreFilesConfig",
"BaseVideoConfig",
"ANTHROPIC_API_ONLY_HEADERS",
"AnthropicThinkingParam",
"RerankResponse",
"ChatCompletionDeltaToolCallChunk",
"ChatCompletionToolCallChunk",
"ChatCompletionToolCallFunctionChunk",
"LiteLLM_Params",
)
# Import maps for registry pattern - reduces repetition
_UTILS_IMPORT_MAP = {
"exception_type": (".utils", "exception_type"),
@ -586,6 +660,79 @@ _LLM_CONFIGS_IMPORT_MAP = {
"AmazonNovaChatConfig": (".llms.amazon_nova.chat.transformation", "AmazonNovaChatConfig"),
}
# Import map for utils module lazy imports
_UTILS_MODULE_IMPORT_MAP = {
"encoding": ("litellm.main", "encoding"),
"BaseVectorStore": ("litellm.integrations.vector_store_integrations.base_vector_store", "BaseVectorStore"),
"CredentialAccessor": ("litellm.litellm_core_utils.credential_accessor", "CredentialAccessor"),
"exception_type": ("litellm.litellm_core_utils.exception_mapping_utils", "exception_type"),
"get_error_message": ("litellm.litellm_core_utils.exception_mapping_utils", "get_error_message"),
"_get_response_headers": ("litellm.litellm_core_utils.exception_mapping_utils", "_get_response_headers"),
"get_llm_provider": ("litellm.litellm_core_utils.get_llm_provider_logic", "get_llm_provider"),
"_is_non_openai_azure_model": ("litellm.litellm_core_utils.get_llm_provider_logic", "_is_non_openai_azure_model"),
"get_supported_openai_params": ("litellm.litellm_core_utils.get_supported_openai_params", "get_supported_openai_params"),
"LiteLLMResponseObjectHandler": ("litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", "LiteLLMResponseObjectHandler"),
"_handle_invalid_parallel_tool_calls": ("litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", "_handle_invalid_parallel_tool_calls"),
"convert_to_model_response_object": ("litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", "convert_to_model_response_object"),
"convert_to_streaming_response": ("litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", "convert_to_streaming_response"),
"convert_to_streaming_response_async": ("litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", "convert_to_streaming_response_async"),
"get_api_base": ("litellm.litellm_core_utils.llm_response_utils.get_api_base", "get_api_base"),
"ResponseMetadata": ("litellm.litellm_core_utils.llm_response_utils.response_metadata", "ResponseMetadata"),
"_parse_content_for_reasoning": ("litellm.litellm_core_utils.prompt_templates.common_utils", "_parse_content_for_reasoning"),
"LiteLLMLoggingObject": ("litellm.litellm_core_utils.redact_messages", "LiteLLMLoggingObject"),
"redact_message_input_output_from_logging": ("litellm.litellm_core_utils.redact_messages", "redact_message_input_output_from_logging"),
"CustomStreamWrapper": ("litellm.litellm_core_utils.streaming_handler", "CustomStreamWrapper"),
"BaseGoogleGenAIGenerateContentConfig": ("litellm.llms.base_llm.google_genai.transformation", "BaseGoogleGenAIGenerateContentConfig"),
"BaseOCRConfig": ("litellm.llms.base_llm.ocr.transformation", "BaseOCRConfig"),
"BaseSearchConfig": ("litellm.llms.base_llm.search.transformation", "BaseSearchConfig"),
"BaseTextToSpeechConfig": ("litellm.llms.base_llm.text_to_speech.transformation", "BaseTextToSpeechConfig"),
"BedrockModelInfo": ("litellm.llms.bedrock.common_utils", "BedrockModelInfo"),
"CohereModelInfo": ("litellm.llms.cohere.common_utils", "CohereModelInfo"),
"MistralOCRConfig": ("litellm.llms.mistral.ocr.transformation", "MistralOCRConfig"),
"Rules": ("litellm.litellm_core_utils.rules", "Rules"),
"AsyncHTTPHandler": ("litellm.llms.custom_httpx.http_handler", "AsyncHTTPHandler"),
"HTTPHandler": ("litellm.llms.custom_httpx.http_handler", "HTTPHandler"),
"get_num_retries_from_retry_policy": ("litellm.router_utils.get_retry_from_policy", "get_num_retries_from_retry_policy"),
"reset_retry_policy": ("litellm.router_utils.get_retry_from_policy", "reset_retry_policy"),
"get_secret": ("litellm.secret_managers.main", "get_secret"),
"get_coroutine_checker": ("litellm.litellm_core_utils.cached_imports", "get_coroutine_checker"),
"get_litellm_logging_class": ("litellm.litellm_core_utils.cached_imports", "get_litellm_logging_class"),
"get_set_callbacks": ("litellm.litellm_core_utils.cached_imports", "get_set_callbacks"),
"get_litellm_metadata_from_kwargs": ("litellm.litellm_core_utils.core_helpers", "get_litellm_metadata_from_kwargs"),
"map_finish_reason": ("litellm.litellm_core_utils.core_helpers", "map_finish_reason"),
"process_response_headers": ("litellm.litellm_core_utils.core_helpers", "process_response_headers"),
"delete_nested_value": ("litellm.litellm_core_utils.dot_notation_indexing", "delete_nested_value"),
"is_nested_path": ("litellm.litellm_core_utils.dot_notation_indexing", "is_nested_path"),
"_get_base_model_from_litellm_call_metadata": ("litellm.litellm_core_utils.get_litellm_params", "_get_base_model_from_litellm_call_metadata"),
"get_litellm_params": ("litellm.litellm_core_utils.get_litellm_params", "get_litellm_params"),
"_ensure_extra_body_is_safe": ("litellm.litellm_core_utils.llm_request_utils", "_ensure_extra_body_is_safe"),
"get_formatted_prompt": ("litellm.litellm_core_utils.llm_response_utils.get_formatted_prompt", "get_formatted_prompt"),
"get_response_headers": ("litellm.litellm_core_utils.llm_response_utils.get_headers", "get_response_headers"),
"update_response_metadata": ("litellm.litellm_core_utils.llm_response_utils.response_metadata", "update_response_metadata"),
"executor": ("litellm.litellm_core_utils.thread_pool_executor", "executor"),
"BaseAnthropicMessagesConfig": ("litellm.llms.base_llm.anthropic_messages.transformation", "BaseAnthropicMessagesConfig"),
"BaseAudioTranscriptionConfig": ("litellm.llms.base_llm.audio_transcription.transformation", "BaseAudioTranscriptionConfig"),
"BaseBatchesConfig": ("litellm.llms.base_llm.batches.transformation", "BaseBatchesConfig"),
"BaseContainerConfig": ("litellm.llms.base_llm.containers.transformation", "BaseContainerConfig"),
"BaseEmbeddingConfig": ("litellm.llms.base_llm.embedding.transformation", "BaseEmbeddingConfig"),
"BaseImageEditConfig": ("litellm.llms.base_llm.image_edit.transformation", "BaseImageEditConfig"),
"BaseImageGenerationConfig": ("litellm.llms.base_llm.image_generation.transformation", "BaseImageGenerationConfig"),
"BaseImageVariationConfig": ("litellm.llms.base_llm.image_variations.transformation", "BaseImageVariationConfig"),
"BasePassthroughConfig": ("litellm.llms.base_llm.passthrough.transformation", "BasePassthroughConfig"),
"BaseRealtimeConfig": ("litellm.llms.base_llm.realtime.transformation", "BaseRealtimeConfig"),
"BaseRerankConfig": ("litellm.llms.base_llm.rerank.transformation", "BaseRerankConfig"),
"BaseVectorStoreConfig": ("litellm.llms.base_llm.vector_store.transformation", "BaseVectorStoreConfig"),
"BaseVectorStoreFilesConfig": ("litellm.llms.base_llm.vector_store_files.transformation", "BaseVectorStoreFilesConfig"),
"BaseVideoConfig": ("litellm.llms.base_llm.videos.transformation", "BaseVideoConfig"),
"ANTHROPIC_API_ONLY_HEADERS": ("litellm.types.llms.anthropic", "ANTHROPIC_API_ONLY_HEADERS"),
"AnthropicThinkingParam": ("litellm.types.llms.anthropic", "AnthropicThinkingParam"),
"RerankResponse": ("litellm.types.rerank", "RerankResponse"),
"ChatCompletionDeltaToolCallChunk": ("litellm.types.llms.openai", "ChatCompletionDeltaToolCallChunk"),
"ChatCompletionToolCallChunk": ("litellm.types.llms.openai", "ChatCompletionToolCallChunk"),
"ChatCompletionToolCallFunctionChunk": ("litellm.types.llms.openai", "ChatCompletionToolCallFunctionChunk"),
"LiteLLM_Params": ("litellm.types.router", "LiteLLM_Params"),
}
# Export all name tuples and import maps for use in _lazy_imports.py
__all__ = [
# Name tuples
@ -602,6 +749,7 @@ __all__ = [
"LLM_CONFIG_NAMES",
"TYPES_NAMES",
"LLM_PROVIDER_LOGIC_NAMES",
"UTILS_MODULE_NAMES",
# Import maps
"_UTILS_IMPORT_MAP",
"_COST_CALCULATOR_IMPORT_MAP",
@ -614,5 +762,6 @@ __all__ = [
"_TYPES_IMPORT_MAP",
"_LLM_CONFIGS_IMPORT_MAP",
"_LLM_PROVIDER_LOGIC_IMPORT_MAP",
"_UTILS_MODULE_IMPORT_MAP",
]

View file

@ -615,15 +615,6 @@ def get_applied_guardrails(kwargs: Dict[str, Any]) -> List[str]:
return applied_guardrails
def _get_utils_globals() -> dict:
"""
Get the globals dictionary of the utils module.
This is where we cache imported attributes so we don't import them twice.
"""
return sys.modules[__name__].__dict__
def load_credentials_from_list(kwargs: dict):
"""
Updates kwargs with the credentials if credential_name in kwarg
@ -8749,672 +8740,16 @@ def should_run_mock_completion(
return False
def __getattr__(name: str) -> Any: # noqa: PLR0915
"""Lazy import handler for utils module"""
_globals = _get_utils_globals()
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
# Lazy load encoding from main.py to avoid heavy tiktoken import
if name == "encoding":
# Check if already cached
if "encoding" not in _globals:
from litellm.main import encoding as _encoding
_globals["encoding"] = _encoding
return _globals["encoding"]
registry = _get_lazy_import_registry()
# Lazy load BaseVectorStore to avoid loading it at module import time
if name == "BaseVectorStore":
# Check if already cached
if "BaseVectorStore" not in _globals:
from litellm.integrations.vector_store_integrations.base_vector_store import (
BaseVectorStore as _BaseVectorStore,
)
_globals["BaseVectorStore"] = _BaseVectorStore
return _globals["BaseVectorStore"]
# Lazy load CredentialAccessor to avoid loading it at module import time
if name == "CredentialAccessor":
# Check if already cached
if "CredentialAccessor" not in _globals:
from litellm.litellm_core_utils.credential_accessor import (
CredentialAccessor as _CredentialAccessor,
)
_globals["CredentialAccessor"] = _CredentialAccessor
return _globals["CredentialAccessor"]
# Lazy load exception_mapping_utils functions to avoid loading at module import time
if name == "exception_type":
# Check if already cached
if "exception_type" not in _globals:
from litellm.litellm_core_utils.exception_mapping_utils import (
exception_type as _exception_type,
)
_globals["exception_type"] = _exception_type
return _globals["exception_type"]
if name == "get_error_message":
# Check if already cached
if "get_error_message" not in _globals:
from litellm.litellm_core_utils.exception_mapping_utils import (
get_error_message as _get_error_message,
)
_globals["get_error_message"] = _get_error_message
return _globals["get_error_message"]
if name == "_get_response_headers":
# Check if already cached
if "_get_response_headers" not in _globals:
from litellm.litellm_core_utils.exception_mapping_utils import (
_get_response_headers as __get_response_headers,
)
_globals["_get_response_headers"] = __get_response_headers
return _globals["_get_response_headers"]
# Lazy load get_llm_provider_logic functions to avoid loading at module import time
if name == "get_llm_provider":
# Check if already cached
if "get_llm_provider" not in _globals:
from litellm.litellm_core_utils.get_llm_provider_logic import (
get_llm_provider as _get_llm_provider,
)
_globals["get_llm_provider"] = _get_llm_provider
return _globals["get_llm_provider"]
if name == "_is_non_openai_azure_model":
# Check if already cached
if "_is_non_openai_azure_model" not in _globals:
from litellm.litellm_core_utils.get_llm_provider_logic import (
_is_non_openai_azure_model as __is_non_openai_azure_model,
)
_globals["_is_non_openai_azure_model"] = __is_non_openai_azure_model
return _globals["_is_non_openai_azure_model"]
# Lazy load get_supported_openai_params to avoid loading at module import time
if name == "get_supported_openai_params":
# Check if already cached
if "get_supported_openai_params" not in _globals:
from litellm.litellm_core_utils.get_supported_openai_params import (
get_supported_openai_params as _get_supported_openai_params,
)
_globals["get_supported_openai_params"] = _get_supported_openai_params
return _globals["get_supported_openai_params"]
# Lazy load convert_dict_to_response functions to avoid loading at module import time
if name == "LiteLLMResponseObjectHandler":
# Check if already cached
if "LiteLLMResponseObjectHandler" not in _globals:
from litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response import (
LiteLLMResponseObjectHandler as _LiteLLMResponseObjectHandler,
)
_globals["LiteLLMResponseObjectHandler"] = _LiteLLMResponseObjectHandler
return _globals["LiteLLMResponseObjectHandler"]
if name == "_handle_invalid_parallel_tool_calls":
# Check if already cached
if "_handle_invalid_parallel_tool_calls" not in _globals:
from litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response import (
_handle_invalid_parallel_tool_calls as __handle_invalid_parallel_tool_calls,
)
_globals["_handle_invalid_parallel_tool_calls"] = __handle_invalid_parallel_tool_calls
return _globals["_handle_invalid_parallel_tool_calls"]
if name == "convert_to_model_response_object":
# Check if already cached
if "convert_to_model_response_object" not in _globals:
from litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response import (
convert_to_model_response_object as _convert_to_model_response_object,
)
_globals["convert_to_model_response_object"] = _convert_to_model_response_object
return _globals["convert_to_model_response_object"]
if name == "convert_to_streaming_response":
# Check if already cached
if "convert_to_streaming_response" not in _globals:
from litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response import (
convert_to_streaming_response as _convert_to_streaming_response,
)
_globals["convert_to_streaming_response"] = _convert_to_streaming_response
return _globals["convert_to_streaming_response"]
if name == "convert_to_streaming_response_async":
# Check if already cached
if "convert_to_streaming_response_async" not in _globals:
from litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response import (
convert_to_streaming_response_async as _convert_to_streaming_response_async,
)
_globals["convert_to_streaming_response_async"] = _convert_to_streaming_response_async
return _globals["convert_to_streaming_response_async"]
# Lazy load get_api_base to avoid loading at module import time
if name == "get_api_base":
# Check if already cached
if "get_api_base" not in _globals:
from litellm.litellm_core_utils.llm_response_utils.get_api_base import (
get_api_base as _get_api_base,
)
_globals["get_api_base"] = _get_api_base
return _globals["get_api_base"]
# Lazy load ResponseMetadata to avoid loading at module import time
if name == "ResponseMetadata":
# Check if already cached
if "ResponseMetadata" not in _globals:
from litellm.litellm_core_utils.llm_response_utils.response_metadata import (
ResponseMetadata as _ResponseMetadata,
)
_globals["ResponseMetadata"] = _ResponseMetadata
return _globals["ResponseMetadata"]
# Lazy load _parse_content_for_reasoning to avoid loading at module import time
if name == "_parse_content_for_reasoning":
# Check if already cached
if "_parse_content_for_reasoning" not in _globals:
from litellm.litellm_core_utils.prompt_templates.common_utils import (
_parse_content_for_reasoning as __parse_content_for_reasoning,
)
_globals["_parse_content_for_reasoning"] = __parse_content_for_reasoning
return _globals["_parse_content_for_reasoning"]
# Lazy load redact_messages to avoid loading at module import time
if name == "LiteLLMLoggingObject":
# Check if already cached
if "LiteLLMLoggingObject" not in _globals:
from litellm.litellm_core_utils.redact_messages import (
LiteLLMLoggingObject as _LiteLLMLoggingObject,
)
_globals["LiteLLMLoggingObject"] = _LiteLLMLoggingObject
return _globals["LiteLLMLoggingObject"]
if name == "redact_message_input_output_from_logging":
# Check if already cached
if "redact_message_input_output_from_logging" not in _globals:
from litellm.litellm_core_utils.redact_messages import (
redact_message_input_output_from_logging as _redact_message_input_output_from_logging,
)
_globals["redact_message_input_output_from_logging"] = _redact_message_input_output_from_logging
return _globals["redact_message_input_output_from_logging"]
# Lazy load CustomStreamWrapper to avoid loading at module import time
if name == "CustomStreamWrapper":
# Check if already cached
if "CustomStreamWrapper" not in _globals:
from litellm.litellm_core_utils.streaming_handler import (
CustomStreamWrapper as _CustomStreamWrapper,
)
_globals["CustomStreamWrapper"] = _CustomStreamWrapper
return _globals["CustomStreamWrapper"]
# Lazy load BaseGoogleGenAIGenerateContentConfig to avoid loading at module import time
if name == "BaseGoogleGenAIGenerateContentConfig":
# Check if already cached
if "BaseGoogleGenAIGenerateContentConfig" not in _globals:
from litellm.llms.base_llm.google_genai.transformation import (
BaseGoogleGenAIGenerateContentConfig as _BaseGoogleGenAIGenerateContentConfig,
)
_globals["BaseGoogleGenAIGenerateContentConfig"] = _BaseGoogleGenAIGenerateContentConfig
return _globals["BaseGoogleGenAIGenerateContentConfig"]
# Lazy load BaseOCRConfig to avoid loading at module import time
if name == "BaseOCRConfig":
# Check if already cached
if "BaseOCRConfig" not in _globals:
from litellm.llms.base_llm.ocr.transformation import (
BaseOCRConfig as _BaseOCRConfig,
)
_globals["BaseOCRConfig"] = _BaseOCRConfig
return _globals["BaseOCRConfig"]
# Lazy load BaseSearchConfig to avoid loading at module import time
if name == "BaseSearchConfig":
# Check if already cached
if "BaseSearchConfig" not in _globals:
from litellm.llms.base_llm.search.transformation import (
BaseSearchConfig as _BaseSearchConfig,
)
_globals["BaseSearchConfig"] = _BaseSearchConfig
return _globals["BaseSearchConfig"]
# Lazy load BaseTextToSpeechConfig to avoid loading at module import time
if name == "BaseTextToSpeechConfig":
# Check if already cached
if "BaseTextToSpeechConfig" not in _globals:
from litellm.llms.base_llm.text_to_speech.transformation import (
BaseTextToSpeechConfig as _BaseTextToSpeechConfig,
)
_globals["BaseTextToSpeechConfig"] = _BaseTextToSpeechConfig
return _globals["BaseTextToSpeechConfig"]
# Lazy load BedrockModelInfo to avoid loading at module import time
if name == "BedrockModelInfo":
# Check if already cached
if "BedrockModelInfo" not in _globals:
from litellm.llms.bedrock.common_utils import (
BedrockModelInfo as _BedrockModelInfo,
)
_globals["BedrockModelInfo"] = _BedrockModelInfo
return _globals["BedrockModelInfo"]
# Lazy load CohereModelInfo to avoid loading at module import time
if name == "CohereModelInfo":
# Check if already cached
if "CohereModelInfo" not in _globals:
from litellm.llms.cohere.common_utils import (
CohereModelInfo as _CohereModelInfo,
)
_globals["CohereModelInfo"] = _CohereModelInfo
return _globals["CohereModelInfo"]
# Lazy load MistralOCRConfig to avoid loading at module import time
if name == "MistralOCRConfig":
# Check if already cached
if "MistralOCRConfig" not in _globals:
from litellm.llms.mistral.ocr.transformation import (
MistralOCRConfig as _MistralOCRConfig,
)
_globals["MistralOCRConfig"] = _MistralOCRConfig
return _globals["MistralOCRConfig"]
# Lazy load Rules to avoid loading at module import time
if name == "Rules":
# Check if already cached
if "Rules" not in _globals:
from litellm.litellm_core_utils.rules import Rules as _Rules
_globals["Rules"] = _Rules
return _globals["Rules"]
# Lazy load AsyncHTTPHandler and HTTPHandler to avoid loading at module import time
if name == "AsyncHTTPHandler":
# Check if already cached
if "AsyncHTTPHandler" not in _globals:
from litellm.llms.custom_httpx.http_handler import (
AsyncHTTPHandler as _AsyncHTTPHandler,
)
_globals["AsyncHTTPHandler"] = _AsyncHTTPHandler
return _globals["AsyncHTTPHandler"]
if name == "HTTPHandler":
# Check if already cached
if "HTTPHandler" not in _globals:
from litellm.llms.custom_httpx.http_handler import (
HTTPHandler as _HTTPHandler,
)
_globals["HTTPHandler"] = _HTTPHandler
return _globals["HTTPHandler"]
# Lazy load get_num_retries_from_retry_policy and reset_retry_policy to avoid loading at module import time
if name == "get_num_retries_from_retry_policy":
# Check if already cached
if "get_num_retries_from_retry_policy" not in _globals:
from litellm.router_utils.get_retry_from_policy import (
get_num_retries_from_retry_policy as _get_num_retries_from_retry_policy,
)
_globals["get_num_retries_from_retry_policy"] = _get_num_retries_from_retry_policy
return _globals["get_num_retries_from_retry_policy"]
if name == "reset_retry_policy":
# Check if already cached
if "reset_retry_policy" not in _globals:
from litellm.router_utils.get_retry_from_policy import (
reset_retry_policy as _reset_retry_policy,
)
_globals["reset_retry_policy"] = _reset_retry_policy
return _globals["reset_retry_policy"]
# Lazy load get_secret to avoid loading at module import time
if name == "get_secret":
# Check if already cached
if "get_secret" not in _globals:
from litellm.secret_managers.main import get_secret as _get_secret
_globals["get_secret"] = _get_secret
return _globals["get_secret"]
# Lazy load cached_imports functions to avoid loading at module import time
if name == "get_coroutine_checker":
# Check if already cached
if "get_coroutine_checker" not in _globals:
from litellm.litellm_core_utils.cached_imports import (
get_coroutine_checker as _get_coroutine_checker,
)
_globals["get_coroutine_checker"] = _get_coroutine_checker
return _globals["get_coroutine_checker"]
if name == "get_litellm_logging_class":
# Check if already cached
if "get_litellm_logging_class" not in _globals:
from litellm.litellm_core_utils.cached_imports import (
get_litellm_logging_class as _get_litellm_logging_class,
)
_globals["get_litellm_logging_class"] = _get_litellm_logging_class
return _globals["get_litellm_logging_class"]
if name == "get_set_callbacks":
# Check if already cached
if "get_set_callbacks" not in _globals:
from litellm.litellm_core_utils.cached_imports import (
get_set_callbacks as _get_set_callbacks,
)
_globals["get_set_callbacks"] = _get_set_callbacks
return _globals["get_set_callbacks"]
# Lazy load core_helpers functions to avoid loading at module import time
if name == "get_litellm_metadata_from_kwargs":
# Check if already cached
if "get_litellm_metadata_from_kwargs" not in _globals:
from litellm.litellm_core_utils.core_helpers import (
get_litellm_metadata_from_kwargs as _get_litellm_metadata_from_kwargs,
)
_globals["get_litellm_metadata_from_kwargs"] = _get_litellm_metadata_from_kwargs
return _globals["get_litellm_metadata_from_kwargs"]
if name == "map_finish_reason":
# Check if already cached
if "map_finish_reason" not in _globals:
from litellm.litellm_core_utils.core_helpers import (
map_finish_reason as _map_finish_reason,
)
_globals["map_finish_reason"] = _map_finish_reason
return _globals["map_finish_reason"]
if name == "process_response_headers":
# Check if already cached
if "process_response_headers" not in _globals:
from litellm.litellm_core_utils.core_helpers import (
process_response_headers as _process_response_headers,
)
_globals["process_response_headers"] = _process_response_headers
return _globals["process_response_headers"]
# Lazy load dot_notation_indexing functions to avoid loading at module import time
if name == "delete_nested_value":
# Check if already cached
if "delete_nested_value" not in _globals:
from litellm.litellm_core_utils.dot_notation_indexing import (
delete_nested_value as _delete_nested_value,
)
_globals["delete_nested_value"] = _delete_nested_value
return _globals["delete_nested_value"]
if name == "is_nested_path":
# Check if already cached
if "is_nested_path" not in _globals:
from litellm.litellm_core_utils.dot_notation_indexing import (
is_nested_path as _is_nested_path,
)
_globals["is_nested_path"] = _is_nested_path
return _globals["is_nested_path"]
# Lazy load get_litellm_params functions to avoid loading at module import time
if name == "_get_base_model_from_litellm_call_metadata":
# Check if already cached
if "_get_base_model_from_litellm_call_metadata" not in _globals:
from litellm.litellm_core_utils.get_litellm_params import (
_get_base_model_from_litellm_call_metadata as __get_base_model_from_litellm_call_metadata,
)
_globals["_get_base_model_from_litellm_call_metadata"] = __get_base_model_from_litellm_call_metadata
return _globals["_get_base_model_from_litellm_call_metadata"]
if name == "get_litellm_params":
# Check if already cached
if "get_litellm_params" not in _globals:
from litellm.litellm_core_utils.get_litellm_params import (
get_litellm_params as _get_litellm_params,
)
_globals["get_litellm_params"] = _get_litellm_params
return _globals["get_litellm_params"]
# Lazy load _ensure_extra_body_is_safe to avoid loading at module import time
if name == "_ensure_extra_body_is_safe":
# Check if already cached
if "_ensure_extra_body_is_safe" not in _globals:
from litellm.litellm_core_utils.llm_request_utils import (
_ensure_extra_body_is_safe as __ensure_extra_body_is_safe,
)
_globals["_ensure_extra_body_is_safe"] = __ensure_extra_body_is_safe
return _globals["_ensure_extra_body_is_safe"]
# Lazy load get_formatted_prompt to avoid loading at module import time
if name == "get_formatted_prompt":
# Check if already cached
if "get_formatted_prompt" not in _globals:
from litellm.litellm_core_utils.llm_response_utils.get_formatted_prompt import (
get_formatted_prompt as _get_formatted_prompt,
)
_globals["get_formatted_prompt"] = _get_formatted_prompt
return _globals["get_formatted_prompt"]
# Lazy load get_response_headers to avoid loading at module import time
if name == "get_response_headers":
# Check if already cached
if "get_response_headers" not in _globals:
from litellm.litellm_core_utils.llm_response_utils.get_headers import (
get_response_headers as _get_response_headers,
)
_globals["get_response_headers"] = _get_response_headers
return _globals["get_response_headers"]
# Lazy load update_response_metadata to avoid loading at module import time
if name == "update_response_metadata":
# Check if already cached
if "update_response_metadata" not in _globals:
from litellm.litellm_core_utils.llm_response_utils.response_metadata import (
update_response_metadata as _update_response_metadata,
)
_globals["update_response_metadata"] = _update_response_metadata
return _globals["update_response_metadata"]
# Lazy load executor to avoid loading at module import time
if name == "executor":
# Check if already cached
if "executor" not in _globals:
from litellm.litellm_core_utils.thread_pool_executor import (
executor as _executor,
)
_globals["executor"] = _executor
return _globals["executor"]
# Lazy load BaseAnthropicMessagesConfig to avoid loading at module import time
if name == "BaseAnthropicMessagesConfig":
# Check if already cached
if "BaseAnthropicMessagesConfig" not in _globals:
from litellm.llms.base_llm.anthropic_messages.transformation import (
BaseAnthropicMessagesConfig as _BaseAnthropicMessagesConfig,
)
_globals["BaseAnthropicMessagesConfig"] = _BaseAnthropicMessagesConfig
return _globals["BaseAnthropicMessagesConfig"]
# Lazy load BaseAudioTranscriptionConfig to avoid loading at module import time
if name == "BaseAudioTranscriptionConfig":
# Check if already cached
if "BaseAudioTranscriptionConfig" not in _globals:
from litellm.llms.base_llm.audio_transcription.transformation import (
BaseAudioTranscriptionConfig as _BaseAudioTranscriptionConfig,
)
_globals["BaseAudioTranscriptionConfig"] = _BaseAudioTranscriptionConfig
return _globals["BaseAudioTranscriptionConfig"]
# Lazy load BaseBatchesConfig to avoid loading at module import time
if name == "BaseBatchesConfig":
# Check if already cached
if "BaseBatchesConfig" not in _globals:
from litellm.llms.base_llm.batches.transformation import (
BaseBatchesConfig as _BaseBatchesConfig,
)
_globals["BaseBatchesConfig"] = _BaseBatchesConfig
return _globals["BaseBatchesConfig"]
# Lazy load BaseContainerConfig to avoid loading at module import time
if name == "BaseContainerConfig":
# Check if already cached
if "BaseContainerConfig" not in _globals:
from litellm.llms.base_llm.containers.transformation import (
BaseContainerConfig as _BaseContainerConfig,
)
_globals["BaseContainerConfig"] = _BaseContainerConfig
return _globals["BaseContainerConfig"]
# Lazy load BaseEmbeddingConfig to avoid loading at module import time
if name == "BaseEmbeddingConfig":
# Check if already cached
if "BaseEmbeddingConfig" not in _globals:
from litellm.llms.base_llm.embedding.transformation import (
BaseEmbeddingConfig as _BaseEmbeddingConfig,
)
_globals["BaseEmbeddingConfig"] = _BaseEmbeddingConfig
return _globals["BaseEmbeddingConfig"]
# Lazy load BaseImageEditConfig to avoid loading at module import time
if name == "BaseImageEditConfig":
# Check if already cached
if "BaseImageEditConfig" not in _globals:
from litellm.llms.base_llm.image_edit.transformation import (
BaseImageEditConfig as _BaseImageEditConfig,
)
_globals["BaseImageEditConfig"] = _BaseImageEditConfig
return _globals["BaseImageEditConfig"]
# Lazy load BaseImageGenerationConfig to avoid loading at module import time
if name == "BaseImageGenerationConfig":
# Check if already cached
if "BaseImageGenerationConfig" not in _globals:
from litellm.llms.base_llm.image_generation.transformation import (
BaseImageGenerationConfig as _BaseImageGenerationConfig,
)
_globals["BaseImageGenerationConfig"] = _BaseImageGenerationConfig
return _globals["BaseImageGenerationConfig"]
# Lazy load BaseImageVariationConfig to avoid loading at module import time
if name == "BaseImageVariationConfig":
# Check if already cached
if "BaseImageVariationConfig" not in _globals:
from litellm.llms.base_llm.image_variations.transformation import (
BaseImageVariationConfig as _BaseImageVariationConfig,
)
_globals["BaseImageVariationConfig"] = _BaseImageVariationConfig
return _globals["BaseImageVariationConfig"]
# Lazy load BasePassthroughConfig to avoid loading at module import time
if name == "BasePassthroughConfig":
# Check if already cached
if "BasePassthroughConfig" not in _globals:
from litellm.llms.base_llm.passthrough.transformation import (
BasePassthroughConfig as _BasePassthroughConfig,
)
_globals["BasePassthroughConfig"] = _BasePassthroughConfig
return _globals["BasePassthroughConfig"]
# Lazy load BaseRealtimeConfig to avoid loading at module import time
if name == "BaseRealtimeConfig":
# Check if already cached
if "BaseRealtimeConfig" not in _globals:
from litellm.llms.base_llm.realtime.transformation import (
BaseRealtimeConfig as _BaseRealtimeConfig,
)
_globals["BaseRealtimeConfig"] = _BaseRealtimeConfig
return _globals["BaseRealtimeConfig"]
# Lazy load BaseRerankConfig to avoid loading at module import time
if name == "BaseRerankConfig":
# Check if already cached
if "BaseRerankConfig" not in _globals:
from litellm.llms.base_llm.rerank.transformation import (
BaseRerankConfig as _BaseRerankConfig,
)
_globals["BaseRerankConfig"] = _BaseRerankConfig
return _globals["BaseRerankConfig"]
# Lazy load BaseVectorStoreConfig to avoid loading at module import time
if name == "BaseVectorStoreConfig":
# Check if already cached
if "BaseVectorStoreConfig" not in _globals:
from litellm.llms.base_llm.vector_store.transformation import (
BaseVectorStoreConfig as _BaseVectorStoreConfig,
)
_globals["BaseVectorStoreConfig"] = _BaseVectorStoreConfig
return _globals["BaseVectorStoreConfig"]
# Lazy load BaseVectorStoreFilesConfig to avoid loading at module import time
if name == "BaseVectorStoreFilesConfig":
# Check if already cached
if "BaseVectorStoreFilesConfig" not in _globals:
from litellm.llms.base_llm.vector_store_files.transformation import (
BaseVectorStoreFilesConfig as _BaseVectorStoreFilesConfig,
)
_globals["BaseVectorStoreFilesConfig"] = _BaseVectorStoreFilesConfig
return _globals["BaseVectorStoreFilesConfig"]
# Lazy load BaseVideoConfig to avoid loading at module import time
if name == "BaseVideoConfig":
# Check if already cached
if "BaseVideoConfig" not in _globals:
from litellm.llms.base_llm.videos.transformation import (
BaseVideoConfig as _BaseVideoConfig,
)
_globals["BaseVideoConfig"] = _BaseVideoConfig
return _globals["BaseVideoConfig"]
# Lazy load ANTHROPIC_API_ONLY_HEADERS to avoid loading at module import time
if name == "ANTHROPIC_API_ONLY_HEADERS":
# Check if already cached
if "ANTHROPIC_API_ONLY_HEADERS" not in _globals:
from litellm.types.llms.anthropic import (
ANTHROPIC_API_ONLY_HEADERS as _ANTHROPIC_API_ONLY_HEADERS,
)
_globals["ANTHROPIC_API_ONLY_HEADERS"] = _ANTHROPIC_API_ONLY_HEADERS
return _globals["ANTHROPIC_API_ONLY_HEADERS"]
# Lazy load AnthropicThinkingParam to avoid loading at module import time
if name == "AnthropicThinkingParam":
# Check if already cached
if "AnthropicThinkingParam" not in _globals:
from litellm.types.llms.anthropic import (
AnthropicThinkingParam as _AnthropicThinkingParam,
)
_globals["AnthropicThinkingParam"] = _AnthropicThinkingParam
return _globals["AnthropicThinkingParam"]
# Lazy load RerankResponse to avoid loading at module import time
if name == "RerankResponse":
# Check if already cached
if "RerankResponse" not in _globals:
from litellm.types.rerank import RerankResponse as _RerankResponse
_globals["RerankResponse"] = _RerankResponse
return _globals["RerankResponse"]
# Lazy load ChatCompletionDeltaToolCallChunk to avoid loading at module import time
if name == "ChatCompletionDeltaToolCallChunk":
# Check if already cached
if "ChatCompletionDeltaToolCallChunk" not in _globals:
from litellm.types.llms.openai import (
ChatCompletionDeltaToolCallChunk as _ChatCompletionDeltaToolCallChunk,
)
_globals["ChatCompletionDeltaToolCallChunk"] = _ChatCompletionDeltaToolCallChunk
return _globals["ChatCompletionDeltaToolCallChunk"]
# Lazy load ChatCompletionToolCallChunk to avoid loading at module import time
if name == "ChatCompletionToolCallChunk":
# Check if already cached
if "ChatCompletionToolCallChunk" not in _globals:
from litellm.types.llms.openai import (
ChatCompletionToolCallChunk as _ChatCompletionToolCallChunk,
)
_globals["ChatCompletionToolCallChunk"] = _ChatCompletionToolCallChunk
return _globals["ChatCompletionToolCallChunk"]
# Lazy load ChatCompletionToolCallFunctionChunk to avoid loading at module import time
if name == "ChatCompletionToolCallFunctionChunk":
# Check if already cached
if "ChatCompletionToolCallFunctionChunk" not in _globals:
from litellm.types.llms.openai import (
ChatCompletionToolCallFunctionChunk as _ChatCompletionToolCallFunctionChunk,
)
_globals["ChatCompletionToolCallFunctionChunk"] = _ChatCompletionToolCallFunctionChunk
return _globals["ChatCompletionToolCallFunctionChunk"]
# Lazy load LiteLLM_Params to avoid loading at module import time
if name == "LiteLLM_Params":
# Check if already cached
if "LiteLLM_Params" not in _globals:
from litellm.types.router import LiteLLM_Params as _LiteLLM_Params
_globals["LiteLLM_Params"] = _LiteLLM_Params
return _globals["LiteLLM_Params"]
# Check if name is in registry and call the cached handler function
if name in registry:
handler_func = registry[name]
return handler_func(name)
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

View file

@ -35,6 +35,8 @@ from litellm._lazy_imports import (
_lazy_import_types,
LLM_PROVIDER_LOGIC_NAMES,
_lazy_import_llm_provider_logic,
UTILS_MODULE_NAMES,
_lazy_import_utils_module,
)
@ -45,6 +47,13 @@ def _clear_names_from_globals(names: tuple):
del litellm.__dict__[name]
def _clear_names_from_utils_globals(names: tuple):
"""Clear all names from litellm.utils globals."""
for name in names:
if name in litellm.utils.__dict__:
del litellm.utils.__dict__[name]
def _verify_only_requested_name_imported(name: str, all_names: tuple):
"""Verify that only the requested name is in globals, not the others."""
for other_name in all_names:
@ -52,6 +61,13 @@ def _verify_only_requested_name_imported(name: str, all_names: tuple):
assert other_name not in litellm.__dict__, 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."""
for other_name in all_names:
if other_name != name:
assert other_name not in litellm.utils.__dict__, 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."""
# Test each name individually - only that name should be imported
@ -223,6 +239,9 @@ def test_unknown_attribute_raises_error():
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."""
@ -264,3 +283,15 @@ def test_llm_provider_logic_lazy_imports():
_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."""
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 litellm.utils.__dict__
_verify_only_requested_name_imported_in_utils(name, UTILS_MODULE_NAMES)