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
File without changes
@@ -0,0 +1,137 @@
1
+ from typing import Any
2
+
3
+ from memos.log import get_logger
4
+ from memos.mem_scheduler.general_modules.base import BaseSchedulerModule
5
+ from memos.mem_scheduler.orm_modules.api_redis_model import APIRedisDBManager
6
+ from memos.mem_scheduler.schemas.api_schemas import (
7
+ APIMemoryHistoryEntryItem,
8
+ APISearchHistoryManager,
9
+ TaskRunningStatus,
10
+ )
11
+ from memos.memories.textual.item import TextualMemoryItem
12
+
13
+
14
+ logger = get_logger(__name__)
15
+
16
+
17
+ class SchedulerAPIModule(BaseSchedulerModule):
18
+ def __init__(self, window_size: int | None = None, history_memory_turns: int | None = None):
19
+ super().__init__()
20
+ self.window_size = window_size
21
+ self.history_memory_turns = history_memory_turns
22
+ self.search_history_managers: dict[str, APIRedisDBManager] = {}
23
+
24
+ def get_search_history_manager(self, user_id: str, mem_cube_id: str) -> APIRedisDBManager:
25
+ """Get or create a Redis manager for search history."""
26
+ logger.info(
27
+ f"Getting search history manager for user_id: {user_id}, mem_cube_id: {mem_cube_id}"
28
+ )
29
+ key = f"search_history:{user_id}:{mem_cube_id}"
30
+ if key not in self.search_history_managers:
31
+ logger.info(f"Creating new search history manager for key: {key}")
32
+ self.search_history_managers[key] = APIRedisDBManager(
33
+ user_id=user_id,
34
+ mem_cube_id=mem_cube_id,
35
+ obj=APISearchHistoryManager(window_size=self.window_size),
36
+ )
37
+ return self.search_history_managers[key]
38
+
39
+ def sync_search_data(
40
+ self,
41
+ item_id: str,
42
+ user_id: str,
43
+ mem_cube_id: str,
44
+ query: str,
45
+ memories: list[TextualMemoryItem],
46
+ formatted_memories: Any,
47
+ session_id: str | None = None,
48
+ conversation_turn: int = 0,
49
+ ) -> Any:
50
+ logger.info(
51
+ f"Syncing search data for item_id: {item_id}, user_id: {user_id}, mem_cube_id: {mem_cube_id}"
52
+ )
53
+ # Get the search history manager
54
+ manager = self.get_search_history_manager(user_id, mem_cube_id)
55
+ manager.sync_with_redis(size_limit=self.window_size)
56
+
57
+ search_history = manager.obj
58
+
59
+ # Check if entry with item_id already exists
60
+ existing_entry, location = search_history.find_entry_by_item_id(item_id)
61
+
62
+ if existing_entry is not None:
63
+ # Update existing entry
64
+ success = search_history.update_entry_by_item_id(
65
+ item_id=item_id,
66
+ query=query,
67
+ formatted_memories=formatted_memories,
68
+ task_status=TaskRunningStatus.COMPLETED, # Use the provided running_status
69
+ session_id=session_id,
70
+ memories=memories,
71
+ )
72
+
73
+ if success:
74
+ logger.info(f"Updated existing entry with item_id: {item_id} in {location} list")
75
+ else:
76
+ logger.warning(f"Failed to update entry with item_id: {item_id}")
77
+ else:
78
+ # Add new entry based on running_status
79
+ entry_item = APIMemoryHistoryEntryItem(
80
+ item_id=item_id,
81
+ query=query,
82
+ formatted_memories=formatted_memories,
83
+ memories=memories,
84
+ task_status=TaskRunningStatus.COMPLETED,
85
+ session_id=session_id,
86
+ conversation_turn=conversation_turn,
87
+ )
88
+
89
+ # Add directly to completed list as APIMemoryHistoryEntryItem instance
90
+ search_history.completed_entries.append(entry_item)
91
+
92
+ # Maintain window size
93
+ if len(search_history.completed_entries) > search_history.window_size:
94
+ search_history.completed_entries = search_history.completed_entries[
95
+ -search_history.window_size :
96
+ ]
97
+
98
+ # Remove from running task IDs
99
+ if item_id in search_history.running_item_ids:
100
+ search_history.running_item_ids.remove(item_id)
101
+
102
+ logger.info(f"Created new entry with item_id: {item_id}")
103
+
104
+ # Update manager's object with the modified search history
105
+ manager.obj = search_history
106
+
107
+ # Use sync_with_redis to handle Redis synchronization with merging
108
+ manager.sync_with_redis(size_limit=self.window_size)
109
+ return manager
110
+
111
+ def get_history_memories(
112
+ self, user_id: str, mem_cube_id: str, turns: int | None = None
113
+ ) -> list:
114
+ """Get history memories for backward compatibility with tests."""
115
+ logger.info(
116
+ f"Getting history memories for user_id: {user_id}, mem_cube_id: {mem_cube_id}, turns: {turns}"
117
+ )
118
+ manager = self.get_search_history_manager(user_id, mem_cube_id)
119
+ existing_data = manager.load_from_db()
120
+
121
+ if existing_data is None:
122
+ return []
123
+
124
+ if turns is None:
125
+ turns = self.history_memory_turns
126
+
127
+ # Handle different data formats
128
+ if isinstance(existing_data, APISearchHistoryManager):
129
+ search_history = existing_data
130
+ else:
131
+ # Try to convert to APISearchHistoryManager
132
+ try:
133
+ search_history = APISearchHistoryManager(**existing_data)
134
+ except Exception:
135
+ return []
136
+
137
+ return search_history.get_history_memories(turns=turns)
@@ -0,0 +1,80 @@
1
+ from pathlib import Path
2
+
3
+ from memos.llms.base import BaseLLM
4
+ from memos.log import get_logger
5
+ from memos.mem_cube.general import GeneralMemCube
6
+ from memos.mem_scheduler.schemas.general_schemas import BASE_DIR
7
+ from memos.templates.mem_scheduler_prompts import PROMPT_MAPPING
8
+
9
+
10
+ logger = get_logger(__name__)
11
+
12
+
13
+ class BaseSchedulerModule:
14
+ def __init__(self):
15
+ """Initialize the scheduler with the given configuration."""
16
+ self.base_dir = Path(BASE_DIR)
17
+
18
+ self._chat_llm = None
19
+ self._process_llm = None
20
+
21
+ def load_template(self, template_name: str) -> str:
22
+ if template_name not in PROMPT_MAPPING:
23
+ logger.error("Prompt template is not found!")
24
+ prompt = PROMPT_MAPPING[template_name]
25
+ return prompt
26
+
27
+ def build_prompt(self, template_name: str, **kwargs) -> str:
28
+ template = self.load_template(template_name)
29
+ if not template:
30
+ raise FileNotFoundError(f"Prompt template `{template_name}` not found.")
31
+ return template.format(**kwargs)
32
+
33
+ def _build_system_prompt(self, memories: list | None = None) -> str:
34
+ """Build system prompt with optional memories context."""
35
+ base_prompt = (
36
+ "You are a knowledgeable and helpful AI assistant. "
37
+ "You have access to conversation memories that help you provide more personalized responses. "
38
+ "Use the memories to understand the user's context, preferences, and past interactions. "
39
+ "If memories are provided, reference them naturally when relevant, but don't explicitly mention having memories."
40
+ )
41
+
42
+ if memories:
43
+ memory_context = "\n\n## Conversation Context:\n"
44
+ for i, memory in enumerate(memories, 1):
45
+ memory_context += f"{i}. {memory.memory}\n"
46
+ return base_prompt + memory_context
47
+
48
+ return base_prompt
49
+
50
+ def get_mem_cube(self, mem_cube_id: str) -> GeneralMemCube:
51
+ logger.error(f"mem_cube {mem_cube_id} does not exists.")
52
+ return self.current_mem_cube
53
+
54
+ @property
55
+ def chat_llm(self) -> BaseLLM:
56
+ """The memory cube associated with this MemChat."""
57
+ return self._chat_llm
58
+
59
+ @chat_llm.setter
60
+ def chat_llm(self, value: BaseLLM) -> None:
61
+ """The memory cube associated with this MemChat."""
62
+ self._chat_llm = value
63
+
64
+ @property
65
+ def process_llm(self) -> BaseLLM:
66
+ return self._process_llm
67
+
68
+ @process_llm.setter
69
+ def process_llm(self, value: BaseLLM) -> None:
70
+ self._process_llm = value
71
+
72
+ @property
73
+ def mem_cube(self) -> GeneralMemCube:
74
+ """The memory cube associated with this MemChat."""
75
+ return self.current_mem_cube
76
+
77
+ @mem_cube.setter
78
+ def mem_cube(self, value: GeneralMemCube) -> None:
79
+ """The memory cube associated with this MemChat."""
80
+ self.current_mem_cube = value
@@ -0,0 +1,425 @@
1
+ import json
2
+ import os
3
+
4
+ from typing import TYPE_CHECKING, Any
5
+
6
+ from memos.api.config import APIConfig
7
+ from memos.configs.embedder import EmbedderConfigFactory
8
+ from memos.configs.graph_db import GraphDBConfigFactory
9
+ from memos.configs.internet_retriever import InternetRetrieverConfigFactory
10
+ from memos.configs.llm import LLMConfigFactory
11
+ from memos.configs.mem_reader import MemReaderConfigFactory
12
+ from memos.configs.reranker import RerankerConfigFactory
13
+ from memos.configs.vec_db import VectorDBConfigFactory
14
+ from memos.embedders.factory import EmbedderFactory
15
+ from memos.graph_dbs.factory import GraphStoreFactory
16
+ from memos.llms.factory import LLMFactory
17
+ from memos.log import get_logger
18
+ from memos.mem_cube.navie import NaiveMemCube
19
+ from memos.mem_feedback.simple_feedback import SimpleMemFeedback
20
+ from memos.mem_reader.factory import MemReaderFactory
21
+ from memos.memories.textual.prefer_text_memory.config import (
22
+ AdderConfigFactory,
23
+ ExtractorConfigFactory,
24
+ RetrieverConfigFactory,
25
+ )
26
+ from memos.memories.textual.prefer_text_memory.factory import (
27
+ AdderFactory,
28
+ ExtractorFactory,
29
+ RetrieverFactory,
30
+ )
31
+ from memos.memories.textual.simple_preference import SimplePreferenceTextMemory
32
+ from memos.memories.textual.simple_tree import SimpleTreeTextMemory
33
+ from memos.memories.textual.tree_text_memory.organize.manager import MemoryManager
34
+ from memos.memories.textual.tree_text_memory.retrieve.internet_retriever_factory import (
35
+ InternetRetrieverFactory,
36
+ )
37
+ from memos.memories.textual.tree_text_memory.retrieve.retrieve_utils import FastTokenizer
38
+
39
+
40
+ if TYPE_CHECKING:
41
+ from memos.memories.textual.tree_text_memory.retrieve.searcher import Searcher
42
+ from memos.reranker.factory import RerankerFactory
43
+ from memos.vec_dbs.factory import VecDBFactory
44
+
45
+
46
+ logger = get_logger(__name__)
47
+
48
+
49
+ def build_graph_db_config(user_id: str = "default") -> dict[str, Any]:
50
+ """
51
+ Build graph database configuration.
52
+
53
+ Args:
54
+ user_id: User ID for configuration context (default: "default")
55
+
56
+ Returns:
57
+ Validated graph database configuration dictionary
58
+ """
59
+ graph_db_backend_map = {
60
+ "neo4j-community": APIConfig.get_neo4j_community_config(user_id=user_id),
61
+ "neo4j": APIConfig.get_neo4j_config(user_id=user_id),
62
+ "nebular": APIConfig.get_nebular_config(user_id=user_id),
63
+ "polardb": APIConfig.get_polardb_config(user_id=user_id),
64
+ }
65
+
66
+ graph_db_backend = os.getenv("NEO4J_BACKEND", "nebular").lower()
67
+ return GraphDBConfigFactory.model_validate(
68
+ {
69
+ "backend": graph_db_backend,
70
+ "config": graph_db_backend_map[graph_db_backend],
71
+ }
72
+ )
73
+
74
+
75
+ def build_vec_db_config() -> dict[str, Any]:
76
+ """
77
+ Build vector database configuration.
78
+
79
+ Returns:
80
+ Validated vector database configuration dictionary
81
+ """
82
+ return VectorDBConfigFactory.model_validate(
83
+ {
84
+ "backend": "milvus",
85
+ "config": APIConfig.get_milvus_config(),
86
+ }
87
+ )
88
+
89
+
90
+ def build_llm_config() -> dict[str, Any]:
91
+ """
92
+ Build LLM configuration.
93
+
94
+ Returns:
95
+ Validated LLM configuration dictionary
96
+ """
97
+ return LLMConfigFactory.model_validate(
98
+ {
99
+ "backend": "openai",
100
+ "config": APIConfig.get_openai_config(),
101
+ }
102
+ )
103
+
104
+
105
+ def build_chat_llm_config() -> list[dict[str, Any]]:
106
+ """
107
+ Build chat LLM configuration.
108
+
109
+ Returns:
110
+ Validated chat LLM configuration dictionary
111
+ """
112
+ configs = json.loads(os.getenv("CHAT_MODEL_LIST", "[]"))
113
+ return [
114
+ {
115
+ "config_class": LLMConfigFactory.model_validate(
116
+ {
117
+ "backend": cfg.get("backend", "openai"),
118
+ "config": (
119
+ {k: v for k, v in cfg.items() if k not in ["backend", "support_models"]}
120
+ )
121
+ if cfg
122
+ else APIConfig.get_openai_config(),
123
+ }
124
+ ),
125
+ "support_models": cfg.get("support_models", None),
126
+ }
127
+ for cfg in configs
128
+ ]
129
+
130
+
131
+ def build_embedder_config() -> dict[str, Any]:
132
+ """
133
+ Build embedder configuration.
134
+
135
+ Returns:
136
+ Validated embedder configuration dictionary
137
+ """
138
+ return EmbedderConfigFactory.model_validate(APIConfig.get_embedder_config())
139
+
140
+
141
+ def build_mem_reader_config() -> dict[str, Any]:
142
+ """
143
+ Build memory reader configuration.
144
+
145
+ Returns:
146
+ Validated memory reader configuration dictionary
147
+ """
148
+ return MemReaderConfigFactory.model_validate(
149
+ APIConfig.get_product_default_config()["mem_reader"]
150
+ )
151
+
152
+
153
+ def build_reranker_config() -> dict[str, Any]:
154
+ """
155
+ Build reranker configuration.
156
+
157
+ Returns:
158
+ Validated reranker configuration dictionary
159
+ """
160
+ return RerankerConfigFactory.model_validate(APIConfig.get_reranker_config())
161
+
162
+
163
+ def build_feedback_reranker_config() -> dict[str, Any]:
164
+ """
165
+ Build reranker configuration.
166
+
167
+ Returns:
168
+ Validated reranker configuration dictionary
169
+ """
170
+ return RerankerConfigFactory.model_validate(APIConfig.get_feedback_reranker_config())
171
+
172
+
173
+ def build_internet_retriever_config() -> dict[str, Any]:
174
+ """
175
+ Build internet retriever configuration.
176
+
177
+ Returns:
178
+ Validated internet retriever configuration dictionary
179
+ """
180
+ return InternetRetrieverConfigFactory.model_validate(APIConfig.get_internet_config())
181
+
182
+
183
+ def build_pref_extractor_config() -> dict[str, Any]:
184
+ """
185
+ Build preference memory extractor configuration.
186
+
187
+ Returns:
188
+ Validated extractor configuration dictionary
189
+ """
190
+ return ExtractorConfigFactory.model_validate({"backend": "naive", "config": {}})
191
+
192
+
193
+ def build_pref_adder_config() -> dict[str, Any]:
194
+ """
195
+ Build preference memory adder configuration.
196
+
197
+ Returns:
198
+ Validated adder configuration dictionary
199
+ """
200
+ return AdderConfigFactory.model_validate({"backend": "naive", "config": {}})
201
+
202
+
203
+ def build_pref_retriever_config() -> dict[str, Any]:
204
+ """
205
+ Build preference memory retriever configuration.
206
+
207
+ Returns:
208
+ Validated retriever configuration dictionary
209
+ """
210
+ return RetrieverConfigFactory.model_validate({"backend": "naive", "config": {}})
211
+
212
+
213
+ def _get_default_memory_size(cube_config: Any) -> dict[str, int]:
214
+ """
215
+ Get default memory size configuration.
216
+
217
+ Attempts to retrieve memory size from cube config, falls back to defaults
218
+ if not found.
219
+
220
+ Args:
221
+ cube_config: The cube configuration object
222
+
223
+ Returns:
224
+ Dictionary with memory sizes for different memory types
225
+ """
226
+ return getattr(cube_config.text_mem.config, "memory_size", None) or {
227
+ "WorkingMemory": 20,
228
+ "LongTermMemory": 1500,
229
+ "UserMemory": 480,
230
+ }
231
+
232
+
233
+ def _init_chat_llms(chat_llm_configs: list[dict]) -> dict[str, Any]:
234
+ """
235
+ Initialize chat language models from configuration.
236
+
237
+ Args:
238
+ chat_llm_configs: List of chat LLM configuration dictionaries
239
+
240
+ Returns:
241
+ Dictionary mapping model names to initialized LLM instances
242
+ """
243
+
244
+ def _list_models(client):
245
+ try:
246
+ models = (
247
+ [model.id for model in client.models.list().data]
248
+ if client.models.list().data
249
+ else client.models.list().models
250
+ )
251
+ except Exception as e:
252
+ logger.error(f"Error listing models: {e}")
253
+ models = []
254
+ return models
255
+
256
+ model_name_instrance_maping = {}
257
+ for cfg in chat_llm_configs:
258
+ llm = LLMFactory.from_config(cfg["config_class"])
259
+ if cfg["support_models"]:
260
+ for model_name in cfg["support_models"]:
261
+ model_name_instrance_maping[model_name] = llm
262
+ return model_name_instrance_maping
263
+
264
+
265
+ def init_components() -> dict[str, Any]:
266
+ # Initialize Redis client first as it is a core dependency for features like scheduler status tracking
267
+ try:
268
+ from memos.mem_scheduler.orm_modules.api_redis_model import APIRedisDBManager
269
+
270
+ redis_client = APIRedisDBManager.load_redis_engine_from_env()
271
+ if redis_client:
272
+ logger.info("Redis client initialized successfully.")
273
+ else:
274
+ logger.error(
275
+ "Failed to initialize Redis client. Check REDIS_HOST etc. in environment variables."
276
+ )
277
+ except Exception as e:
278
+ logger.error(f"Failed to initialize Redis client: {e}", exc_info=True)
279
+ redis_client = None # Ensure redis_client exists even on failure
280
+
281
+ # Get default cube configuration
282
+ default_cube_config = APIConfig.get_default_cube_config()
283
+
284
+ # Build component configurations
285
+ graph_db_config = build_graph_db_config()
286
+ llm_config = build_llm_config()
287
+ embedder_config = build_embedder_config()
288
+ mem_reader_config = build_mem_reader_config()
289
+ reranker_config = build_reranker_config()
290
+ feedback_reranker_config = build_feedback_reranker_config()
291
+ internet_retriever_config = build_internet_retriever_config()
292
+ vector_db_config = build_vec_db_config()
293
+ pref_extractor_config = build_pref_extractor_config()
294
+ pref_adder_config = build_pref_adder_config()
295
+ pref_retriever_config = build_pref_retriever_config()
296
+
297
+ logger.debug("Component configurations built successfully")
298
+
299
+ # Create component instances
300
+ graph_db = GraphStoreFactory.from_config(graph_db_config)
301
+ vector_db = (
302
+ VecDBFactory.from_config(vector_db_config)
303
+ if os.getenv("ENABLE_PREFERENCE_MEMORY", "false") == "true"
304
+ else None
305
+ )
306
+ llm = LLMFactory.from_config(llm_config)
307
+ embedder = EmbedderFactory.from_config(embedder_config)
308
+ # Pass graph_db to mem_reader for recall operations (deduplication, conflict detection)
309
+ mem_reader = MemReaderFactory.from_config(mem_reader_config, graph_db=graph_db)
310
+ reranker = RerankerFactory.from_config(reranker_config)
311
+ feedback_reranker = RerankerFactory.from_config(feedback_reranker_config)
312
+ internet_retriever = InternetRetrieverFactory.from_config(
313
+ internet_retriever_config, embedder=embedder
314
+ )
315
+
316
+ # Initialize chat llms
317
+ logger.debug("Core components instantiated")
318
+
319
+ # Initialize memory manager
320
+ memory_manager = MemoryManager(
321
+ graph_db,
322
+ embedder,
323
+ llm,
324
+ memory_size=_get_default_memory_size(default_cube_config),
325
+ is_reorganize=getattr(default_cube_config.text_mem.config, "reorganize", False),
326
+ )
327
+
328
+ logger.debug("Memory manager initialized")
329
+
330
+ tokenizer = FastTokenizer()
331
+ # Initialize text memory
332
+ text_mem = SimpleTreeTextMemory(
333
+ llm=llm,
334
+ embedder=embedder,
335
+ mem_reader=mem_reader,
336
+ graph_db=graph_db,
337
+ reranker=reranker,
338
+ memory_manager=memory_manager,
339
+ config=default_cube_config.text_mem.config,
340
+ internet_retriever=internet_retriever,
341
+ tokenizer=tokenizer,
342
+ )
343
+
344
+ logger.debug("Text memory initialized")
345
+
346
+ # Initialize preference memory components
347
+ pref_extractor = (
348
+ ExtractorFactory.from_config(
349
+ config_factory=pref_extractor_config,
350
+ llm_provider=llm,
351
+ embedder=embedder,
352
+ vector_db=vector_db,
353
+ )
354
+ if os.getenv("ENABLE_PREFERENCE_MEMORY", "false") == "true"
355
+ else None
356
+ )
357
+
358
+ pref_adder = (
359
+ AdderFactory.from_config(
360
+ config_factory=pref_adder_config,
361
+ llm_provider=llm,
362
+ embedder=embedder,
363
+ vector_db=vector_db,
364
+ text_mem=text_mem,
365
+ )
366
+ if os.getenv("ENABLE_PREFERENCE_MEMORY", "false") == "true"
367
+ else None
368
+ )
369
+
370
+ pref_retriever = (
371
+ RetrieverFactory.from_config(
372
+ config_factory=pref_retriever_config,
373
+ llm_provider=llm,
374
+ embedder=embedder,
375
+ reranker=feedback_reranker,
376
+ vector_db=vector_db,
377
+ )
378
+ if os.getenv("ENABLE_PREFERENCE_MEMORY", "false") == "true"
379
+ else None
380
+ )
381
+
382
+ logger.debug("Preference memory components initialized")
383
+
384
+ # Initialize preference memory
385
+ pref_mem = (
386
+ SimplePreferenceTextMemory(
387
+ extractor_llm=llm,
388
+ vector_db=vector_db,
389
+ embedder=embedder,
390
+ reranker=feedback_reranker,
391
+ extractor=pref_extractor,
392
+ adder=pref_adder,
393
+ retriever=pref_retriever,
394
+ )
395
+ if os.getenv("ENABLE_PREFERENCE_MEMORY", "false") == "true"
396
+ else None
397
+ )
398
+
399
+ # Create MemCube with pre-initialized memory instances
400
+ naive_mem_cube = NaiveMemCube(
401
+ text_mem=text_mem,
402
+ pref_mem=pref_mem,
403
+ act_mem=None,
404
+ para_mem=None,
405
+ )
406
+
407
+ tree_mem: SimpleTreeTextMemory = naive_mem_cube.text_mem
408
+ searcher: Searcher = tree_mem.get_searcher(
409
+ manual_close_internet=os.getenv("ENABLE_INTERNET", "true").lower() == "false",
410
+ moscube=False,
411
+ process_llm=mem_reader.llm,
412
+ )
413
+ # Initialize feedback server
414
+ feedback_server = SimpleMemFeedback(
415
+ llm=llm,
416
+ embedder=embedder,
417
+ graph_store=graph_db,
418
+ memory_manager=memory_manager,
419
+ mem_reader=mem_reader,
420
+ searcher=searcher,
421
+ reranker=feedback_reranker,
422
+ pref_mem=pref_mem,
423
+ )
424
+ # Return all components as a dictionary for easy access and extension
425
+ return {"naive_mem_cube": naive_mem_cube, "feedback_server": feedback_server}