diff --git a/litellm/__init__.py b/litellm/__init__.py index 08440e3092..0bb9ac2723 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -1055,7 +1055,6 @@ from .utils import client from .llms.bytez.chat.transformation import BytezChatConfig from .llms.custom_llm import CustomLLM -from .llms.bedrock.chat.converse_transformation import AmazonConverseConfig from .llms.openai_like.chat.handler import OpenAILikeChatConfig from .llms.aiohttp_openai.chat.transformation import AiohttpOpenAIChatConfig from .llms.galadriel.chat.transformation import GaladrielChatConfig @@ -1551,6 +1550,9 @@ if TYPE_CHECKING: module_level_aclient: AsyncHTTPHandler module_level_client: HTTPHandler + # LLM config classes - lazy loaded only + AmazonConverseConfig: Type[Any] + def __getattr__(name: str) -> Any: """Lazy import handler""" @@ -1565,6 +1567,7 @@ def __getattr__(name: str) -> Any: CACHING_NAMES, HTTP_HANDLER_NAMES, DOTPROMPT_NAMES, + LLM_CONFIG_NAMES, ) # Lazy load cost_calculator functions @@ -1619,6 +1622,12 @@ def __getattr__(name: str) -> Any: return _lazy_import_dotprompt(name) + # Lazy load LLM config classes + if name in LLM_CONFIG_NAMES: + from ._lazy_imports import _lazy_import_llm_configs + + return _lazy_import_llm_configs(name) + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/litellm/_lazy_imports.py b/litellm/_lazy_imports.py index cef723ae26..ba62355cc8 100644 --- a/litellm/_lazy_imports.py +++ b/litellm/_lazy_imports.py @@ -154,6 +154,11 @@ DOTPROMPT_NAMES = ( "set_global_prompt_directory", ) +# LLM config classes that support lazy loading via _lazy_import_llm_configs +LLM_CONFIG_NAMES = ( + "AmazonConverseConfig", +) + # Lazy import for utils module - imports only the requested item by name. # Note: PLR0915 (too many statements) is suppressed because the many if statements # are intentional - each attribute is imported individually only when requested, @@ -611,4 +616,19 @@ def _lazy_import_dotprompt(name: str) -> Any: _globals["set_global_prompt_directory"] = _set_global_prompt_directory return _set_global_prompt_directory - raise AttributeError(f"Dotprompt lazy import: unknown attribute {name!r}") \ No newline at end of file + raise AttributeError(f"Dotprompt lazy import: unknown attribute {name!r}") + + +def _lazy_import_llm_configs(name: str) -> Any: + """Lazy import for LLM config classes.""" + _globals = _get_litellm_globals() + + if name == "AmazonConverseConfig": + from .llms.bedrock.chat.converse_transformation import ( + AmazonConverseConfig as _AmazonConverseConfig, + ) + + _globals["AmazonConverseConfig"] = _AmazonConverseConfig + return _AmazonConverseConfig + + raise AttributeError(f"LLM config lazy import: unknown attribute {name!r}") \ No newline at end of file diff --git a/litellm/utils.py b/litellm/utils.py index 4b648b9eb5..dfc0df5c9a 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -8393,3 +8393,17 @@ def should_run_mock_completion( if mock_response or mock_tool_calls or mock_timeout: return True return False + + +# Re-export encoding from main.py for backward compatibility +# This allows tests to import: from litellm.utils import encoding +# We use a lazy import to avoid loading main.py at utils.py import time +def __getattr__(name: str) -> Any: + """Lazy import handler for utils module""" + if name == "encoding": + from litellm.main import encoding as _encoding + # Cache it in the module's __dict__ for subsequent accesses + import sys + sys.modules[__name__].__dict__["encoding"] = _encoding + return _encoding + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/tests/test_litellm/test_lazy_imports.py b/tests/test_litellm/test_lazy_imports.py index 619d9a1d1b..0b38956441 100644 --- a/tests/test_litellm/test_lazy_imports.py +++ b/tests/test_litellm/test_lazy_imports.py @@ -29,6 +29,8 @@ from litellm._lazy_imports import ( _lazy_import_http_handlers, DOTPROMPT_NAMES, _lazy_import_dotprompt, + LLM_CONFIG_NAMES, + _lazy_import_llm_configs, ) @@ -208,3 +210,20 @@ def test_unknown_attribute_raises_error(): with pytest.raises(AttributeError): _lazy_import_types_utils("unknown") + with pytest.raises(AttributeError): + _lazy_import_llm_configs("unknown") + + +def test_llm_config_lazy_imports(): + """Test that LLM config classes can be lazy imported.""" + 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.__dict__ + # 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) +