MemoryOS 1.0.1__py3-none-any.whl → 1.1.1__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.

Potentially problematic release.


This version of MemoryOS might be problematic. Click here for more details.

Files changed (82) hide show
  1. {memoryos-1.0.1.dist-info → memoryos-1.1.1.dist-info}/METADATA +7 -2
  2. {memoryos-1.0.1.dist-info → memoryos-1.1.1.dist-info}/RECORD +79 -65
  3. {memoryos-1.0.1.dist-info → memoryos-1.1.1.dist-info}/WHEEL +1 -1
  4. memos/__init__.py +1 -1
  5. memos/api/client.py +109 -0
  6. memos/api/config.py +11 -9
  7. memos/api/context/dependencies.py +15 -55
  8. memos/api/middleware/request_context.py +9 -40
  9. memos/api/product_api.py +2 -3
  10. memos/api/product_models.py +91 -16
  11. memos/api/routers/product_router.py +23 -16
  12. memos/api/start_api.py +10 -0
  13. memos/configs/graph_db.py +4 -0
  14. memos/configs/mem_scheduler.py +38 -3
  15. memos/context/context.py +255 -0
  16. memos/embedders/factory.py +2 -0
  17. memos/graph_dbs/nebular.py +230 -232
  18. memos/graph_dbs/neo4j.py +35 -1
  19. memos/graph_dbs/neo4j_community.py +7 -0
  20. memos/llms/factory.py +2 -0
  21. memos/llms/openai.py +74 -2
  22. memos/log.py +27 -15
  23. memos/mem_cube/general.py +3 -1
  24. memos/mem_os/core.py +60 -22
  25. memos/mem_os/main.py +3 -6
  26. memos/mem_os/product.py +35 -11
  27. memos/mem_reader/factory.py +2 -0
  28. memos/mem_reader/simple_struct.py +127 -74
  29. memos/mem_scheduler/analyzer/__init__.py +0 -0
  30. memos/mem_scheduler/analyzer/mos_for_test_scheduler.py +569 -0
  31. memos/mem_scheduler/analyzer/scheduler_for_eval.py +280 -0
  32. memos/mem_scheduler/base_scheduler.py +126 -56
  33. memos/mem_scheduler/general_modules/dispatcher.py +2 -2
  34. memos/mem_scheduler/general_modules/misc.py +99 -1
  35. memos/mem_scheduler/general_modules/scheduler_logger.py +17 -11
  36. memos/mem_scheduler/general_scheduler.py +40 -88
  37. memos/mem_scheduler/memory_manage_modules/__init__.py +5 -0
  38. memos/mem_scheduler/memory_manage_modules/memory_filter.py +308 -0
  39. memos/mem_scheduler/{general_modules → memory_manage_modules}/retriever.py +34 -7
  40. memos/mem_scheduler/monitors/dispatcher_monitor.py +9 -8
  41. memos/mem_scheduler/monitors/general_monitor.py +119 -39
  42. memos/mem_scheduler/optimized_scheduler.py +124 -0
  43. memos/mem_scheduler/orm_modules/__init__.py +0 -0
  44. memos/mem_scheduler/orm_modules/base_model.py +635 -0
  45. memos/mem_scheduler/orm_modules/monitor_models.py +261 -0
  46. memos/mem_scheduler/scheduler_factory.py +2 -0
  47. memos/mem_scheduler/schemas/monitor_schemas.py +96 -29
  48. memos/mem_scheduler/utils/config_utils.py +100 -0
  49. memos/mem_scheduler/utils/db_utils.py +33 -0
  50. memos/mem_scheduler/utils/filter_utils.py +1 -1
  51. memos/mem_scheduler/webservice_modules/__init__.py +0 -0
  52. memos/memories/activation/kv.py +2 -1
  53. memos/memories/textual/item.py +95 -16
  54. memos/memories/textual/naive.py +1 -1
  55. memos/memories/textual/tree.py +27 -3
  56. memos/memories/textual/tree_text_memory/organize/handler.py +4 -2
  57. memos/memories/textual/tree_text_memory/organize/manager.py +28 -14
  58. memos/memories/textual/tree_text_memory/organize/relation_reason_detector.py +1 -2
  59. memos/memories/textual/tree_text_memory/organize/reorganizer.py +75 -23
  60. memos/memories/textual/tree_text_memory/retrieve/bochasearch.py +7 -5
  61. memos/memories/textual/tree_text_memory/retrieve/internet_retriever.py +6 -2
  62. memos/memories/textual/tree_text_memory/retrieve/internet_retriever_factory.py +2 -0
  63. memos/memories/textual/tree_text_memory/retrieve/recall.py +70 -22
  64. memos/memories/textual/tree_text_memory/retrieve/searcher.py +101 -33
  65. memos/memories/textual/tree_text_memory/retrieve/xinyusearch.py +5 -4
  66. memos/memos_tools/singleton.py +174 -0
  67. memos/memos_tools/thread_safe_dict.py +22 -0
  68. memos/memos_tools/thread_safe_dict_segment.py +382 -0
  69. memos/parsers/factory.py +2 -0
  70. memos/reranker/concat.py +59 -0
  71. memos/reranker/cosine_local.py +1 -0
  72. memos/reranker/factory.py +5 -0
  73. memos/reranker/http_bge.py +225 -12
  74. memos/templates/mem_scheduler_prompts.py +242 -0
  75. memos/types.py +4 -1
  76. memos/api/context/context.py +0 -147
  77. memos/api/context/context_thread.py +0 -96
  78. memos/mem_scheduler/mos_for_test_scheduler.py +0 -146
  79. {memoryos-1.0.1.dist-info → memoryos-1.1.1.dist-info}/entry_points.txt +0 -0
  80. {memoryos-1.0.1.dist-info → memoryos-1.1.1.dist-info/licenses}/LICENSE +0 -0
  81. /memos/mem_scheduler/{general_modules → webservice_modules}/rabbitmq_service.py +0 -0
  82. /memos/mem_scheduler/{general_modules → webservice_modules}/redis_service.py +0 -0
