mdb-engine 0.7.2__tar.gz → 0.7.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mdb_engine-0.7.2/mdb_engine.egg-info → mdb_engine-0.7.4}/PKG-INFO +1 -15
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/README.md +0 -14
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/__init__.py +1 -9
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/cli/main.py +1 -1
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/engine.py +3 -2
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/service_initialization.py +5 -4
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/types.py +2 -2
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/dependencies.py +3 -3
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/memory/README.md +145 -21
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/memory/__init__.py +9 -0
- mdb_engine-0.7.4/mdb_engine/memory/base.py +194 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/memory/service.py +323 -187
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/routing/websockets.py +45 -6
- {mdb_engine-0.7.2 → mdb_engine-0.7.4/mdb_engine.egg-info}/PKG-INFO +1 -15
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine.egg-info/SOURCES.txt +1 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/pyproject.toml +1 -1
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/setup.py +1 -1
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/LICENSE +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/MANIFEST.in +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/README.md +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/ARCHITECTURE.md +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/README.md +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/__init__.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/audit.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/base.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/casbin_factory.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/casbin_models.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/config_defaults.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/config_helpers.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/cookie_utils.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/csrf.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/decorators.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/dependencies.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/helpers.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/integration.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/jwt.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/middleware.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/oso_factory.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/provider.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/rate_limiter.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/restrictions.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/session_manager.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/shared_middleware.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/shared_users.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/token_lifecycle.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/token_store.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/users.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/utils.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/websocket_sessions.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/auth/websocket_tickets.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/cli/__init__.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/cli/commands/__init__.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/cli/commands/generate.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/cli/commands/migrate.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/cli/commands/show.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/cli/commands/validate.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/cli/utils.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/config.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/constants.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/README.md +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/__init__.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/app_registration.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/app_secrets.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/connection.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/encryption.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/index_management.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/manifest.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/ray_integration.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/core/seeding.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/database/README.md +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/database/__init__.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/database/abstraction.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/database/connection.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/database/query_validator.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/database/resource_limiter.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/database/scoped_wrapper.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/di/__init__.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/di/container.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/di/providers.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/di/scopes.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/embeddings/README.md +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/embeddings/__init__.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/embeddings/dependencies.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/embeddings/service.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/exceptions.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/indexes/README.md +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/indexes/__init__.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/indexes/helpers.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/indexes/manager.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/observability/README.md +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/observability/__init__.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/observability/health.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/observability/logging.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/observability/metrics.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/repositories/__init__.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/repositories/base.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/repositories/mongo.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/repositories/unit_of_work.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/routing/README.md +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/routing/__init__.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/utils/__init__.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine/utils/mongo.py +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine.egg-info/dependency_links.txt +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine.egg-info/entry_points.txt +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine.egg-info/requires.txt +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/mdb_engine.egg-info/top_level.txt +0 -0
- {mdb_engine-0.7.2 → mdb_engine-0.7.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mdb-engine
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: MongoDB Engine
|
|
5
5
|
Home-page: https://github.com/ranfysvalle02/mdb-engine
|
|
6
6
|
Author: Fabian Valle
|
|
@@ -72,20 +72,6 @@ Dynamic: requires-python
|
|
|
72
72
|
[](https://www.python.org/downloads/)
|
|
73
73
|
[](https://opensource.org/licenses/AGPL-3.0)
|
|
74
74
|
|
|
75
|
-
## 🎉 What's New in v0.7.0
|
|
76
|
-
|
|
77
|
-
**FastAPI Native WebSocket Support**: MDB-Engine now uses FastAPI's `APIRouter` approach for WebSocket registration in both single-app and multi-app modes. This provides:
|
|
78
|
-
|
|
79
|
-
- ✅ **Full FastAPI Feature Support**: Dependency injection, OpenAPI documentation, request/response models
|
|
80
|
-
- ✅ **Consistency**: Same registration pattern across single-app and multi-app modes
|
|
81
|
-
- ✅ **Best Practices**: Follows FastAPI's recommended WebSocket registration patterns
|
|
82
|
-
- ✅ **Better Maintainability**: Uses FastAPI abstractions instead of low-level Starlette APIs
|
|
83
|
-
- ✅ **Route Priority**: WebSocket routes registered before mounted apps ensure proper routing
|
|
84
|
-
|
|
85
|
-
**Value**: This change ensures WebSocket endpoints benefit from all FastAPI features, making your code more maintainable and consistent with FastAPI best practices.
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
75
|
## 🎯 manifest.json: The Key to Everything
|
|
90
76
|
|
|
91
77
|
**`manifest.json` is the foundation of your application.** It's a single configuration file that defines your app's identity, data structure, authentication, indexes, and services. Everything flows from this file.
|
|
@@ -6,20 +6,6 @@
|
|
|
6
6
|
[](https://www.python.org/downloads/)
|
|
7
7
|
[](https://opensource.org/licenses/AGPL-3.0)
|
|
8
8
|
|
|
9
|
-
## 🎉 What's New in v0.7.0
|
|
10
|
-
|
|
11
|
-
**FastAPI Native WebSocket Support**: MDB-Engine now uses FastAPI's `APIRouter` approach for WebSocket registration in both single-app and multi-app modes. This provides:
|
|
12
|
-
|
|
13
|
-
- ✅ **Full FastAPI Feature Support**: Dependency injection, OpenAPI documentation, request/response models
|
|
14
|
-
- ✅ **Consistency**: Same registration pattern across single-app and multi-app modes
|
|
15
|
-
- ✅ **Best Practices**: Follows FastAPI's recommended WebSocket registration patterns
|
|
16
|
-
- ✅ **Better Maintainability**: Uses FastAPI abstractions instead of low-level Starlette APIs
|
|
17
|
-
- ✅ **Route Priority**: WebSocket routes registered before mounted apps ensure proper routing
|
|
18
|
-
|
|
19
|
-
**Value**: This change ensures WebSocket endpoints benefit from all FastAPI features, making your code more maintainable and consistent with FastAPI best practices.
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
9
|
## 🎯 manifest.json: The Key to Everything
|
|
24
10
|
|
|
25
11
|
**`manifest.json` is the foundation of your application.** It's a single configuration file that defines your app's identity, data structure, authentication, indexes, and services. Everything flows from this file.
|
|
@@ -81,15 +81,7 @@ from .repositories import Entity, MongoRepository, Repository, UnitOfWork
|
|
|
81
81
|
# Utilities
|
|
82
82
|
from .utils import clean_mongo_doc, clean_mongo_docs
|
|
83
83
|
|
|
84
|
-
__version__ =
|
|
85
|
-
"0.7.2" # Memory service update functionality
|
|
86
|
-
# - ADDED: Memory service update() method for in-place memory updates
|
|
87
|
-
# - ADDED: Support for updating memory content and metadata while preserving IDs
|
|
88
|
-
# - ADDED: Automatic embedding recomputation via Mem0's update method
|
|
89
|
-
# - ADDED: Comprehensive unit tests for memory update functionality (17 tests)
|
|
90
|
-
# - ENHANCED: Memory service now uses Mem0's native update method exclusively
|
|
91
|
-
# - REMOVED: Direct MongoDB update fallback (simplified implementation)
|
|
92
|
-
)
|
|
84
|
+
__version__ = "0.7.4"
|
|
93
85
|
|
|
94
86
|
__all__ = [
|
|
95
87
|
# Core Engine
|
|
@@ -910,13 +910,14 @@ class MongoDBEngine:
|
|
|
910
910
|
|
|
911
911
|
def get_memory_service(self, slug: str) -> Any | None:
|
|
912
912
|
"""
|
|
913
|
-
Get
|
|
913
|
+
Get memory service for an app (returns BaseMemoryService instance).
|
|
914
914
|
|
|
915
915
|
Args:
|
|
916
916
|
slug: App slug
|
|
917
917
|
|
|
918
918
|
Returns:
|
|
919
|
-
|
|
919
|
+
BaseMemoryService instance (currently Mem0MemoryService) if memory is enabled
|
|
920
|
+
for this app, None otherwise
|
|
920
921
|
|
|
921
922
|
Example:
|
|
922
923
|
```python
|
|
@@ -63,10 +63,10 @@ class ServiceInitializer:
|
|
|
63
63
|
self, slug: str, memory_config: dict[str, Any] | None
|
|
64
64
|
) -> None:
|
|
65
65
|
"""
|
|
66
|
-
Initialize
|
|
66
|
+
Initialize memory service for an app (defaults to Mem0 implementation).
|
|
67
67
|
|
|
68
68
|
Memory support is OPTIONAL - only processes if dependencies are available.
|
|
69
|
-
|
|
69
|
+
Currently uses Mem0.ai which handles embeddings and LLM via environment variables (.env).
|
|
70
70
|
|
|
71
71
|
Args:
|
|
72
72
|
slug: App slug
|
|
@@ -356,13 +356,14 @@ class ServiceInitializer:
|
|
|
356
356
|
|
|
357
357
|
def get_memory_service(self, slug: str) -> Any | None:
|
|
358
358
|
"""
|
|
359
|
-
Get
|
|
359
|
+
Get memory service for an app (returns BaseMemoryService instance).
|
|
360
360
|
|
|
361
361
|
Args:
|
|
362
362
|
slug: App slug
|
|
363
363
|
|
|
364
364
|
Returns:
|
|
365
|
-
|
|
365
|
+
BaseMemoryService instance (currently Mem0MemoryService) if memory is enabled
|
|
366
|
+
for this app, None otherwise
|
|
366
367
|
"""
|
|
367
368
|
try:
|
|
368
369
|
service = self._memory_services.get(slug)
|
|
@@ -11,9 +11,9 @@ This module is part of MDB_ENGINE - MongoDB Engine.
|
|
|
11
11
|
from typing import TYPE_CHECKING, Any, Literal, TypedDict
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
|
-
from ..memory import
|
|
14
|
+
from ..memory import BaseMemoryService
|
|
15
15
|
else:
|
|
16
|
-
|
|
16
|
+
BaseMemoryService = Any
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
# ============================================================================
|
|
@@ -33,7 +33,7 @@ if TYPE_CHECKING:
|
|
|
33
33
|
from .core.engine import MongoDBEngine
|
|
34
34
|
from .database.scoped_wrapper import ScopedMongoWrapper
|
|
35
35
|
from .embeddings.service import EmbeddingService
|
|
36
|
-
from .memory
|
|
36
|
+
from .memory import BaseMemoryService
|
|
37
37
|
|
|
38
38
|
logger = logging.getLogger(__name__)
|
|
39
39
|
|
|
@@ -121,8 +121,8 @@ async def get_embedding_service(request: Request) -> "EmbeddingService":
|
|
|
121
121
|
raise HTTPException(503, f"Failed to initialize embedding service: {e}") from e
|
|
122
122
|
|
|
123
123
|
|
|
124
|
-
async def get_memory_service(request: Request) -> Optional["
|
|
125
|
-
"""Get the
|
|
124
|
+
async def get_memory_service(request: Request) -> Optional["BaseMemoryService"]:
|
|
125
|
+
"""Get the memory service if configured (defaults to Mem0 implementation)."""
|
|
126
126
|
engine = getattr(request.app.state, "engine", None)
|
|
127
127
|
slug = getattr(request.app.state, "app_slug", None)
|
|
128
128
|
if not engine or not slug:
|
|
@@ -2,9 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
Mem0.ai integration for intelligent memory management in MDB_ENGINE applications. Provides semantic memory storage, retrieval, and inference capabilities with MongoDB integration.
|
|
4
4
|
|
|
5
|
+
## 🎉 What's New
|
|
6
|
+
|
|
7
|
+
### Extensible Architecture (Latest)
|
|
8
|
+
|
|
9
|
+
**Base Class Pattern for Future Extensibility!**
|
|
10
|
+
|
|
11
|
+
The memory service now uses an abstract base class pattern, enabling future memory provider implementations while maintaining backward compatibility:
|
|
12
|
+
|
|
13
|
+
- **🏗️ BaseMemoryService**: Abstract base class defining the memory service interface
|
|
14
|
+
- **🔌 Provider Extensibility**: Easy to add new memory providers (LangChain, custom implementations, etc.)
|
|
15
|
+
- **✅ Backward Compatible**: All existing code continues to work without changes
|
|
16
|
+
- **📝 Type Safety**: Better IDE support and type checking with abstract base class
|
|
17
|
+
- **🎯 Consistent API**: All memory providers implement the same interface
|
|
18
|
+
|
|
19
|
+
### v0.7.4 Enhancements
|
|
20
|
+
|
|
21
|
+
**Enhanced Mem0 Integration - Production Ready!**
|
|
22
|
+
|
|
23
|
+
- **🔧 Hybrid Update Pattern**: Content updates via Mem0 (triggers re-embedding), metadata updates via direct MongoDB (full control, no API limitations)
|
|
24
|
+
- **📊 Direct MongoDB Access**: Reliable data retrieval directly from MongoDB, bypassing Mem0 API inconsistencies
|
|
25
|
+
- **🏷️ Full Metadata Support**: Update any metadata field without restrictions - not limited by Mem0's API
|
|
26
|
+
- **✅ Correct Mem0 Structure**: Properly handles Mem0's MongoDB structure (`_id` as document ID, `payload` for memory data)
|
|
27
|
+
- **🛡️ Robust Error Handling**: Specific exception handling with proper KeyboardInterrupt/SystemExit propagation
|
|
28
|
+
- **🔍 Reliable Returns**: Always returns normalized documents fetched directly from MongoDB (guaranteed structure)
|
|
29
|
+
|
|
30
|
+
> 📖 **Want to understand why we use manual MongoDB access?** See the [Mem0 Implementation Guide](../../docs/guides/MEM0_IMPLEMENTATION.md) for detailed explanations of our architectural decisions, Mem0's MongoDB structure, and things to watch out for.
|
|
31
|
+
|
|
5
32
|
## Features
|
|
6
33
|
|
|
7
|
-
- **
|
|
34
|
+
- **Extensible Architecture**: Base class pattern allows for multiple memory provider implementations
|
|
35
|
+
- **Mem0 Integration**: Default implementation using Mem0.ai for intelligent memory management
|
|
8
36
|
- **MongoDB Storage**: Built-in MongoDB vector store integration
|
|
9
37
|
- **Auto-Detection**: Automatically detects OpenAI or Azure OpenAI from environment variables
|
|
10
38
|
- **Semantic Search**: Vector-based semantic memory search
|
|
@@ -67,7 +95,7 @@ Enable memory service in your `manifest.json`:
|
|
|
67
95
|
### Basic Usage
|
|
68
96
|
|
|
69
97
|
```python
|
|
70
|
-
from mdb_engine.memory import
|
|
98
|
+
from mdb_engine.memory import BaseMemoryService # Base class for type hints
|
|
71
99
|
from mdb_engine.core import MongoDBEngine
|
|
72
100
|
|
|
73
101
|
# Initialize engine
|
|
@@ -75,7 +103,8 @@ engine = MongoDBEngine(mongo_uri="...", db_name="...")
|
|
|
75
103
|
await engine.initialize()
|
|
76
104
|
|
|
77
105
|
# Get memory service (automatically configured from manifest)
|
|
78
|
-
|
|
106
|
+
# Returns BaseMemoryService instance (currently Mem0MemoryService)
|
|
107
|
+
memory_service: BaseMemoryService = engine.get_memory_service("my_app")
|
|
79
108
|
|
|
80
109
|
# Add memory
|
|
81
110
|
memory = await memory_service.add(
|
|
@@ -163,14 +192,17 @@ results = await memory_service.search(
|
|
|
163
192
|
|
|
164
193
|
### Get Memories
|
|
165
194
|
|
|
166
|
-
Retrieve memories for a user:
|
|
195
|
+
Retrieve memories for a user. The service automatically normalizes Mem0's MongoDB structure (`_id`, `payload`) into a consistent API format:
|
|
167
196
|
|
|
168
197
|
```python
|
|
169
198
|
# Get all memories
|
|
170
199
|
all_memories = await memory_service.get_all(user_id="user123")
|
|
200
|
+
# Returns normalized format: [{"id": "...", "memory": "...", "metadata": {...}, ...}]
|
|
171
201
|
|
|
172
202
|
# Get specific memory
|
|
173
203
|
memory = await memory_service.get(memory_id="memory_123", user_id="user123")
|
|
204
|
+
# Returns normalized format: {"id": "...", "memory": "...", "metadata": {...}, ...}
|
|
205
|
+
# Note: memory_id can be either Mem0's _id or the normalized id field
|
|
174
206
|
|
|
175
207
|
# Get memories with filters
|
|
176
208
|
memories = await memory_service.get_all(
|
|
@@ -179,9 +211,16 @@ memories = await memory_service.get_all(
|
|
|
179
211
|
)
|
|
180
212
|
```
|
|
181
213
|
|
|
214
|
+
**Note**: The service handles Mem0's internal MongoDB structure (`_id` as document ID, `payload` containing memory data) automatically. All methods return normalized documents with consistent `id`, `memory`, `text`, and `metadata` fields.
|
|
215
|
+
|
|
182
216
|
### Update Memory
|
|
183
217
|
|
|
184
|
-
Update existing memories
|
|
218
|
+
Update existing memories using a **hybrid approach** that combines Mem0's embedding capabilities with direct MongoDB control:
|
|
219
|
+
|
|
220
|
+
**Architecture:**
|
|
221
|
+
- **Content Updates**: Routed via Mem0 (triggers automatic re-embedding)
|
|
222
|
+
- **Metadata Updates**: Routed via direct PyMongo (full control, no API limitations)
|
|
223
|
+
- **Return Value**: Always fetched from MongoDB (guaranteed correct structure)
|
|
185
224
|
|
|
186
225
|
```python
|
|
187
226
|
# Update memory content and metadata
|
|
@@ -200,14 +239,21 @@ updated = memory_service.update(
|
|
|
200
239
|
metadata={"updated": True}
|
|
201
240
|
)
|
|
202
241
|
|
|
203
|
-
# Update only metadata (content unchanged)
|
|
242
|
+
# Update only metadata (content unchanged) - FULLY SUPPORTED
|
|
243
|
+
updated = memory_service.update(
|
|
244
|
+
memory_id="memory_123",
|
|
245
|
+
user_id="user123",
|
|
246
|
+
metadata={"category": "updated", "priority": "high"}
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
# Update only content (no metadata changes)
|
|
204
250
|
updated = memory_service.update(
|
|
205
251
|
memory_id="memory_123",
|
|
206
252
|
user_id="user123",
|
|
207
|
-
|
|
253
|
+
memory="Updated content only"
|
|
208
254
|
)
|
|
209
255
|
|
|
210
|
-
#
|
|
256
|
+
# Using 'data' parameter
|
|
211
257
|
updated = memory_service.update(
|
|
212
258
|
memory_id="memory_123",
|
|
213
259
|
user_id="user123",
|
|
@@ -217,12 +263,18 @@ updated = memory_service.update(
|
|
|
217
263
|
```
|
|
218
264
|
|
|
219
265
|
**Key Features:**
|
|
266
|
+
- **Hybrid Architecture**: Mem0 handles embeddings, MongoDB handles data persistence
|
|
267
|
+
- **Full Metadata Support**: Update any metadata field (not limited by Mem0 API)
|
|
220
268
|
- **Preserves Memory ID**: The original memory ID is maintained
|
|
221
269
|
- **Preserves Creation Timestamp**: `created_at` is not modified
|
|
222
270
|
- **Updates Timestamp**: `updated_at` is automatically set to current time
|
|
223
|
-
- **Recomputes Embeddings**: If content changes, the embedding vector is automatically recomputed
|
|
224
|
-
- **
|
|
271
|
+
- **Recomputes Embeddings**: If content changes, the embedding vector is automatically recomputed via Mem0
|
|
272
|
+
- **Reliable Returns**: Always returns the actual document from MongoDB (not Mem0's response format)
|
|
225
273
|
- **Partial Updates**: Can update content only, metadata only, or both
|
|
274
|
+
- **Security**: Validates user_id ownership before allowing updates
|
|
275
|
+
- **Mem0 Structure Aware**: Correctly handles Mem0's MongoDB structure (`_id` as document ID, `payload` for memory data)
|
|
276
|
+
- **Direct MongoDB Access**: Uses PyMongo for reliable data operations, ensuring consistency
|
|
277
|
+
- **Normalized Responses**: All methods return consistent document structure regardless of Mem0's internal format
|
|
226
278
|
|
|
227
279
|
### Delete Memory
|
|
228
280
|
|
|
@@ -336,25 +388,93 @@ for memory in insights:
|
|
|
336
388
|
print(f"Insights: {memory.get('insights')}")
|
|
337
389
|
```
|
|
338
390
|
|
|
391
|
+
## Architecture
|
|
392
|
+
|
|
393
|
+
### Base Class Pattern
|
|
394
|
+
|
|
395
|
+
The memory service uses an abstract base class pattern for extensibility:
|
|
396
|
+
|
|
397
|
+
```python
|
|
398
|
+
from mdb_engine.memory import BaseMemoryService, MemoryServiceError
|
|
399
|
+
|
|
400
|
+
# BaseMemoryService defines the interface
|
|
401
|
+
# Mem0MemoryService implements it (default provider)
|
|
402
|
+
# Future providers can inherit from BaseMemoryService
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
**Benefits:**
|
|
406
|
+
- **Type Safety**: Use `BaseMemoryService` for type hints
|
|
407
|
+
- **Extensibility**: Easy to add new providers (LangChain, custom, etc.)
|
|
408
|
+
- **Consistency**: All providers implement the same interface
|
|
409
|
+
- **Backward Compatible**: Existing code works without changes
|
|
410
|
+
|
|
411
|
+
### Creating Custom Memory Providers
|
|
412
|
+
|
|
413
|
+
To create a custom memory provider, inherit from `BaseMemoryService`:
|
|
414
|
+
|
|
415
|
+
```python
|
|
416
|
+
from mdb_engine.memory import BaseMemoryService, MemoryServiceError
|
|
417
|
+
|
|
418
|
+
class CustomMemoryService(BaseMemoryService):
|
|
419
|
+
"""Custom memory service implementation."""
|
|
420
|
+
|
|
421
|
+
def __init__(self, mongo_uri: str, db_name: str, app_slug: str, config: dict | None = None):
|
|
422
|
+
# Initialize your custom implementation
|
|
423
|
+
pass
|
|
424
|
+
|
|
425
|
+
def add(self, messages, user_id=None, metadata=None, **kwargs):
|
|
426
|
+
# Implement add method
|
|
427
|
+
pass
|
|
428
|
+
|
|
429
|
+
# Implement all other abstract methods...
|
|
430
|
+
def get_all(self, user_id=None, limit=100, filters=None, **kwargs):
|
|
431
|
+
pass
|
|
432
|
+
|
|
433
|
+
def search(self, query, user_id=None, limit=5, filters=None, **kwargs):
|
|
434
|
+
pass
|
|
435
|
+
|
|
436
|
+
def get(self, memory_id, user_id=None, **kwargs):
|
|
437
|
+
pass
|
|
438
|
+
|
|
439
|
+
def delete(self, memory_id, user_id=None, **kwargs):
|
|
440
|
+
pass
|
|
441
|
+
|
|
442
|
+
def delete_all(self, user_id=None, **kwargs):
|
|
443
|
+
pass
|
|
444
|
+
|
|
445
|
+
def update(self, memory_id, user_id=None, memory=None, metadata=None, **kwargs):
|
|
446
|
+
pass
|
|
447
|
+
```
|
|
448
|
+
|
|
339
449
|
## API Reference
|
|
340
450
|
|
|
451
|
+
### BaseMemoryService
|
|
452
|
+
|
|
453
|
+
Abstract base class for all memory service implementations. Defines the standard interface.
|
|
454
|
+
|
|
341
455
|
### Mem0MemoryService
|
|
342
456
|
|
|
457
|
+
Default implementation using Mem0.ai. Inherits from `BaseMemoryService`.
|
|
458
|
+
|
|
343
459
|
#### Initialization
|
|
344
460
|
|
|
345
461
|
```python
|
|
346
462
|
Mem0MemoryService(
|
|
347
463
|
mongo_uri: str,
|
|
348
464
|
db_name: str,
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
465
|
+
app_slug: str,
|
|
466
|
+
config: dict = None # Optional configuration
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
# Or use the factory function
|
|
470
|
+
from mdb_engine.memory import get_memory_service
|
|
471
|
+
|
|
472
|
+
memory_service = get_memory_service(
|
|
473
|
+
mongo_uri="...",
|
|
474
|
+
db_name="...",
|
|
475
|
+
app_slug="...",
|
|
476
|
+
config={...},
|
|
477
|
+
provider="mem0" # Default, future providers can be specified here
|
|
358
478
|
)
|
|
359
479
|
```
|
|
360
480
|
|
|
@@ -513,15 +633,19 @@ knowledge = await memory_service.search(
|
|
|
513
633
|
## Error Handling
|
|
514
634
|
|
|
515
635
|
```python
|
|
516
|
-
from mdb_engine.memory import Mem0MemoryServiceError
|
|
636
|
+
from mdb_engine.memory import MemoryServiceError, Mem0MemoryServiceError
|
|
517
637
|
|
|
518
638
|
try:
|
|
519
639
|
memory = await memory_service.add(
|
|
520
640
|
messages=[{"role": "user", "content": "Test"}],
|
|
521
641
|
user_id="user123"
|
|
522
642
|
)
|
|
523
|
-
except
|
|
643
|
+
except MemoryServiceError as e:
|
|
644
|
+
# Base exception for all memory service errors
|
|
524
645
|
print(f"Memory service error: {e}")
|
|
646
|
+
except Mem0MemoryServiceError as e:
|
|
647
|
+
# Specific exception for Mem0 implementation
|
|
648
|
+
print(f"Mem0 memory service error: {e}")
|
|
525
649
|
except (ValueError, TypeError, ConnectionError) as e:
|
|
526
650
|
print(f"Configuration or connection error: {e}")
|
|
527
651
|
```
|
|
@@ -14,16 +14,25 @@ Key Features:
|
|
|
14
14
|
- **Optional LLM Inference**: Can leverage LLM service for automatic memory
|
|
15
15
|
extraction (set infer: false to disable)
|
|
16
16
|
- **Graph Support**: Optional knowledge graph construction for entity relationships
|
|
17
|
+
- **Extensible Architecture**: Base class allows for future memory provider implementations
|
|
17
18
|
|
|
18
19
|
Dependencies:
|
|
19
20
|
pip install mem0ai
|
|
20
21
|
"""
|
|
21
22
|
|
|
23
|
+
# Import base classes
|
|
24
|
+
from .base import BaseMemoryService, MemoryServiceError
|
|
25
|
+
|
|
22
26
|
# Import service components (mem0 import is lazy within service.py)
|
|
23
27
|
from .service import Mem0MemoryService, Mem0MemoryServiceError, get_memory_service
|
|
24
28
|
|
|
25
29
|
__all__ = [
|
|
30
|
+
# Base classes (for extensibility)
|
|
31
|
+
"BaseMemoryService",
|
|
32
|
+
"MemoryServiceError",
|
|
33
|
+
# Mem0 implementation (default)
|
|
26
34
|
"Mem0MemoryService",
|
|
27
35
|
"Mem0MemoryServiceError",
|
|
36
|
+
# Factory function
|
|
28
37
|
"get_memory_service",
|
|
29
38
|
]
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base Memory Service Interface
|
|
3
|
+
|
|
4
|
+
Abstract base class for memory service implementations.
|
|
5
|
+
This allows for extensibility with different memory providers (Mem0, LangChain, custom, etc.)
|
|
6
|
+
while maintaining a consistent API.
|
|
7
|
+
|
|
8
|
+
This module is part of MDB_ENGINE - MongoDB Engine.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MemoryServiceError(Exception):
|
|
16
|
+
"""Base exception for all memory service errors."""
|
|
17
|
+
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class BaseMemoryService(ABC):
|
|
22
|
+
"""
|
|
23
|
+
Abstract base class for memory service implementations.
|
|
24
|
+
|
|
25
|
+
This class defines the interface that all memory service implementations must follow.
|
|
26
|
+
Concrete implementations (e.g., Mem0MemoryService) inherit from this class and
|
|
27
|
+
implement the abstract methods.
|
|
28
|
+
|
|
29
|
+
All memory operations are scoped per user_id for safety and data isolation.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
@abstractmethod
|
|
33
|
+
def add(
|
|
34
|
+
self,
|
|
35
|
+
messages: str | list[dict[str, str]],
|
|
36
|
+
user_id: str | None = None,
|
|
37
|
+
metadata: dict[str, Any] | None = None,
|
|
38
|
+
bucket_id: str | None = None,
|
|
39
|
+
bucket_type: str | None = None,
|
|
40
|
+
raw_content: str | None = None,
|
|
41
|
+
**kwargs,
|
|
42
|
+
) -> list[dict[str, Any]]:
|
|
43
|
+
"""
|
|
44
|
+
Add memories with user scoping and metadata convenience.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
messages: Memory content as a string or list of message dicts
|
|
48
|
+
user_id: User ID for scoping (optional but recommended)
|
|
49
|
+
metadata: Additional metadata to store with the memory
|
|
50
|
+
bucket_id: Bucket ID for organizing memories
|
|
51
|
+
bucket_type: Type of bucket (e.g., "general", "file", "conversation")
|
|
52
|
+
raw_content: Raw content to store alongside extracted facts
|
|
53
|
+
**kwargs: Additional provider-specific arguments
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
List of created memory objects with their IDs and metadata
|
|
57
|
+
"""
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
@abstractmethod
|
|
61
|
+
def get_all(
|
|
62
|
+
self,
|
|
63
|
+
user_id: str | None = None,
|
|
64
|
+
limit: int = 100,
|
|
65
|
+
filters: dict[str, Any] | None = None,
|
|
66
|
+
**kwargs,
|
|
67
|
+
) -> list[dict[str, Any]]:
|
|
68
|
+
"""
|
|
69
|
+
Get all memories with optional filtering.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
user_id: User ID to filter memories (optional)
|
|
73
|
+
limit: Maximum number of memories to return
|
|
74
|
+
filters: Additional filters to apply (provider-specific)
|
|
75
|
+
**kwargs: Additional provider-specific arguments
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
List of memory objects
|
|
79
|
+
"""
|
|
80
|
+
pass
|
|
81
|
+
|
|
82
|
+
@abstractmethod
|
|
83
|
+
def search(
|
|
84
|
+
self,
|
|
85
|
+
query: str,
|
|
86
|
+
user_id: str | None = None,
|
|
87
|
+
limit: int = 5,
|
|
88
|
+
filters: dict[str, Any] | None = None,
|
|
89
|
+
**kwargs,
|
|
90
|
+
) -> list[dict[str, Any]]:
|
|
91
|
+
"""
|
|
92
|
+
Perform semantic search across memories.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
query: Search query string
|
|
96
|
+
user_id: User ID to scope search (optional)
|
|
97
|
+
limit: Maximum number of results to return
|
|
98
|
+
filters: Additional metadata filters to apply
|
|
99
|
+
**kwargs: Additional provider-specific arguments
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
List of memory objects matching the query, ordered by relevance
|
|
103
|
+
"""
|
|
104
|
+
pass
|
|
105
|
+
|
|
106
|
+
@abstractmethod
|
|
107
|
+
def get(
|
|
108
|
+
self,
|
|
109
|
+
memory_id: str,
|
|
110
|
+
user_id: str | None = None,
|
|
111
|
+
**kwargs,
|
|
112
|
+
) -> dict[str, Any] | None:
|
|
113
|
+
"""
|
|
114
|
+
Get a single memory by ID.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
memory_id: Unique identifier for the memory
|
|
118
|
+
user_id: User ID for security scoping (optional)
|
|
119
|
+
**kwargs: Additional provider-specific arguments
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Memory object if found, None otherwise
|
|
123
|
+
"""
|
|
124
|
+
pass
|
|
125
|
+
|
|
126
|
+
@abstractmethod
|
|
127
|
+
def delete(
|
|
128
|
+
self,
|
|
129
|
+
memory_id: str,
|
|
130
|
+
user_id: str | None = None,
|
|
131
|
+
**kwargs,
|
|
132
|
+
) -> bool:
|
|
133
|
+
"""
|
|
134
|
+
Delete a single memory by ID.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
memory_id: Unique identifier for the memory to delete
|
|
138
|
+
user_id: User ID for security scoping (optional)
|
|
139
|
+
**kwargs: Additional provider-specific arguments
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
True if deletion was successful, False otherwise
|
|
143
|
+
"""
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
@abstractmethod
|
|
147
|
+
def delete_all(
|
|
148
|
+
self,
|
|
149
|
+
user_id: str | None = None,
|
|
150
|
+
**kwargs,
|
|
151
|
+
) -> bool:
|
|
152
|
+
"""
|
|
153
|
+
Delete all memories for a user.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
user_id: User ID whose memories should be deleted (optional)
|
|
157
|
+
**kwargs: Additional provider-specific arguments
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
True if deletion was successful, False otherwise
|
|
161
|
+
"""
|
|
162
|
+
pass
|
|
163
|
+
|
|
164
|
+
@abstractmethod
|
|
165
|
+
def update(
|
|
166
|
+
self,
|
|
167
|
+
memory_id: str,
|
|
168
|
+
user_id: str | None = None,
|
|
169
|
+
memory: str | None = None,
|
|
170
|
+
data: str | dict[str, Any] | None = None,
|
|
171
|
+
messages: str | list[dict[str, str]] | None = None,
|
|
172
|
+
metadata: dict[str, Any] | None = None,
|
|
173
|
+
**kwargs,
|
|
174
|
+
) -> dict[str, Any] | None:
|
|
175
|
+
"""
|
|
176
|
+
Update an existing memory's content and/or metadata.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
memory_id: Unique identifier for the memory to update (required)
|
|
180
|
+
user_id: User ID for security scoping (optional)
|
|
181
|
+
memory: New memory content as a string (optional)
|
|
182
|
+
data: Alternative parameter for content (string or dict) (optional)
|
|
183
|
+
messages: Alternative way to provide content as messages (optional)
|
|
184
|
+
metadata: Metadata updates (optional)
|
|
185
|
+
**kwargs: Additional provider-specific arguments
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
Updated memory object if successful, None if memory not found
|
|
189
|
+
|
|
190
|
+
Raises:
|
|
191
|
+
MemoryServiceError: If update operation fails
|
|
192
|
+
ValueError: If memory_id is invalid or empty
|
|
193
|
+
"""
|
|
194
|
+
pass
|