MemoryOS 2.0.3__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.
Files changed (315) hide show
  1. memoryos-2.0.3.dist-info/METADATA +418 -0
  2. memoryos-2.0.3.dist-info/RECORD +315 -0
  3. memoryos-2.0.3.dist-info/WHEEL +4 -0
  4. memoryos-2.0.3.dist-info/entry_points.txt +3 -0
  5. memoryos-2.0.3.dist-info/licenses/LICENSE +201 -0
  6. memos/__init__.py +20 -0
  7. memos/api/client.py +571 -0
  8. memos/api/config.py +1018 -0
  9. memos/api/context/dependencies.py +50 -0
  10. memos/api/exceptions.py +53 -0
  11. memos/api/handlers/__init__.py +62 -0
  12. memos/api/handlers/add_handler.py +158 -0
  13. memos/api/handlers/base_handler.py +194 -0
  14. memos/api/handlers/chat_handler.py +1401 -0
  15. memos/api/handlers/component_init.py +388 -0
  16. memos/api/handlers/config_builders.py +190 -0
  17. memos/api/handlers/feedback_handler.py +93 -0
  18. memos/api/handlers/formatters_handler.py +237 -0
  19. memos/api/handlers/memory_handler.py +316 -0
  20. memos/api/handlers/scheduler_handler.py +497 -0
  21. memos/api/handlers/search_handler.py +222 -0
  22. memos/api/handlers/suggestion_handler.py +117 -0
  23. memos/api/mcp_serve.py +614 -0
  24. memos/api/middleware/request_context.py +101 -0
  25. memos/api/product_api.py +38 -0
  26. memos/api/product_models.py +1206 -0
  27. memos/api/routers/__init__.py +1 -0
  28. memos/api/routers/product_router.py +477 -0
  29. memos/api/routers/server_router.py +394 -0
  30. memos/api/server_api.py +44 -0
  31. memos/api/start_api.py +433 -0
  32. memos/chunkers/__init__.py +4 -0
  33. memos/chunkers/base.py +24 -0
  34. memos/chunkers/charactertext_chunker.py +41 -0
  35. memos/chunkers/factory.py +24 -0
  36. memos/chunkers/markdown_chunker.py +62 -0
  37. memos/chunkers/sentence_chunker.py +54 -0
  38. memos/chunkers/simple_chunker.py +50 -0
  39. memos/cli.py +113 -0
  40. memos/configs/__init__.py +0 -0
  41. memos/configs/base.py +82 -0
  42. memos/configs/chunker.py +59 -0
  43. memos/configs/embedder.py +88 -0
  44. memos/configs/graph_db.py +236 -0
  45. memos/configs/internet_retriever.py +100 -0
  46. memos/configs/llm.py +151 -0
  47. memos/configs/mem_agent.py +54 -0
  48. memos/configs/mem_chat.py +81 -0
  49. memos/configs/mem_cube.py +105 -0
  50. memos/configs/mem_os.py +83 -0
  51. memos/configs/mem_reader.py +91 -0
  52. memos/configs/mem_scheduler.py +385 -0
  53. memos/configs/mem_user.py +70 -0
  54. memos/configs/memory.py +324 -0
  55. memos/configs/parser.py +38 -0
  56. memos/configs/reranker.py +18 -0
  57. memos/configs/utils.py +8 -0
  58. memos/configs/vec_db.py +80 -0
  59. memos/context/context.py +355 -0
  60. memos/dependency.py +52 -0
  61. memos/deprecation.py +262 -0
  62. memos/embedders/__init__.py +0 -0
  63. memos/embedders/ark.py +95 -0
  64. memos/embedders/base.py +106 -0
  65. memos/embedders/factory.py +29 -0
  66. memos/embedders/ollama.py +77 -0
  67. memos/embedders/sentence_transformer.py +49 -0
  68. memos/embedders/universal_api.py +51 -0
  69. memos/exceptions.py +30 -0
  70. memos/graph_dbs/__init__.py +0 -0
  71. memos/graph_dbs/base.py +274 -0
  72. memos/graph_dbs/factory.py +27 -0
  73. memos/graph_dbs/item.py +46 -0
  74. memos/graph_dbs/nebular.py +1794 -0
  75. memos/graph_dbs/neo4j.py +1942 -0
  76. memos/graph_dbs/neo4j_community.py +1058 -0
  77. memos/graph_dbs/polardb.py +5446 -0
  78. memos/hello_world.py +97 -0
  79. memos/llms/__init__.py +0 -0
  80. memos/llms/base.py +25 -0
  81. memos/llms/deepseek.py +13 -0
  82. memos/llms/factory.py +38 -0
  83. memos/llms/hf.py +443 -0
  84. memos/llms/hf_singleton.py +114 -0
  85. memos/llms/ollama.py +135 -0
  86. memos/llms/openai.py +222 -0
  87. memos/llms/openai_new.py +198 -0
  88. memos/llms/qwen.py +13 -0
  89. memos/llms/utils.py +14 -0
  90. memos/llms/vllm.py +218 -0
  91. memos/log.py +237 -0
  92. memos/mem_agent/base.py +19 -0
  93. memos/mem_agent/deepsearch_agent.py +391 -0
  94. memos/mem_agent/factory.py +36 -0
  95. memos/mem_chat/__init__.py +0 -0
  96. memos/mem_chat/base.py +30 -0
  97. memos/mem_chat/factory.py +21 -0
  98. memos/mem_chat/simple.py +200 -0
  99. memos/mem_cube/__init__.py +0 -0
  100. memos/mem_cube/base.py +30 -0
  101. memos/mem_cube/general.py +240 -0
  102. memos/mem_cube/navie.py +172 -0
  103. memos/mem_cube/utils.py +169 -0
  104. memos/mem_feedback/base.py +15 -0
  105. memos/mem_feedback/feedback.py +1192 -0
  106. memos/mem_feedback/simple_feedback.py +40 -0
  107. memos/mem_feedback/utils.py +230 -0
  108. memos/mem_os/client.py +5 -0
  109. memos/mem_os/core.py +1203 -0
  110. memos/mem_os/main.py +582 -0
  111. memos/mem_os/product.py +1608 -0
  112. memos/mem_os/product_server.py +455 -0
  113. memos/mem_os/utils/default_config.py +359 -0
  114. memos/mem_os/utils/format_utils.py +1403 -0
  115. memos/mem_os/utils/reference_utils.py +162 -0
  116. memos/mem_reader/__init__.py +0 -0
  117. memos/mem_reader/base.py +47 -0
  118. memos/mem_reader/factory.py +53 -0
  119. memos/mem_reader/memory.py +298 -0
  120. memos/mem_reader/multi_modal_struct.py +965 -0
  121. memos/mem_reader/read_multi_modal/__init__.py +43 -0
  122. memos/mem_reader/read_multi_modal/assistant_parser.py +311 -0
  123. memos/mem_reader/read_multi_modal/base.py +273 -0
  124. memos/mem_reader/read_multi_modal/file_content_parser.py +826 -0
  125. memos/mem_reader/read_multi_modal/image_parser.py +359 -0
  126. memos/mem_reader/read_multi_modal/multi_modal_parser.py +252 -0
  127. memos/mem_reader/read_multi_modal/string_parser.py +139 -0
  128. memos/mem_reader/read_multi_modal/system_parser.py +327 -0
  129. memos/mem_reader/read_multi_modal/text_content_parser.py +131 -0
  130. memos/mem_reader/read_multi_modal/tool_parser.py +210 -0
  131. memos/mem_reader/read_multi_modal/user_parser.py +218 -0
  132. memos/mem_reader/read_multi_modal/utils.py +358 -0
  133. memos/mem_reader/simple_struct.py +912 -0
  134. memos/mem_reader/strategy_struct.py +163 -0
  135. memos/mem_reader/utils.py +157 -0
  136. memos/mem_scheduler/__init__.py +0 -0
  137. memos/mem_scheduler/analyzer/__init__.py +0 -0
  138. memos/mem_scheduler/analyzer/api_analyzer.py +714 -0
  139. memos/mem_scheduler/analyzer/eval_analyzer.py +219 -0
  140. memos/mem_scheduler/analyzer/mos_for_test_scheduler.py +571 -0
  141. memos/mem_scheduler/analyzer/scheduler_for_eval.py +280 -0
  142. memos/mem_scheduler/base_scheduler.py +1319 -0
  143. memos/mem_scheduler/general_modules/__init__.py +0 -0
  144. memos/mem_scheduler/general_modules/api_misc.py +137 -0
  145. memos/mem_scheduler/general_modules/base.py +80 -0
  146. memos/mem_scheduler/general_modules/init_components_for_scheduler.py +425 -0
  147. memos/mem_scheduler/general_modules/misc.py +313 -0
  148. memos/mem_scheduler/general_modules/scheduler_logger.py +389 -0
  149. memos/mem_scheduler/general_modules/task_threads.py +315 -0
  150. memos/mem_scheduler/general_scheduler.py +1495 -0
  151. memos/mem_scheduler/memory_manage_modules/__init__.py +5 -0
  152. memos/mem_scheduler/memory_manage_modules/memory_filter.py +306 -0
  153. memos/mem_scheduler/memory_manage_modules/retriever.py +547 -0
  154. memos/mem_scheduler/monitors/__init__.py +0 -0
  155. memos/mem_scheduler/monitors/dispatcher_monitor.py +366 -0
  156. memos/mem_scheduler/monitors/general_monitor.py +394 -0
  157. memos/mem_scheduler/monitors/task_schedule_monitor.py +254 -0
  158. memos/mem_scheduler/optimized_scheduler.py +410 -0
  159. memos/mem_scheduler/orm_modules/__init__.py +0 -0
  160. memos/mem_scheduler/orm_modules/api_redis_model.py +518 -0
  161. memos/mem_scheduler/orm_modules/base_model.py +729 -0
  162. memos/mem_scheduler/orm_modules/monitor_models.py +261 -0
  163. memos/mem_scheduler/orm_modules/redis_model.py +699 -0
  164. memos/mem_scheduler/scheduler_factory.py +23 -0
  165. memos/mem_scheduler/schemas/__init__.py +0 -0
  166. memos/mem_scheduler/schemas/analyzer_schemas.py +52 -0
  167. memos/mem_scheduler/schemas/api_schemas.py +233 -0
  168. memos/mem_scheduler/schemas/general_schemas.py +55 -0
  169. memos/mem_scheduler/schemas/message_schemas.py +173 -0
  170. memos/mem_scheduler/schemas/monitor_schemas.py +406 -0
  171. memos/mem_scheduler/schemas/task_schemas.py +132 -0
  172. memos/mem_scheduler/task_schedule_modules/__init__.py +0 -0
  173. memos/mem_scheduler/task_schedule_modules/dispatcher.py +740 -0
  174. memos/mem_scheduler/task_schedule_modules/local_queue.py +247 -0
  175. memos/mem_scheduler/task_schedule_modules/orchestrator.py +74 -0
  176. memos/mem_scheduler/task_schedule_modules/redis_queue.py +1385 -0
  177. memos/mem_scheduler/task_schedule_modules/task_queue.py +162 -0
  178. memos/mem_scheduler/utils/__init__.py +0 -0
  179. memos/mem_scheduler/utils/api_utils.py +77 -0
  180. memos/mem_scheduler/utils/config_utils.py +100 -0
  181. memos/mem_scheduler/utils/db_utils.py +50 -0
  182. memos/mem_scheduler/utils/filter_utils.py +176 -0
  183. memos/mem_scheduler/utils/metrics.py +125 -0
  184. memos/mem_scheduler/utils/misc_utils.py +290 -0
  185. memos/mem_scheduler/utils/monitor_event_utils.py +67 -0
  186. memos/mem_scheduler/utils/status_tracker.py +229 -0
  187. memos/mem_scheduler/webservice_modules/__init__.py +0 -0
  188. memos/mem_scheduler/webservice_modules/rabbitmq_service.py +485 -0
  189. memos/mem_scheduler/webservice_modules/redis_service.py +380 -0
  190. memos/mem_user/factory.py +94 -0
  191. memos/mem_user/mysql_persistent_user_manager.py +271 -0
  192. memos/mem_user/mysql_user_manager.py +502 -0
  193. memos/mem_user/persistent_factory.py +98 -0
  194. memos/mem_user/persistent_user_manager.py +260 -0
  195. memos/mem_user/redis_persistent_user_manager.py +225 -0
  196. memos/mem_user/user_manager.py +488 -0
  197. memos/memories/__init__.py +0 -0
  198. memos/memories/activation/__init__.py +0 -0
  199. memos/memories/activation/base.py +42 -0
  200. memos/memories/activation/item.py +56 -0
  201. memos/memories/activation/kv.py +292 -0
  202. memos/memories/activation/vllmkv.py +219 -0
  203. memos/memories/base.py +19 -0
  204. memos/memories/factory.py +42 -0
  205. memos/memories/parametric/__init__.py +0 -0
  206. memos/memories/parametric/base.py +19 -0
  207. memos/memories/parametric/item.py +11 -0
  208. memos/memories/parametric/lora.py +41 -0
  209. memos/memories/textual/__init__.py +0 -0
  210. memos/memories/textual/base.py +92 -0
  211. memos/memories/textual/general.py +236 -0
  212. memos/memories/textual/item.py +304 -0
  213. memos/memories/textual/naive.py +187 -0
  214. memos/memories/textual/prefer_text_memory/__init__.py +0 -0
  215. memos/memories/textual/prefer_text_memory/adder.py +504 -0
  216. memos/memories/textual/prefer_text_memory/config.py +106 -0
  217. memos/memories/textual/prefer_text_memory/extractor.py +221 -0
  218. memos/memories/textual/prefer_text_memory/factory.py +85 -0
  219. memos/memories/textual/prefer_text_memory/retrievers.py +177 -0
  220. memos/memories/textual/prefer_text_memory/spliter.py +132 -0
  221. memos/memories/textual/prefer_text_memory/utils.py +93 -0
  222. memos/memories/textual/preference.py +344 -0
  223. memos/memories/textual/simple_preference.py +161 -0
  224. memos/memories/textual/simple_tree.py +69 -0
  225. memos/memories/textual/tree.py +459 -0
  226. memos/memories/textual/tree_text_memory/__init__.py +0 -0
  227. memos/memories/textual/tree_text_memory/organize/__init__.py +0 -0
  228. memos/memories/textual/tree_text_memory/organize/handler.py +184 -0
  229. memos/memories/textual/tree_text_memory/organize/manager.py +518 -0
  230. memos/memories/textual/tree_text_memory/organize/relation_reason_detector.py +238 -0
  231. memos/memories/textual/tree_text_memory/organize/reorganizer.py +622 -0
  232. memos/memories/textual/tree_text_memory/retrieve/__init__.py +0 -0
  233. memos/memories/textual/tree_text_memory/retrieve/advanced_searcher.py +364 -0
  234. memos/memories/textual/tree_text_memory/retrieve/bm25_util.py +186 -0
  235. memos/memories/textual/tree_text_memory/retrieve/bochasearch.py +419 -0
  236. memos/memories/textual/tree_text_memory/retrieve/internet_retriever.py +270 -0
  237. memos/memories/textual/tree_text_memory/retrieve/internet_retriever_factory.py +102 -0
  238. memos/memories/textual/tree_text_memory/retrieve/reasoner.py +61 -0
  239. memos/memories/textual/tree_text_memory/retrieve/recall.py +497 -0
  240. memos/memories/textual/tree_text_memory/retrieve/reranker.py +111 -0
  241. memos/memories/textual/tree_text_memory/retrieve/retrieval_mid_structs.py +16 -0
  242. memos/memories/textual/tree_text_memory/retrieve/retrieve_utils.py +472 -0
  243. memos/memories/textual/tree_text_memory/retrieve/searcher.py +848 -0
  244. memos/memories/textual/tree_text_memory/retrieve/task_goal_parser.py +135 -0
  245. memos/memories/textual/tree_text_memory/retrieve/utils.py +54 -0
  246. memos/memories/textual/tree_text_memory/retrieve/xinyusearch.py +387 -0
  247. memos/memos_tools/dinding_report_bot.py +453 -0
  248. memos/memos_tools/lockfree_dict.py +120 -0
  249. memos/memos_tools/notification_service.py +44 -0
  250. memos/memos_tools/notification_utils.py +142 -0
  251. memos/memos_tools/singleton.py +174 -0
  252. memos/memos_tools/thread_safe_dict.py +310 -0
  253. memos/memos_tools/thread_safe_dict_segment.py +382 -0
  254. memos/multi_mem_cube/__init__.py +0 -0
  255. memos/multi_mem_cube/composite_cube.py +86 -0
  256. memos/multi_mem_cube/single_cube.py +874 -0
  257. memos/multi_mem_cube/views.py +54 -0
  258. memos/parsers/__init__.py +0 -0
  259. memos/parsers/base.py +15 -0
  260. memos/parsers/factory.py +21 -0
  261. memos/parsers/markitdown.py +28 -0
  262. memos/reranker/__init__.py +4 -0
  263. memos/reranker/base.py +25 -0
  264. memos/reranker/concat.py +103 -0
  265. memos/reranker/cosine_local.py +102 -0
  266. memos/reranker/factory.py +72 -0
  267. memos/reranker/http_bge.py +324 -0
  268. memos/reranker/http_bge_strategy.py +327 -0
  269. memos/reranker/noop.py +19 -0
  270. memos/reranker/strategies/__init__.py +4 -0
  271. memos/reranker/strategies/base.py +61 -0
  272. memos/reranker/strategies/concat_background.py +94 -0
  273. memos/reranker/strategies/concat_docsource.py +110 -0
  274. memos/reranker/strategies/dialogue_common.py +109 -0
  275. memos/reranker/strategies/factory.py +31 -0
  276. memos/reranker/strategies/single_turn.py +107 -0
  277. memos/reranker/strategies/singleturn_outmem.py +98 -0
  278. memos/settings.py +10 -0
  279. memos/templates/__init__.py +0 -0
  280. memos/templates/advanced_search_prompts.py +211 -0
  281. memos/templates/cloud_service_prompt.py +107 -0
  282. memos/templates/instruction_completion.py +66 -0
  283. memos/templates/mem_agent_prompts.py +85 -0
  284. memos/templates/mem_feedback_prompts.py +822 -0
  285. memos/templates/mem_reader_prompts.py +1096 -0
  286. memos/templates/mem_reader_strategy_prompts.py +238 -0
  287. memos/templates/mem_scheduler_prompts.py +626 -0
  288. memos/templates/mem_search_prompts.py +93 -0
  289. memos/templates/mos_prompts.py +403 -0
  290. memos/templates/prefer_complete_prompt.py +735 -0
  291. memos/templates/tool_mem_prompts.py +139 -0
  292. memos/templates/tree_reorganize_prompts.py +230 -0
  293. memos/types/__init__.py +34 -0
  294. memos/types/general_types.py +151 -0
  295. memos/types/openai_chat_completion_types/__init__.py +15 -0
  296. memos/types/openai_chat_completion_types/chat_completion_assistant_message_param.py +56 -0
  297. memos/types/openai_chat_completion_types/chat_completion_content_part_image_param.py +27 -0
  298. memos/types/openai_chat_completion_types/chat_completion_content_part_input_audio_param.py +23 -0
  299. memos/types/openai_chat_completion_types/chat_completion_content_part_param.py +43 -0
  300. memos/types/openai_chat_completion_types/chat_completion_content_part_refusal_param.py +16 -0
  301. memos/types/openai_chat_completion_types/chat_completion_content_part_text_param.py +16 -0
  302. memos/types/openai_chat_completion_types/chat_completion_message_custom_tool_call_param.py +27 -0
  303. memos/types/openai_chat_completion_types/chat_completion_message_function_tool_call_param.py +32 -0
  304. memos/types/openai_chat_completion_types/chat_completion_message_param.py +18 -0
  305. memos/types/openai_chat_completion_types/chat_completion_message_tool_call_union_param.py +15 -0
  306. memos/types/openai_chat_completion_types/chat_completion_system_message_param.py +36 -0
  307. memos/types/openai_chat_completion_types/chat_completion_tool_message_param.py +30 -0
  308. memos/types/openai_chat_completion_types/chat_completion_user_message_param.py +34 -0
  309. memos/utils.py +123 -0
  310. memos/vec_dbs/__init__.py +0 -0
  311. memos/vec_dbs/base.py +117 -0
  312. memos/vec_dbs/factory.py +23 -0
  313. memos/vec_dbs/item.py +50 -0
  314. memos/vec_dbs/milvus.py +654 -0
  315. memos/vec_dbs/qdrant.py +355 -0