@@ -2,11 +2,18 @@ from datetime import datetime
2
2
  from threading import Lock
3
3
  from typing import Any
4
4
 
5
+ from sqlalchemy.engine import Engine
6
+
5
7
  from memos.configs.mem_scheduler import BaseSchedulerConfig
6
8
  from memos.llms.base import BaseLLM
7
9
  from memos.log import get_logger
8
10
  from memos.mem_cube.general import GeneralMemCube
9
11
  from memos.mem_scheduler.general_modules.base import BaseSchedulerModule
12
+ from memos.mem_scheduler.orm_modules.base_model import BaseDBManager
13
+ from memos.mem_scheduler.orm_modules.monitor_models import (
14
+ DBManagerForMemoryMonitorManager,
15
+ DBManagerForQueryMonitorQueue,
16
+ )
10
17
  from memos.mem_scheduler.schemas.general_schemas import (
11
18
  DEFAULT_ACTIVATION_MEM_MONITOR_SIZE_LIMIT,
12
19
  DEFAULT_WEIGHT_VECTOR_FOR_RANKING,
@@ -19,7 +26,6 @@ from memos.mem_scheduler.schemas.general_schemas import (
19
26
  from memos.mem_scheduler.schemas.monitor_schemas import (
20
27
  MemoryMonitorItem,
21
28
  MemoryMonitorManager,
22
- QueryMonitorItem,
23
29
  QueryMonitorQueue,
24
30
  )
25
31
  from memos.mem_scheduler.utils.misc_utils import extract_json_dict
@@ -32,7 +38,9 @@ logger = get_logger(__name__)
32
38
  class SchedulerGeneralMonitor(BaseSchedulerModule):
33
39
  """Monitors and manages scheduling operations with LLM integration."""
34
40
 
35
- def __init__(self, process_llm: BaseLLM, config: BaseSchedulerConfig):
41
+ def __init__(
42
+ self, process_llm: BaseLLM, config: BaseSchedulerConfig, db_engine: Engine | None = None
43
+ ):
36
44
  super().__init__()
37
45
 
38
46
  # hyper-parameters
@@ -49,12 +57,22 @@ class SchedulerGeneralMonitor(BaseSchedulerModule):
49
57
  "activation_mem_monitor_capacity", DEFAULT_ACTIVATION_MEM_MONITOR_SIZE_LIMIT
50
58
  )
51
59
 
52
- # attributes
53
- # recording query_messages
54
- self.query_monitors: dict[UserID, dict[MemCubeID, QueryMonitorQueue[QueryMonitorItem]]] = {}
60
+ # ORM-based monitor managers
61
+ self.db_engine = db_engine
62
+ if self.db_engine is None:
63
+ logger.warning(
64
+ "No database engine provided; falling back to default temporary SQLite engine. "
65
+ "This is intended for testing only. Consider providing a configured engine for production use."
66
+ )
67
+ self.db_engine = BaseDBManager.create_default_engine()
55
68
 
56
- self.working_memory_monitors: dict[UserID, dict[MemCubeID, MemoryMonitorManager]] = {}
57
- self.activation_memory_monitors: dict[UserID, dict[MemCubeID, MemoryMonitorManager]] = {}
69
+ self.query_monitors: dict[UserID, dict[MemCubeID, DBManagerForQueryMonitorQueue]] = {}
70
+ self.working_memory_monitors: dict[
71
+ UserID, dict[MemCubeID, DBManagerForMemoryMonitorManager]
72
+ ] = {}
73
+ self.activation_memory_monitors: dict[
74
+ UserID, dict[MemCubeID, DBManagerForMemoryMonitorManager]
75
+ ] = {}
58
76
 
59
77
  # Lifecycle monitor
60
78
  self.last_activation_mem_update_time = datetime.min
@@ -96,40 +114,47 @@ class SchedulerGeneralMonitor(BaseSchedulerModule):
96
114
  if user_id not in self.query_monitors:
97
115
  self.query_monitors[user_id] = {}
98
116
  if mem_cube_id not in self.query_monitors[user_id]:
99
- self.query_monitors[user_id][mem_cube_id] = QueryMonitorQueue(
100
- maxsize=self.config.context_window_size
101
- )
117
+ if self.db_engine:
118
+ # Create ORM manager with initial QueryMonitorQueue
119
+ initial_queue = QueryMonitorQueue(maxsize=self.config.context_window_size)
120
+ db_manager = DBManagerForQueryMonitorQueue(
121
+ engine=self.db_engine,
122
+ user_id=str(user_id),
123
+ mem_cube_id=str(mem_cube_id),
124
+ obj=initial_queue,
125
+ )
126
+ self.query_monitors[user_id][mem_cube_id] = db_manager
127
+ else:
128
+ # Fallback to in-memory (this shouldn't happen with proper config)
129
+ logger.warning("ORM persistence disabled, using in-memory fallback")
130
+ # For backward compatibility, we'll need to handle this case differently
131
+ raise RuntimeError("ORM persistence is required but not properly configured")
102
132
 
103
133
  def register_memory_manager_if_not_exists(
104
134
  self,
105
135
  user_id: UserID | str,
106
136
  mem_cube_id: MemCubeID | str,
107
- memory_monitors: dict[UserID, dict[MemCubeID, MemoryMonitorManager]],
137
+ memory_monitors: dict[UserID, dict[MemCubeID, DBManagerForMemoryMonitorManager]],
108
138
  max_capacity: int,
109
139
  ) -> None:
110
140
  """
111
- Register a new MemoryMonitorManager for the given user and memory cube if it doesn't exist.
141
+ Register a new MemoryMonitorManager ORM manager for the given user and memory cube if it doesn't exist.
112
142
  Thread-safe implementation using double-checked locking pattern.
113
143
 
114
- Checks if a MemoryMonitorManager already exists for the specified user_id and mem_cube_id.
115
- If not, creates a new MemoryMonitorManager with appropriate capacity settings and registers it.
144
+ Checks if a MemoryMonitorManager ORM manager already exists for the specified user_id and mem_cube_id.
145
+ If not, creates a new ORM manager with appropriate capacity settings and registers it.
116
146
 
117
147
  Args:
118
148
  user_id: The ID of the user to associate with the memory manager
119
149
  mem_cube_id: The ID of the memory cube to monitor
120
- memory_monitors: Dictionary storing existing memory monitor managers
150
+ memory_monitors: Dictionary storing existing memory monitor ORM managers
121
151
  max_capacity: Maximum capacity for the new memory monitor manager
122
- lock: Threading lock to ensure safe concurrent access
123
-
124
- Note:
125
- This function will update the loose_max_working_memory_capacity based on the current
126
- WorkingMemory size plus partial retention number before creating a new manager.
127
152
  """
128
153
  # First check (lock-free, fast path)
129
154
  # Quickly verify existence without lock overhead
130
155
  if user_id in memory_monitors and mem_cube_id in memory_monitors[user_id]:
131
156
  logger.info(
132
- f"MemoryMonitorManager already exists for user_id={user_id}, "
157
+ f"MemoryMonitorManager ORM manager already exists for user_id={user_id}, "
133
158
  f"mem_cube_id={mem_cube_id} in the provided memory_monitors dictionary"
134
159
  )
135
160
  return
@@ -140,22 +165,33 @@ class SchedulerGeneralMonitor(BaseSchedulerModule):
140
165
  # Re-check after acquiring lock, as another thread might have created it
141
166
  if user_id in memory_monitors and mem_cube_id in memory_monitors[user_id]:
142
167
  logger.info(
143
- f"MemoryMonitorManager already exists for user_id={user_id}, "
168
+ f"MemoryMonitorManager ORM manager already exists for user_id={user_id}, "
144
169
  f"mem_cube_id={mem_cube_id} in the provided memory_monitors dictionary"
145
170
  )
146
171
  return
147
172
 
148
- # Initialize MemoryMonitorManager with user ID, memory cube ID, and max capacity
149
- monitor_manager = MemoryMonitorManager(
150
- user_id=user_id, mem_cube_id=mem_cube_id, max_capacity=max_capacity
151
- )
173
+ if self.db_engine:
174
+ # Initialize MemoryMonitorManager with user ID, memory cube ID, and max capacity
175
+ monitor_manager = MemoryMonitorManager(
176
+ user_id=user_id, mem_cube_id=mem_cube_id, max_capacity=max_capacity
177
+ )
152
178
 
153
- # Safely register the new manager in the nested dictionary structure
154
- memory_monitors.setdefault(user_id, {})[mem_cube_id] = monitor_manager
155
- logger.info(
156
- f"Registered new MemoryMonitorManager for user_id={user_id},"
157
- f" mem_cube_id={mem_cube_id} with max_capacity={max_capacity}"
158
- )
179
+ # Create ORM manager
180
+ db_manager = DBManagerForMemoryMonitorManager(
181
+ engine=self.db_engine,
182
+ user_id=str(user_id),
183
+ mem_cube_id=str(mem_cube_id),
184
+ obj=monitor_manager,
185
+ )
186
+
187
+ # Safely register the new ORM manager in the nested dictionary structure
188
+ memory_monitors.setdefault(user_id, {})[mem_cube_id] = db_manager
189
+ logger.info(
190
+ f"Registered new MemoryMonitorManager ORM manager for user_id={user_id},"
191
+ f" mem_cube_id={mem_cube_id} with max_capacity={max_capacity}"
192
+ )
193
+ else:
194
+ raise RuntimeError("ORM persistence is required but not properly configured")
159
195
 
160
196
  def update_working_memory_monitors(
161
197
  self,
@@ -182,10 +218,14 @@ class SchedulerGeneralMonitor(BaseSchedulerModule):
182
218
  max_capacity=self.working_mem_monitor_capacity,
183
219
  )
184
220
 
185
- self.working_memory_monitors[user_id][mem_cube_id].update_memories(
221
+ # Get the ORM manager and update memories with database sync
222
+ db_manager = self.working_memory_monitors[user_id][mem_cube_id]
223
+ db_manager.obj.update_memories(
186
224
  new_memory_monitors=new_working_memory_monitors,
187
225
  partial_retention_number=self.partial_retention_number,
188
226
  )
227
+ # Sync with database
228
+ db_manager.sync_with_orm(size_limit=self.working_mem_monitor_capacity)
189
229
 
190
230
  def update_activation_memory_monitors(
191
231
  self, user_id: str, mem_cube_id: str, mem_cube: GeneralMemCube
@@ -199,17 +239,21 @@ class SchedulerGeneralMonitor(BaseSchedulerModule):
199
239
 
200
240
  # === update activation memory monitors ===
201
241
  # Sort by importance_score in descending order and take top k
242
+ working_db_manager = self.working_memory_monitors[user_id][mem_cube_id]
202
243
  top_k_memories = sorted(
203
- self.working_memory_monitors[user_id][mem_cube_id].memories,
244
+ working_db_manager.obj.memories,
204
245
  key=lambda m: m.get_importance_score(weight_vector=DEFAULT_WEIGHT_VECTOR_FOR_RANKING),
205
246
  reverse=True,
206
247
  )[: self.activation_mem_monitor_capacity]
207
248
 
208
249
  # Update the activation memory monitors with these important memories
209
- self.activation_memory_monitors[user_id][mem_cube_id].update_memories(
250
+ activation_db_manager = self.activation_memory_monitors[user_id][mem_cube_id]
251
+ activation_db_manager.obj.update_memories(
210
252
  new_memory_monitors=top_k_memories,
211
253
  partial_retention_number=self.partial_retention_number,
212
254
  )
255
+ # Sync with database
256
+ activation_db_manager.sync_with_orm(size_limit=self.activation_mem_monitor_capacity)
213
257
 
214
258
  def timed_trigger(self, last_time: datetime, interval_seconds: float) -> bool:
215
259
  now = datetime.utcnow()
@@ -255,9 +299,12 @@ class SchedulerGeneralMonitor(BaseSchedulerModule):
255
299
  )
256
300
  return []
257
301
 
258
- manager: MemoryMonitorManager = monitor_dict[user_id][mem_cube_id]
302
+ db_manager: DBManagerForMemoryMonitorManager = monitor_dict[user_id][mem_cube_id]
303
+ # Load latest data from database before accessing
304
+ db_manager.sync_with_orm()
305
+
259
306
  # Sort memories by recording_count in descending order and return top_k items
260
- sorted_memory_monitors = manager.get_sorted_mem_monitors(reverse=True)
307
+ sorted_memory_monitors = db_manager.obj.get_sorted_mem_monitors(reverse=True)
261
308
  sorted_text_memories = [m.memory_text for m in sorted_memory_monitors[:top_k]]
262
309
  return sorted_text_memories
263
310
 
@@ -273,16 +320,19 @@ class SchedulerGeneralMonitor(BaseSchedulerModule):
273
320
  return {}
274
321
 
275
322
  info_dict = {}
276
- for manager in [
323
+ for db_manager in [
277
324
  self.working_memory_monitors[user_id][mem_cube_id],
278
325
  self.activation_memory_monitors[user_id][mem_cube_id],
279
326
  ]:
327
+ # Sync with database to get latest data
328
+ db_manager.sync_with_orm()
329
+ manager = db_manager.obj
280
330
  info_dict[str(type(manager))] = {
281
331
  "user_id": user_id,
282
332
  "mem_cube_id": mem_cube_id,
283
333
  "memory_count": manager.memory_size,
284
334
  "max_capacity": manager.max_capacity,
285
- "top_memories": self.get_scheduler_working_memories(user_id, mem_cube_id, top_k=1),
335
+ "top_memories": self.get_monitor_memories(user_id, mem_cube_id, top_k=1),
286
336
  }
287
337
  return info_dict
288
338
 
@@ -308,3 +358,33 @@ class SchedulerGeneralMonitor(BaseSchedulerModule):
308
358
  logger.error(f"Fail to extract json dict from response: {response}")
309
359
  response = {"trigger_retrieval": False, "missing_evidences": q_list}
310
360
  return response
361
+
362
+ def close(self):
363
+ """Close all database connections and clean up resources"""
364
+ logger.info("Closing database connections for all monitors")
365
+
366
+ # Close all query monitor database managers
367
+ for user_monitors in self.query_monitors.values():
368
+ for db_manager in user_monitors.values():
369
+ try:
370
+ db_manager.close()
371
+ except Exception as e:
372
+ logger.error(f"Error closing query monitor DB manager: {e}")
373
+
374
+ # Close all working memory monitor database managers
375
+ for user_monitors in self.working_memory_monitors.values():
376
+ for db_manager in user_monitors.values():
377
+ try:
378
+ db_manager.close()
379
+ except Exception as e:
380
+ logger.error(f"Error closing working memory monitor DB manager: {e}")
381
+
382
+ # Close all activation memory monitor database managers
383
+ for user_monitors in self.activation_memory_monitors.values():
384
+ for db_manager in user_monitors.values():
385
+ try:
386
+ db_manager.close()
387
+ except Exception as e:
388
+ logger.error(f"Error closing activation memory monitor DB manager: {e}")
389
+
390
+ logger.info("All database connections closed")
@@ -0,0 +1,124 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ from memos.configs.mem_scheduler import GeneralSchedulerConfig
4
+ from memos.log import get_logger
5
+ from memos.mem_cube.general import GeneralMemCube
6
+ from memos.mem_scheduler.general_scheduler import GeneralScheduler
7
+ from memos.mem_scheduler.schemas.general_schemas import (
8
+ MemCubeID,
9
+ UserID,
10
+ )
11
+ from memos.memories.textual.tree import TextualMemoryItem, TreeTextMemory
12
+
13
+
14
+ if TYPE_CHECKING:
15
+ from memos.mem_scheduler.schemas.monitor_schemas import MemoryMonitorItem
16
+
17
+
18
+ logger = get_logger(__name__)
19
+
20
+
21
+ class OptimizedScheduler(GeneralScheduler):
22
+ """Optimized scheduler with improved working memory management"""
23
+
24
+ def __init__(self, config: GeneralSchedulerConfig):
25
+ super().__init__(config)
26
+
27
+ def replace_working_memory(
28
+ self,
29
+ user_id: UserID | str,
30
+ mem_cube_id: MemCubeID | str,
31
+ mem_cube: GeneralMemCube,
32
+ original_memory: list[TextualMemoryItem],
33
+ new_memory: list[TextualMemoryItem],
34
+ ) -> None | list[TextualMemoryItem]:
35
+ """Replace working memory with new memories after reranking."""
36
+ text_mem_base = mem_cube.text_mem
37
+ if isinstance(text_mem_base, TreeTextMemory):
38
+ text_mem_base: TreeTextMemory = text_mem_base
39
+
40
+ # process rerank memories with llm
41
+ query_db_manager = self.monitor.query_monitors[user_id][mem_cube_id]
42
+ # Sync with database to get latest query history
43
+ query_db_manager.sync_with_orm()
44
+
45
+ query_history = query_db_manager.obj.get_queries_with_timesort()
46
+ memories_with_new_order, rerank_success_flag = (
47
+ self.retriever.process_and_rerank_memories(
48
+ queries=query_history,
49
+ original_memory=original_memory,
50
+ new_memory=new_memory,
51
+ top_k=self.top_k,
52
+ )
53
+ )
54
+
55
+ # Apply combined filtering (unrelated + redundant)
56
+ logger.info(
57
+ f"Applying combined unrelated and redundant memory filtering to {len(memories_with_new_order)} memories"
58
+ )
59
+ filtered_memories, filtering_success_flag = (
60
+ self.retriever.filter_unrelated_and_redundant_memories(
61
+ query_history=query_history,
62
+ memories=memories_with_new_order,
63
+ )
64
+ )
65
+
66
+ if filtering_success_flag:
67
+ logger.info(
68
+ f"Combined filtering completed successfully. "
69
+ f"Filtered from {len(memories_with_new_order)} to {len(filtered_memories)} memories"
70
+ )
71
+ memories_with_new_order = filtered_memories
72
+ else:
73
+ logger.warning(
74
+ "Combined filtering failed - keeping memories as fallback. "
75
+ f"Count: {len(memories_with_new_order)}"
76
+ )
77
+
78
+ # Update working memory monitors
79
+ query_keywords = query_db_manager.obj.get_keywords_collections()
80
+ logger.info(
81
+ f"Processing {len(memories_with_new_order)} memories with {len(query_keywords)} query keywords"
82
+ )
83
+ new_working_memory_monitors = self.transform_working_memories_to_monitors(
84
+ query_keywords=query_keywords,
85
+ memories=memories_with_new_order,
86
+ )
87
+
88
+ if not rerank_success_flag:
89
+ for one in new_working_memory_monitors:
90
+ one.sorting_score = 0
91
+
92
+ logger.info(f"update {len(new_working_memory_monitors)} working_memory_monitors")
93
+ self.monitor.update_working_memory_monitors(
94
+ new_working_memory_monitors=new_working_memory_monitors,
95
+ user_id=user_id,
96
+ mem_cube_id=mem_cube_id,
97
+ mem_cube=mem_cube,
98
+ )
99
+
100
+ # Use the filtered and reranked memories directly
101
+ text_mem_base.replace_working_memory(memories=memories_with_new_order)
102
+
103
+ # Update monitor after replacing working memory
104
+ mem_monitors: list[MemoryMonitorItem] = self.monitor.working_memory_monitors[user_id][
105
+ mem_cube_id
106
+ ].obj.get_sorted_mem_monitors(reverse=True)
107
+ new_working_memories = [mem_monitor.tree_memory_item for mem_monitor in mem_monitors]
108
+
109
+ logger.info(
110
+ f"The working memory has been replaced with {len(memories_with_new_order)} new memories."
111
+ )
112
+ self.log_working_memory_replacement(
113
+ original_memory=original_memory,
114
+ new_memory=new_working_memories,
115
+ user_id=user_id,
116
+ mem_cube_id=mem_cube_id,
117
+ mem_cube=mem_cube,
118
+ log_func_callback=self._submit_web_logs,
119
+ )
120
+ else:
121
+ logger.error("memory_base is not supported")
122
+ memories_with_new_order = new_memory
123
+
124
+ return memories_with_new_order
File without changes