mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-11 08:22:40 +00:00
feat: lazy load heavy imports to reduce memory usage at import time (#18592)
- Lazy load remove_index_from_tool_calls via __getattr__ - Lazy load _service_logger module via __getattr__ in __init__.py - Lazy load audio_utils.utils with module-level caching in utils.py - Remove direct imports that trigger heavy module loading These changes reduce import-time memory usage by deferring imports until they are actually needed, while maintaining performance through caching for subsequent accesses.
This commit is contained in:
+13
-1
@@ -1058,7 +1058,7 @@ openai_video_generation_models = ["sora-2"]
|
||||
|
||||
# timeout is lazy-loaded via __getattr__
|
||||
# get_llm_provider is lazy-loaded via __getattr__
|
||||
from litellm.litellm_core_utils.core_helpers import remove_index_from_tool_calls
|
||||
# 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)
|
||||
@@ -1507,6 +1507,7 @@ if TYPE_CHECKING:
|
||||
get_first_chars_messages: Callable[..., str]
|
||||
get_provider_fields: Callable[..., List]
|
||||
get_valid_models: Callable[..., list]
|
||||
remove_index_from_tool_calls: Callable[..., None]
|
||||
|
||||
# Response types - truly lazy loaded only (not in main.py or elsewhere)
|
||||
ModelResponseListIterator: Type[Any]
|
||||
@@ -1658,6 +1659,17 @@ def __getattr__(name: str) -> Any:
|
||||
LoggingCallbackManager = __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"]
|
||||
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
|
||||
|
||||
@@ -290,6 +290,7 @@ TYPES_NAMES = (
|
||||
# LLM provider logic names that support lazy loading via _lazy_import_llm_provider_logic
|
||||
LLM_PROVIDER_LOGIC_NAMES = (
|
||||
"get_llm_provider",
|
||||
"remove_index_from_tool_calls",
|
||||
)
|
||||
|
||||
# Import maps for registry pattern - reduces repetition
|
||||
@@ -393,6 +394,7 @@ _TYPES_IMPORT_MAP = {
|
||||
|
||||
_LLM_PROVIDER_LOGIC_IMPORT_MAP = {
|
||||
"get_llm_provider": ("litellm.litellm_core_utils.get_llm_provider_logic", "get_llm_provider"),
|
||||
"remove_index_from_tool_calls": ("litellm.litellm_core_utils.core_helpers", "remove_index_from_tool_calls"),
|
||||
}
|
||||
|
||||
_LLM_CONFIGS_IMPORT_MAP = {
|
||||
|
||||
+23
-3
@@ -48,9 +48,9 @@ from tiktoken import Encoding
|
||||
from tokenizers import Tokenizer
|
||||
|
||||
import litellm
|
||||
import litellm._service_logger # for storing API inputs, outputs, and metadata
|
||||
|
||||
import litellm.litellm_core_utils
|
||||
import litellm.litellm_core_utils.audio_utils.utils
|
||||
# audio_utils.utils is lazy-loaded - only imported when needed for transcription calls
|
||||
import litellm.litellm_core_utils.json_validation_rule
|
||||
import litellm.llms
|
||||
import litellm.llms.gemini
|
||||
@@ -157,6 +157,24 @@ from litellm.router_utils.get_retry_from_policy import (
|
||||
reset_retry_policy,
|
||||
)
|
||||
from litellm.secret_managers.main import get_secret
|
||||
|
||||
# Cached lazy import for audio_utils.utils
|
||||
# Module-level cache to avoid repeated imports while preserving memory benefits
|
||||
_audio_utils_module = None
|
||||
|
||||
|
||||
def _get_cached_audio_utils():
|
||||
"""
|
||||
Get cached audio_utils.utils module.
|
||||
Lazy imports on first call to avoid loading audio_utils.utils at import time.
|
||||
Subsequent calls use cached module for better performance.
|
||||
"""
|
||||
global _audio_utils_module
|
||||
if _audio_utils_module is None:
|
||||
import litellm.litellm_core_utils.audio_utils.utils
|
||||
_audio_utils_module = litellm.litellm_core_utils.audio_utils.utils
|
||||
return _audio_utils_module
|
||||
|
||||
from litellm.types.llms.anthropic import (
|
||||
ANTHROPIC_API_ONLY_HEADERS,
|
||||
AnthropicThinkingParam,
|
||||
@@ -965,7 +983,9 @@ def function_setup( # noqa: PLR0915
|
||||
or call_type == CallTypes.transcription.value
|
||||
):
|
||||
_file_obj: FileTypes = args[1] if len(args) > 1 else kwargs["file"]
|
||||
file_checksum = litellm.litellm_core_utils.audio_utils.utils.get_audio_file_content_hash(
|
||||
# Lazy import audio_utils.utils only when needed for transcription calls
|
||||
audio_utils = _get_cached_audio_utils()
|
||||
file_checksum = audio_utils.get_audio_file_content_hash(
|
||||
file_obj=_file_obj
|
||||
)
|
||||
if "metadata" in kwargs:
|
||||
|
||||
Reference in New Issue
Block a user