@@ -0,0 +1,280 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+
5
+ from functools import wraps
6
+ from typing import TYPE_CHECKING, Any, ClassVar
7
+
8
+ from memos.log import get_logger
9
+ from memos.mem_scheduler.general_scheduler import GeneralScheduler
10
+ from memos.mem_scheduler.schemas.monitor_schemas import QueryMonitorItem
11
+ from memos.mem_scheduler.schemas.task_schemas import (
12
+ DEFAULT_MAX_QUERY_KEY_WORDS,
13
+ )
14
+
15
+
16
+ if TYPE_CHECKING:
17
+ from memos.memories.textual.tree import TextualMemoryItem
18
+ from memos.types import UserID
19
+
20
+
21
+ logger = get_logger(__name__)
22
+
23
+
24
+ class SchedulerForEval(GeneralScheduler):
25
+ """
26
+ A scheduler class that inherits from GeneralScheduler and provides evaluation-specific functionality.
27
+ This class extends GeneralScheduler with evaluation methods.
28
+ """
29
+
30
+ # Class variable to store timing information for all instances
31
+ timer_cache: ClassVar[dict[str, dict[str, Any]]] = {}
32
+
33
+ def __init__(self, config):
34
+ """
35
+ Initialize the SchedulerForEval with the same configuration as GeneralScheduler.
36
+
37
+ Args:
38
+ config: Configuration object for the scheduler
39
+ """
40
+ super().__init__(config)
41
+ # Initialize instance timer_cache
42
+ self.timer_cache = {}
43
+
44
+ @staticmethod
45
+ def time_it(func_name: str | None = None):
46
+ """
47
+ Static method decorator to measure function execution time and store in timer_cache.
48
+
49
+ Args:
50
+ func_name: Custom name for the function in timer_cache. If None, uses function.__name__
51
+ """
52
+
53
+ def decorator(func):
54
+ @wraps(func)
55
+ def wrapper(self, *args, **kwargs):
56
+ # Get function name
57
+ name = func_name or func.__name__
58
+
59
+ # Start timing
60
+ start_time = time.time()
61
+ result = func(self, *args, **kwargs)
62
+ end_time = time.time()
63
+
64
+ # Calculate execution time
65
+ exec_time = end_time - start_time
66
+
67
+ # Format time as HH:MM:SS.mmm
68
+ hours = int(exec_time // 3600)
69
+ minutes = int((exec_time % 3600) // 60)
70
+ seconds = exec_time % 60
71
+
72
+ if hours > 0:
73
+ time_str = f"{hours:02d}:{minutes:02d}:{seconds:06.3f}"
74
+ else:
75
+ time_str = f"{minutes:02d}:{seconds:06.3f}"
76
+
77
+ # Store in timer_cache
78
+ if not hasattr(self, "timer_cache"):
79
+ self.timer_cache = {}
80
+
81
+ self.timer_cache[name] = {
82
+ "time_str": time_str,
83
+ "seconds": exec_time,
84
+ }
85
+
86
+ logger.info(f"{name} executed in {time_str}")
87
+ return result
88
+
89
+ return wrapper
90
+
91
+ return decorator
92
+
93
+ def get_timer_summary(self) -> str:
94
+ """
95
+ Get a summary of all timed functions.
96
+
97
+ Returns:
98
+ Formatted string with timing information
99
+ """
100
+ if not self.timer_cache:
101
+ return "No timing data available."
102
+
103
+ summary = "=== Timing Summary ===\n"
104
+ for func_name, data in self.timer_cache.items():
105
+ summary += f"{func_name}: {data['time_str']} (at {data['timestamp']})\n"
106
+
107
+ return summary
108
+
109
+ def clear_timer_cache(self):
110
+ """Clear the timer cache."""
111
+ self.timer_cache.clear()
112
+
113
+ @time_it("update_working_memory")
114
+ def update_working_memory_for_eval(
115
+ self, query: str, user_id: UserID | str, top_k: int
116
+ ) -> list[str]:
117
+ """
118
+ Update working memory based on query and return the updated memory list.
119
+
120
+ Args:
121
+ query: The query string
122
+ user_id: User identifier
123
+ top_k: Number of top memories to return
124
+
125
+ Returns:
126
+ List of memory strings from updated working memory
127
+ """
128
+ self.monitor.register_query_monitor_if_not_exists(
129
+ user_id=user_id, mem_cube_id=self.current_mem_cube_id
130
+ )
131
+
132
+ query_keywords = self.monitor.extract_query_keywords(query=query)
133
+ logger.info(f'Extract keywords "{query_keywords}" from query "{query}"')
134
+
135
+ item = QueryMonitorItem(
136
+ user_id=user_id,
137
+ mem_cube_id=self.current_mem_cube_id,
138
+ query_text=query,
139
+ keywords=query_keywords,
140
+ max_keywords=DEFAULT_MAX_QUERY_KEY_WORDS,
141
+ )
142
+ query_db_manager = self.monitor.query_monitors[user_id][self.current_mem_cube_id]
143
+ query_db_manager.obj.put(item=item)
144
+ # Sync with database after adding new item
145
+ query_db_manager.sync_with_orm()
146
+ logger.debug(f"Queries in monitor are {query_db_manager.obj.get_queries_with_timesort()}.")
147
+
148
+ queries = [query]
149
+
150
+ # recall
151
+ mem_cube = self.current_mem_cube
152
+ text_mem_base = mem_cube.text_mem
153
+
154
+ cur_working_memory: list[TextualMemoryItem] = text_mem_base.get_working_memory()
155
+ text_working_memory: list[str] = [w_m.memory for w_m in cur_working_memory]
156
+ intent_result = self.monitor.detect_intent(
157
+ q_list=queries, text_working_memory=text_working_memory
158
+ )
159
+
160
+ if intent_result["trigger_retrieval"]:
161
+ missing_evidences = intent_result["missing_evidences"]
162
+ num_evidence = len(missing_evidences)
163
+ k_per_evidence = max(1, top_k // max(1, num_evidence))
164
+ new_candidates = []
165
+ for item in missing_evidences:
166
+ logger.info(f"missing_evidences: {item}")
167
+ results: list[TextualMemoryItem] = self.retriever.search(
168
+ query=item,
169
+ mem_cube=mem_cube,
170
+ top_k=k_per_evidence,
171
+ method=self.search_method,
172
+ )
173
+ logger.info(
174
+ f"search results for {missing_evidences}: {[one.memory for one in results]}"
175
+ )
176
+ new_candidates.extend(results)
177
+ logger.info(
178
+ f"missing_evidences: {missing_evidences} and get {len(new_candidates)} new candidate memories."
179
+ )
180
+ else:
181
+ new_candidates = []
182
+ logger.info(f"intent_result: {intent_result}. not triggered")
183
+
184
+ # rerank
185
+ new_order_working_memory = self.replace_working_memory(
186
+ user_id=user_id,
187
+ mem_cube_id=self.current_mem_cube_id,
188
+ mem_cube=self.current_mem_cube,
189
+ original_memory=cur_working_memory,
190
+ new_memory=new_candidates,
191
+ )
192
+ new_order_working_memory = new_order_working_memory[:top_k]
193
+ logger.info(f"size of new_order_working_memory: {len(new_order_working_memory)}")
194
+
195
+ return [m.memory for m in new_order_working_memory]
196
+
197
+ @time_it("memory_answer_ability")
198
+ def evaluate_memory_answer_ability(
199
+ self, query: str, memory_texts: list[str], top_k: int = 100
200
+ ) -> bool:
201
+ """
202
+ Use LLM to evaluate whether the given memories can answer the query.
203
+
204
+ Args:
205
+ query: The query string to evaluate
206
+ memory_texts: List of memory texts to check against
207
+ top_k: Maximum number of memories to consider for evaluation
208
+
209
+ Returns:
210
+ Boolean indicating whether the memories can answer the query
211
+ """
212
+ # Limit the number of memories to evaluate
213
+ limited_memories = memory_texts[:top_k] if memory_texts else []
214
+
215
+ # Build prompt using the template
216
+ prompt = self.monitor.build_prompt(
217
+ template_name="memory_answer_ability_evaluation",
218
+ query=query,
219
+ memory_list="\n".join([f"- {memory}" for memory in limited_memories])
220
+ if limited_memories
221
+ else "No memories available",
222
+ )
223
+
224
+ # Use the process LLM to generate response
225
+ response = self.monitor._process_llm.generate([{"role": "user", "content": prompt}])
226
+
227
+ try:
228
+ # Extract JSON response
229
+ from memos.mem_scheduler.utils.misc_utils import extract_json_obj
230
+
231
+ result = extract_json_obj(response)
232
+
233
+ # Validate response structure
234
+ if "result" in result:
235
+ logger.info(
236
+ f"Memory answer ability evaluation result: {result['result']}, reason: {result.get('reason', 'No reason provided')}"
237
+ )
238
+ return result["result"]
239
+ else:
240
+ logger.warning(f"Invalid response structure from LLM: {result}")
241
+ return False
242
+
243
+ except Exception as e:
244
+ logger.error(
245
+ f"Failed to parse LLM response for memory answer ability evaluation: {response}. Error: {e}"
246
+ )
247
+ # Fallback: return False if we can't determine answer ability
248
+ return False
249
+
250
+ @time_it("search_for_eval")
251
+ def search_for_eval(
252
+ self, query: str, user_id: UserID | str, top_k: int, scheduler_flag: bool = True
253
+ ) -> list[str]:
254
+ """
255
+ Original search_for_eval function refactored to use the new decomposed functions.
256
+
257
+ Args:
258
+ query: The query string
259
+ user_id: User identifier
260
+ top_k: Number of top memories to return
261
+ scheduler_flag: Whether to update working memory or just evaluate
262
+
263
+ Returns:
264
+ Tuple of (memory_list, can_answer_boolean)
265
+ """
266
+ if not scheduler_flag:
267
+ # Get current working memory without updating
268
+ mem_cube = self.current_mem_cube
269
+ text_mem_base = mem_cube.text_mem
270
+ cur_working_memory: list[TextualMemoryItem] = text_mem_base.get_working_memory()
271
+ text_working_memory: list[str] = [w_m.memory for w_m in cur_working_memory]
272
+
273
+ return text_working_memory
274
+ else:
275
+ # Update working memory and get the result
276
+ updated_memories = self.update_working_memory_for_eval(
277
+ query=query, user_id=user_id, top_k=top_k
278
+ )
279
+
280
+ return updated_memories