mdb-engine 0.7.4__py3-none-any.whl → 0.7.5__py3-none-any.whl

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/__init__.py CHANGED
@@ -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.4"
84
+ __version__ = "0.7.5"
85
85
 
86
86
  __all__ = [
87
87
  # Core Engine
mdb_engine/cli/main.py CHANGED
@@ -15,7 +15,7 @@ from .commands.validate import validate
15
15
 
16
16
 
17
17
  @click.group()
18
- @click.version_option(version="0.7.4", prog_name="mdb")
18
+ @click.version_option(version="0.7.5", prog_name="mdb")
19
19
  def cli() -> None:
20
20
  """
21
21
  MDB_ENGINE CLI - Manifest management tool.
@@ -16,6 +16,14 @@ The memory service now uses an abstract base class pattern, enabling future memo
16
16
  - **📝 Type Safety**: Better IDE support and type checking with abstract base class
17
17
  - **🎯 Consistent API**: All memory providers implement the same interface
18
18
 
19
+ ### v0.7.5 Enhancements
20
+
21
+ **Memory Injection and Enhanced Delete Capabilities!**
22
+
23
+ - **💉 Inject Method**: New `inject()` method for manual memory insertion without LLM inference - perfect for adding facts, preferences, or structured data directly
24
+ - **🗑️ Enhanced Delete**: Comprehensive delete functionality with improved documentation and user experience
25
+ - **🧠 Memory Explorer UI**: Added memory explorer interface in chit_chat example with inject and delete buttons
26
+
19
27
  ### v0.7.4 Enhancements
20
28
 
21
29
  **Enhanced Mem0 Integration - Production Ready!**
@@ -169,6 +177,45 @@ memories = await memory_service.add_all(
169
177
  )
170
178
  ```
171
179
 
180
+ ### Inject Memory (Manual Insertion)
181
+
182
+ Manually inject memories without LLM inference. This is useful when you want to directly add facts, preferences, or structured data without going through the inference pipeline:
183
+
184
+ ```python
185
+ # Inject memory as a string
186
+ memory = await memory_service.inject(
187
+ memory="The user prefers dark mode interfaces",
188
+ user_id="user123",
189
+ metadata={"source": "manual", "category": "preference"}
190
+ )
191
+
192
+ # Inject memory as a dict
193
+ memory = await memory_service.inject(
194
+ memory={"memory": "Project deadline is next Friday", "category": "work"},
195
+ user_id="user123",
196
+ metadata={"source": "manual", "type": "deadline"}
197
+ )
198
+
199
+ # Returns: {"id": "...", "memory": "...", "metadata": {...}, ...}
200
+ ```
201
+
202
+ **Key Differences from `add()`:**
203
+ - **`inject()`**: Direct insertion without LLM inference (faster, no API costs)
204
+ - **`add()`**: Uses LLM inference to extract facts from messages (slower, costs API calls)
205
+ - **`inject()`**: Returns a single memory dict
206
+ - **`add()`**: Returns a list of extracted memories
207
+
208
+ **When to use `inject()`:**
209
+ - Adding known facts or preferences directly
210
+ - Importing structured data
211
+ - When you want to avoid LLM inference costs
212
+ - When you have pre-formatted memory content
213
+
214
+ **When to use `add()`:**
215
+ - Extracting memories from conversations
216
+ - When you want the LLM to identify key facts
217
+ - Processing unstructured text into memories
218
+
172
219
  ### Search Memories
173
220
 
174
221
  Semantic search across stored memories:
@@ -278,16 +325,48 @@ updated = memory_service.update(
278
325
 
279
326
  ### Delete Memory
280
327
 
281
- Remove memories:
328
+ Remove memories from storage. Both methods return `True` on success, `False` on failure:
282
329
 
283
330
  ```python
284
- # Delete single memory
285
- await memory_service.delete(memory_id="memory_123", user_id="user123")
286
-
287
- # Delete all memories for user
288
- await memory_service.delete_all(user_id="user123")
331
+ # Delete single memory by ID
332
+ success = await memory_service.delete(memory_id="memory_123", user_id="user123")
333
+ if success:
334
+ print("Memory deleted successfully")
335
+ else:
336
+ print("Failed to delete memory (may not exist)")
337
+
338
+ # Delete all memories for a user (use with caution!)
339
+ success = await memory_service.delete_all(user_id="user123")
340
+ if success:
341
+ print("All memories deleted successfully")
342
+
343
+ # Delete with error handling
344
+ try:
345
+ success = await memory_service.delete(memory_id="memory_123", user_id="user123")
346
+ if not success:
347
+ logger.warning(f"Memory {memory_id} not found or already deleted")
348
+ except Mem0MemoryServiceError as e:
349
+ logger.error(f"Error deleting memory: {e}")
289
350
  ```
290
351
 
352
+ **Key Features:**
353
+ - **User Scoping**: Both methods respect `user_id` for security
354
+ - **Safe Deletion**: Returns `False` if memory doesn't exist (doesn't raise exception)
355
+ - **Bulk Deletion**: `delete_all()` removes all memories for a user
356
+ - **Idempotent**: Safe to call multiple times (returns `False` if already deleted)
357
+
358
+ **When to use `delete()`:**
359
+ - Removing a specific memory by ID
360
+ - Cleaning up outdated or incorrect memories
361
+ - User-initiated memory removal
362
+
363
+ **When to use `delete_all()`:**
364
+ - Resetting user memory (e.g., account deletion)
365
+ - Clearing test data
366
+ - Bulk cleanup operations
367
+
368
+ **Note**: Deletion is permanent and cannot be undone. Consider implementing soft deletes if you need to recover deleted memories.
369
+
291
370
  ### Bucket Organization
292
371
 
293
372
  Organize memories into buckets for better management:
@@ -481,6 +560,7 @@ memory_service = get_memory_service(
481
560
  #### Methods
482
561
 
483
562
  - `add(messages, user_id, metadata=None, bucket_id=None, bucket_type=None, store_raw_content=False, raw_content=None)` - Add single memory with optional bucket and raw content storage
563
+ - `inject(memory, user_id, metadata=None)` - Manually inject a memory without LLM inference
484
564
  - `add_with_raw_content(messages, raw_content, user_id, bucket_id=None, bucket_type=None)` - Store both extracted facts and raw content
485
565
  - `get_buckets(user_id, bucket_type=None, limit=None)` - Get all buckets for a user
486
566
  - `get_bucket_memories(bucket_id, user_id, include_raw_content=False, limit=None)` - Get all memories in a bucket
mdb_engine/memory/base.py CHANGED
@@ -57,6 +57,36 @@ class BaseMemoryService(ABC):
57
57
  """
58
58
  pass
59
59
 
60
+ @abstractmethod
61
+ def inject(
62
+ self,
63
+ memory: str | dict[str, Any],
64
+ user_id: str | None = None,
65
+ metadata: dict[str, Any] | None = None,
66
+ **kwargs,
67
+ ) -> dict[str, Any]:
68
+ """
69
+ Manually inject a memory without LLM inference.
70
+
71
+ This method allows direct insertion of memories without going through
72
+ the inference pipeline. Useful for manually adding facts, preferences,
73
+ or other structured data.
74
+
75
+ Args:
76
+ memory: Memory content as a string or dict with memory/text/content key
77
+ user_id: User ID for scoping (optional but recommended)
78
+ metadata: Additional metadata to store with the memory
79
+ **kwargs: Additional provider-specific arguments
80
+
81
+ Returns:
82
+ Created memory object with ID and metadata
83
+
84
+ Raises:
85
+ MemoryServiceError: If injection operation fails
86
+ ValueError: If memory content is invalid or empty
87
+ """
88
+ pass
89
+
60
90
  @abstractmethod
61
91
  def get_all(
62
92
  self,
@@ -4,6 +4,9 @@ Production-ready wrapper for Mem0.ai with strict metadata schema for MongoDB.
4
4
 
5
5
  v0.7.4: Enhanced with hybrid update pattern and direct MongoDB access for reliable
6
6
  memory operations. Properly handles Mem0's MongoDB structure (_id, payload).
7
+
8
+ v0.7.5: Added inject() method for manual memory insertion without LLM inference,
9
+ and enhanced delete functionality with comprehensive documentation.
7
10
  """
8
11
 
9
12
  import logging
@@ -419,6 +422,100 @@ class Mem0MemoryService(BaseMemoryService):
419
422
  logger.exception("Mem0 Add Failed")
420
423
  raise Mem0MemoryServiceError(f"Add failed: {e}") from e
421
424
 
425
+ def inject(
426
+ self,
427
+ memory: str | dict[str, Any],
428
+ user_id: str | None = None,
429
+ metadata: dict[str, Any] | None = None,
430
+ **kwargs,
431
+ ) -> dict[str, Any]:
432
+ """
433
+ Manually inject a memory without LLM inference.
434
+
435
+ This method allows direct insertion of memories without going through
436
+ the inference pipeline. Useful for manually adding facts, preferences,
437
+ or other structured data.
438
+
439
+ Args:
440
+ memory: Memory content as a string or dict with memory/text/content key
441
+ user_id: User ID for scoping (optional but recommended)
442
+ metadata: Additional metadata to store with the memory
443
+ **kwargs: Additional provider-specific arguments
444
+
445
+ Returns:
446
+ Created memory object with ID and metadata
447
+
448
+ Raises:
449
+ Mem0MemoryServiceError: If injection operation fails
450
+ ValueError: If memory content is invalid or empty
451
+ """
452
+ # Normalize input: convert dict to string if needed
453
+ if isinstance(memory, dict):
454
+ # Extract memory content from dict (support multiple key formats)
455
+ memory_content = (
456
+ memory.get("memory") or memory.get("text") or memory.get("content") or str(memory)
457
+ )
458
+ if not memory_content or not isinstance(memory_content, str):
459
+ raise ValueError(
460
+ "Memory dict must contain 'memory', 'text', or 'content' key with string value"
461
+ )
462
+ # Merge any metadata from the dict
463
+ if "metadata" in memory and isinstance(memory["metadata"], dict):
464
+ final_metadata = dict(metadata) if metadata else {}
465
+ final_metadata.update(memory["metadata"])
466
+ metadata = final_metadata
467
+ elif isinstance(memory, str):
468
+ memory_content = memory.strip()
469
+ if not memory_content:
470
+ raise ValueError("Memory content cannot be empty")
471
+ else:
472
+ raise TypeError(f"Memory must be a string or dict, got {type(memory).__name__}")
473
+
474
+ # Convert to messages format for add() method
475
+ messages = [{"role": "user", "content": memory_content}]
476
+
477
+ try:
478
+ # Call add() with infer=False to bypass LLM inference
479
+ logger.debug(
480
+ f"Injecting memory without inference for user_id={user_id}, "
481
+ f"memory_length={len(memory_content)}"
482
+ )
483
+ result = self.add(
484
+ messages=messages,
485
+ user_id=user_id,
486
+ metadata=metadata,
487
+ infer=False, # Explicitly disable inference
488
+ **kwargs,
489
+ )
490
+
491
+ # Return the first created memory (normalized format)
492
+ if result and isinstance(result, list) and len(result) > 0:
493
+ injected_memory = result[0]
494
+ logger.info(
495
+ f"Successfully injected memory with id={injected_memory.get('id')} "
496
+ f"for user_id={user_id}"
497
+ )
498
+ return injected_memory
499
+ else:
500
+ # This shouldn't happen, but handle gracefully
501
+ logger.warning(
502
+ f"add() returned empty result for inject() call. "
503
+ f"user_id={user_id}, memory_length={len(memory_content)}"
504
+ )
505
+ raise Mem0MemoryServiceError("Failed to inject memory: add() returned empty result")
506
+ except (ValueError, TypeError):
507
+ # Re-raise validation errors as-is
508
+ raise
509
+ except (
510
+ ConnectionError,
511
+ OSError,
512
+ AttributeError,
513
+ RuntimeError,
514
+ KeyError,
515
+ ) as e:
516
+ logger.exception("Mem0 inject failed")
517
+ raise Mem0MemoryServiceError(f"Inject failed: {e}") from e
518
+
422
519
  def get_all(
423
520
  self,
424
521
  user_id: str | None = None,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mdb-engine
3
- Version: 0.7.4
3
+ Version: 0.7.5
4
4
  Summary: MongoDB Engine
5
5
  Home-page: https://github.com/ranfysvalle02/mdb-engine
6
6
  Author: Fabian Valle
@@ -1,5 +1,5 @@
1
1
  mdb_engine/README.md,sha256=T3EFGcPopY9LslYW3lxgG3hohWkAOmBNbYG0FDMUJiY,3502
2
- mdb_engine/__init__.py,sha256=OkNHx17I4f8jI5IAJGK0HbSTrZrUVnl1QlvtPZLri-I,3097
2
+ mdb_engine/__init__.py,sha256=hBCXmvmuddGc2c_heZv75UyxP3rDSi4PViu596O-16I,3097
3
3
  mdb_engine/config.py,sha256=DTAyxfKB8ogyI0v5QR9Y-SJOgXQr_eDBCKxNBSqEyLc,7269
4
4
  mdb_engine/constants.py,sha256=eaotvW57TVOg7rRbLziGrVNoP7adgw_G9iVByHezc_A,7837
5
5
  mdb_engine/dependencies.py,sha256=F2_hbtK-lyeqB_iPeJVCh8jFbHi7sx0fduCUCNCKoUc,14128
@@ -35,7 +35,7 @@ mdb_engine/auth/utils.py,sha256=YkexCo0xV37mpOJUI32cntRHVOUUS7r19TIMPWHcgpA,2734
35
35
  mdb_engine/auth/websocket_sessions.py,sha256=7eFNagY2K3Rp1x7d_cO5JcpT-DrYkc__cmVhl6pAC2M,15081
36
36
  mdb_engine/auth/websocket_tickets.py,sha256=VoIArcnQBtYqXRMs-5m7NSvCJB1dEeHrLl7j7yG-H-A,9887
37
37
  mdb_engine/cli/__init__.py,sha256=PANRi4THmL34d1mawlqxIrnuItXMdqoMTq5Z1zHd7rM,301
38
- mdb_engine/cli/main.py,sha256=4etDTeg4DIPQQ5HdWIwcpg9FWLx21NXF6f2fj4xG8gQ,811
38
+ mdb_engine/cli/main.py,sha256=nT1Ws3jzYLblnHMXotqoPKaeI8CZlaek-fOOL0nFfAg,811
39
39
  mdb_engine/cli/utils.py,sha256=bNRGJgdzxUjXAOVe1aoxWJ5M_IqtAE-eW4pfAkwiDDM,2760
40
40
  mdb_engine/cli/commands/__init__.py,sha256=ZSzMhKdV9ILD5EbOSxDV9nURHo1e4bQ0c8AWpqsTEqM,115
41
41
  mdb_engine/cli/commands/generate.py,sha256=VEcn7qNQkIPQlLEK3oXUBgYMwD-G0FyomXQcWTtKsbs,17304
@@ -74,10 +74,10 @@ mdb_engine/indexes/README.md,sha256=r7duq-1vtqHhBk1cwoBMYYh_dfTzxiaQaPE3mLB_3JQ,
74
74
  mdb_engine/indexes/__init__.py,sha256=9QFJ6qo_yD26dZcKyKjj-hhesFpaomBt-mWTtYTQvqc,613
75
75
  mdb_engine/indexes/helpers.py,sha256=tJHqDm18jKLrW-P2ofmnUnaf4_-V5xDLjqP_WU8W9MM,4190
76
76
  mdb_engine/indexes/manager.py,sha256=ekrYBfKD-GOBpZMjXIZWSQ7UPLgrD5BINYzVteWkSI8,32508
77
- mdb_engine/memory/README.md,sha256=3NqI-Sm8Cy-4lsU1wAWxSg92XpRFK19OfDU_dLo3go0,20581
77
+ mdb_engine/memory/README.md,sha256=-HTYbBF4SQICvimThgfyNIc4mUVXnNmGpJpkKZZQnWo,23842
78
78
  mdb_engine/memory/__init__.py,sha256=VEB8PuNBB6q1mSlIYXv9xWt14YmxdiSV5D9hrgmMW94,1328
79
- mdb_engine/memory/base.py,sha256=bI1Rl14mEAsRSMKe8_3jxzrs-N8LGdYWPwXXRziRDLs,5759
80
- mdb_engine/memory/service.py,sha256=9uReFG5FaTIs7Fl6Kz7sXES4Uj_4ao7bgcfs32Nvd9U,37164
79
+ mdb_engine/memory/base.py,sha256=JXpACAB6gHb4jZPbxcSoltmIh1wsAv36qWOFCYN6LuQ,6768
80
+ mdb_engine/memory/service.py,sha256=E1xsLrWp1s0_a_3YbT6AV8YDw7BJJxQ8Ea_Vt38ibOI,41201
81
81
  mdb_engine/observability/README.md,sha256=CMgQaC1H8ESmCitfbhJifz6-XoXH_FPNE4MvuZ-oFas,13085
82
82
  mdb_engine/observability/__init__.py,sha256=jjLsrW6Gy2ayrbfLrgHsDB61NxWWkYLHwv0q-N3fxjA,1213
83
83
  mdb_engine/observability/health.py,sha256=ORjxF_rHYA9vCoxUqel5p0n9g3PLmHsHQn68Q402b6g,9212
@@ -92,9 +92,9 @@ mdb_engine/routing/__init__.py,sha256=reupjHi_RTc2ZBA4AH5XzobAmqy4EQIsfSUcTkFknU
92
92
  mdb_engine/routing/websockets.py,sha256=w0m1XMpXKPpPrEBcZNIj8B8PwWeTNrseUZE1P8cipdM,53441
93
93
  mdb_engine/utils/__init__.py,sha256=lDxQSGqkV4fVw5TWIk6FA6_eey_ZnEtMY0fir3cpAe8,236
94
94
  mdb_engine/utils/mongo.py,sha256=Oqtv4tQdpiiZzrilGLEYQPo8Vmh8WsTQypxQs8Of53s,3369
95
- mdb_engine-0.7.4.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
96
- mdb_engine-0.7.4.dist-info/METADATA,sha256=T67AUeMaWC1ybxcQRAbPlYgKv9S5yWOJpWsIGCJVyrI,18843
97
- mdb_engine-0.7.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
98
- mdb_engine-0.7.4.dist-info/entry_points.txt,sha256=INCbYdFbBzJalwPwxliEzLmPfR57IvQ7RAXG_pn8cL8,48
99
- mdb_engine-0.7.4.dist-info/top_level.txt,sha256=PH0UEBwTtgkm2vWvC9He_EOMn7hVn_Wg_Jyc0SmeO8k,11
100
- mdb_engine-0.7.4.dist-info/RECORD,,
95
+ mdb_engine-0.7.5.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
96
+ mdb_engine-0.7.5.dist-info/METADATA,sha256=H7O6Pdyms68A2xwX1m05mPfUO-yomSYFENoXqgHvIhQ,18843
97
+ mdb_engine-0.7.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
98
+ mdb_engine-0.7.5.dist-info/entry_points.txt,sha256=INCbYdFbBzJalwPwxliEzLmPfR57IvQ7RAXG_pn8cL8,48
99
+ mdb_engine-0.7.5.dist-info/top_level.txt,sha256=PH0UEBwTtgkm2vWvC9He_EOMn7hVn_Wg_Jyc0SmeO8k,11
100
+ mdb_engine-0.7.5.dist-info/RECORD,,