diff --git a/lib/crewai/src/crewai/__init__.py b/lib/crewai/src/crewai/__init__.py index 0c5cc71e2..8ce4712a6 100644 --- a/lib/crewai/src/crewai/__init__.py +++ b/lib/crewai/src/crewai/__init__.py @@ -10,7 +10,6 @@ from crewai.flow.flow import Flow from crewai.knowledge.knowledge import Knowledge from crewai.llm import LLM from crewai.llms.base_llm import BaseLLM -from crewai.memory.unified_memory import Memory from crewai.process import Process from crewai.task import Task from crewai.tasks.llm_guardrail import LLMGuardrail @@ -72,6 +71,25 @@ def _track_install_async() -> None: _track_install_async() + +_LAZY_IMPORTS: dict[str, tuple[str, str]] = { + "Memory": ("crewai.memory.unified_memory", "Memory"), +} + + +def __getattr__(name: str) -> Any: + """Lazily import heavy modules (e.g. Memory → lancedb) on first access.""" + if name in _LAZY_IMPORTS: + module_path, attr = _LAZY_IMPORTS[name] + import importlib + + mod = importlib.import_module(module_path) + val = getattr(mod, attr) + globals()[name] = val + return val + raise AttributeError(f"module 'crewai' has no attribute {name!r}") + + __all__ = [ "LLM", "Agent", diff --git a/lib/crewai/src/crewai/memory/__init__.py b/lib/crewai/src/crewai/memory/__init__.py index 084a57a87..3bd3ef5ee 100644 --- a/lib/crewai/src/crewai/memory/__init__.py +++ b/lib/crewai/src/crewai/memory/__init__.py @@ -1,6 +1,14 @@ -"""Memory module: unified Memory with LLM analysis and pluggable storage.""" +"""Memory module: unified Memory with LLM analysis and pluggable storage. + +Heavy dependencies are lazily imported so that +``import crewai`` does not initialise at runtime — critical for +Celery pre-fork and similar deployment patterns. +""" + +from __future__ import annotations + +from typing import Any -from crewai.memory.encoding_flow import EncodingFlow from crewai.memory.memory_scope import MemoryScope, MemorySlice from crewai.memory.types import ( MemoryMatch, @@ -10,7 +18,24 @@ from crewai.memory.types import ( embed_text, embed_texts, ) -from crewai.memory.unified_memory import Memory + +_LAZY_IMPORTS: dict[str, tuple[str, str]] = { + "Memory": ("crewai.memory.unified_memory", "Memory"), + "EncodingFlow": ("crewai.memory.encoding_flow", "EncodingFlow"), +} + + +def __getattr__(name: str) -> Any: + """Lazily import Memory / EncodingFlow to avoid pulling in lancedb at import time.""" + if name in _LAZY_IMPORTS: + import importlib + + module_path, attr = _LAZY_IMPORTS[name] + mod = importlib.import_module(module_path) + val = getattr(mod, attr) + globals()[name] = val + return val + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") __all__ = [ diff --git a/lib/crewai/src/crewai/memory/unified_memory.py b/lib/crewai/src/crewai/memory/unified_memory.py index 9d921fa1f..cae9013bd 100644 --- a/lib/crewai/src/crewai/memory/unified_memory.py +++ b/lib/crewai/src/crewai/memory/unified_memory.py @@ -21,7 +21,6 @@ from crewai.llms.base_llm import BaseLLM from crewai.memory.analyze import extract_memories_from_content from crewai.memory.recall_flow import RecallFlow from crewai.memory.storage.backend import StorageBackend -from crewai.memory.storage.lancedb_storage import LanceDBStorage from crewai.memory.types import ( MemoryConfig, MemoryMatch, @@ -148,12 +147,10 @@ class Memory: else None ) - # Storage is initialized eagerly (local, no API key needed). - self._storage: StorageBackend - if storage == "lancedb": - self._storage = LanceDBStorage() - elif isinstance(storage, str): - self._storage = LanceDBStorage(path=storage) + if isinstance(storage, str): + from crewai.memory.storage.lancedb_storage import LanceDBStorage + + self._storage = LanceDBStorage() if storage == "lancedb" else LanceDBStorage(path=storage) else: self._storage = storage