mdb-engine 0.7.3__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.
Files changed (107) hide show
  1. {mdb_engine-0.7.3/mdb_engine.egg-info → mdb_engine-0.7.4}/PKG-INFO +1 -1
  2. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/__init__.py +1 -1
  3. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/cli/main.py +1 -1
  4. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/engine.py +3 -2
  5. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/service_initialization.py +5 -4
  6. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/types.py +2 -2
  7. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/dependencies.py +3 -3
  8. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/memory/README.md +145 -21
  9. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/memory/__init__.py +9 -0
  10. mdb_engine-0.7.4/mdb_engine/memory/base.py +194 -0
  11. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/memory/service.py +318 -162
  12. {mdb_engine-0.7.3 → mdb_engine-0.7.4/mdb_engine.egg-info}/PKG-INFO +1 -1
  13. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine.egg-info/SOURCES.txt +1 -0
  14. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/pyproject.toml +1 -1
  15. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/setup.py +1 -1
  16. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/LICENSE +0 -0
  17. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/MANIFEST.in +0 -0
  18. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/README.md +0 -0
  19. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/README.md +0 -0
  20. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/ARCHITECTURE.md +0 -0
  21. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/README.md +0 -0
  22. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/__init__.py +0 -0
  23. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/audit.py +0 -0
  24. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/base.py +0 -0
  25. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/casbin_factory.py +0 -0
  26. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/casbin_models.py +0 -0
  27. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/config_defaults.py +0 -0
  28. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/config_helpers.py +0 -0
  29. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/cookie_utils.py +0 -0
  30. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/csrf.py +0 -0
  31. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/decorators.py +0 -0
  32. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/dependencies.py +0 -0
  33. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/helpers.py +0 -0
  34. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/integration.py +0 -0
  35. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/jwt.py +0 -0
  36. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/middleware.py +0 -0
  37. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/oso_factory.py +0 -0
  38. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/provider.py +0 -0
  39. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/rate_limiter.py +0 -0
  40. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/restrictions.py +0 -0
  41. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/session_manager.py +0 -0
  42. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/shared_middleware.py +0 -0
  43. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/shared_users.py +0 -0
  44. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/token_lifecycle.py +0 -0
  45. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/token_store.py +0 -0
  46. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/users.py +0 -0
  47. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/utils.py +0 -0
  48. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/websocket_sessions.py +0 -0
  49. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/auth/websocket_tickets.py +0 -0
  50. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/cli/__init__.py +0 -0
  51. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/cli/commands/__init__.py +0 -0
  52. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/cli/commands/generate.py +0 -0
  53. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/cli/commands/migrate.py +0 -0
  54. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/cli/commands/show.py +0 -0
  55. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/cli/commands/validate.py +0 -0
  56. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/cli/utils.py +0 -0
  57. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/config.py +0 -0
  58. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/constants.py +0 -0
  59. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/README.md +0 -0
  60. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/__init__.py +0 -0
  61. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/app_registration.py +0 -0
  62. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/app_secrets.py +0 -0
  63. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/connection.py +0 -0
  64. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/encryption.py +0 -0
  65. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/index_management.py +0 -0
  66. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/manifest.py +0 -0
  67. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/ray_integration.py +0 -0
  68. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/core/seeding.py +0 -0
  69. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/database/README.md +0 -0
  70. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/database/__init__.py +0 -0
  71. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/database/abstraction.py +0 -0
  72. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/database/connection.py +0 -0
  73. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/database/query_validator.py +0 -0
  74. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/database/resource_limiter.py +0 -0
  75. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/database/scoped_wrapper.py +0 -0
  76. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/di/__init__.py +0 -0
  77. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/di/container.py +0 -0
  78. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/di/providers.py +0 -0
  79. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/di/scopes.py +0 -0
  80. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/embeddings/README.md +0 -0
  81. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/embeddings/__init__.py +0 -0
  82. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/embeddings/dependencies.py +0 -0
  83. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/embeddings/service.py +0 -0
  84. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/exceptions.py +0 -0
  85. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/indexes/README.md +0 -0
  86. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/indexes/__init__.py +0 -0
  87. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/indexes/helpers.py +0 -0
  88. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/indexes/manager.py +0 -0
  89. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/observability/README.md +0 -0
  90. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/observability/__init__.py +0 -0
  91. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/observability/health.py +0 -0
  92. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/observability/logging.py +0 -0
  93. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/observability/metrics.py +0 -0
  94. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/repositories/__init__.py +0 -0
  95. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/repositories/base.py +0 -0
  96. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/repositories/mongo.py +0 -0
  97. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/repositories/unit_of_work.py +0 -0
  98. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/routing/README.md +0 -0
  99. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/routing/__init__.py +0 -0
  100. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/routing/websockets.py +0 -0
  101. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/utils/__init__.py +0 -0
  102. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine/utils/mongo.py +0 -0
  103. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine.egg-info/dependency_links.txt +0 -0
  104. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine.egg-info/entry_points.txt +0 -0
  105. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine.egg-info/requires.txt +0 -0
  106. {mdb_engine-0.7.3 → mdb_engine-0.7.4}/mdb_engine.egg-info/top_level.txt +0 -0
  107. {mdb_engine-0.7.3 → 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
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
@@ -81,7 +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__ = "0.7.3"
84
+ __version__ = "0.7.4"
85
85
 
86
86
  __all__ = [
87
87
  # Core Engine
@@ -15,7 +15,7 @@ from .commands.validate import validate
15
15
 
16
16
 
17
17
  @click.group()
18
- @click.version_option(version="0.7.3", prog_name="mdb")
18
+ @click.version_option(version="0.7.4", prog_name="mdb")
19
19
  def cli() -> None:
20
20
  """
21
21
  MDB_ENGINE CLI - Manifest management tool.
@@ -910,13 +910,14 @@ class MongoDBEngine:
910
910
 
911
911
  def get_memory_service(self, slug: str) -> Any | None:
912
912
  """
913
- Get Mem0 memory service for an app.
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
- Mem0MemoryService instance if memory is enabled for this app, None otherwise
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 Mem0 memory service for an app.
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
- mem0 handles embeddings and LLM via environment variables (.env).
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 Mem0 memory service for an app.
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
- Mem0MemoryService instance if memory is enabled for this app, None otherwise
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 Mem0MemoryService
14
+ from ..memory import BaseMemoryService
15
15
  else:
16
- Mem0MemoryService = Any
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.service import Mem0MemoryService
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["Mem0MemoryService"]:
125
- """Get the Mem0 memory service if configured."""
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
- - **Mem0 Integration**: Wrapper around Mem0.ai for intelligent memory management
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 Mem0MemoryService
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
- memory_service = engine.get_memory_service("my_app")
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 in-place while preserving the original memory ID and creation timestamp:
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
- metadata={"category": "updated"}
253
+ memory="Updated content only"
208
254
  )
209
255
 
210
- # Backward compatibility: using 'data' parameter
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
- - **Metadata Merging**: New metadata is merged with existing metadata (doesn't replace)
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
- collection_name: str = "memories",
350
- app_slug: str = None,
351
- embedding_model: str = "text-embedding-3-small",
352
- embedding_dimensions: int = None,
353
- chat_model: str = "gpt-4",
354
- temperature: float = 0.7,
355
- infer: bool = True,
356
- enable_graph: bool = False,
357
- config: dict = None
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 Mem0MemoryServiceError as e:
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