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 @@
1
+ # API routers module
@@ -0,0 +1,477 @@
1
+ import json
2
+ import time
3
+ import traceback
4
+
5
+ from fastapi import APIRouter, HTTPException
6
+ from fastapi.responses import StreamingResponse
7
+
8
+ from memos.api.config import APIConfig
9
+ from memos.api.product_models import (
10
+ BaseResponse,
11
+ ChatCompleteRequest,
12
+ ChatRequest,
13
+ GetMemoryPlaygroundRequest,
14
+ MemoryCreateRequest,
15
+ MemoryResponse,
16
+ SearchRequest,
17
+ SearchResponse,
18
+ SimpleResponse,
19
+ SuggestionRequest,
20
+ SuggestionResponse,
21
+ UserRegisterRequest,
22
+ UserRegisterResponse,
23
+ )
24
+ from memos.configs.mem_os import MOSConfig
25
+ from memos.log import get_logger
26
+ from memos.mem_os.product import MOSProduct
27
+ from memos.memos_tools.notification_service import get_error_bot_function, get_online_bot_function
28
+
29
+
30
+ logger = get_logger(__name__)
31
+
32
+ router = APIRouter(prefix="/product", tags=["Product API"])
33
+
34
+ # Initialize MOSProduct instance with lazy initialization
35
+ MOS_PRODUCT_INSTANCE = None
36
+
37
+
38
+ def get_mos_product_instance():
39
+ """Get or create MOSProduct instance."""
40
+ global MOS_PRODUCT_INSTANCE
41
+ if MOS_PRODUCT_INSTANCE is None:
42
+ default_config = APIConfig.get_product_default_config()
43
+ logger.info(f"*********init_default_mos_config********* {default_config}")
44
+ from memos.configs.mem_os import MOSConfig
45
+
46
+ mos_config = MOSConfig(**default_config)
47
+
48
+ # Get default cube config from APIConfig (may be None if disabled)
49
+ default_cube_config = APIConfig.get_default_cube_config()
50
+ logger.info(f"*********initdefault_cube_config******** {default_cube_config}")
51
+
52
+ # Get DingDing bot functions
53
+ dingding_enabled = APIConfig.is_dingding_bot_enabled()
54
+ online_bot = get_online_bot_function() if dingding_enabled else None
55
+ error_bot = get_error_bot_function() if dingding_enabled else None
56
+
57
+ MOS_PRODUCT_INSTANCE = MOSProduct(
58
+ default_config=mos_config,
59
+ default_cube_config=default_cube_config,
60
+ online_bot=online_bot,
61
+ error_bot=error_bot,
62
+ )
63
+ logger.info("MOSProduct instance created successfully with inheritance architecture")
64
+ return MOS_PRODUCT_INSTANCE
65
+
66
+
67
+ get_mos_product_instance()
68
+
69
+
70
+ @router.post("/configure", summary="Configure MOSProduct", response_model=SimpleResponse)
71
+ def set_config(config):
72
+ """Set MOSProduct configuration."""
73
+ global MOS_PRODUCT_INSTANCE
74
+ MOS_PRODUCT_INSTANCE = MOSProduct(default_config=config)
75
+ return SimpleResponse(message="Configuration set successfully")
76
+
77
+
78
+ @router.post("/users/register", summary="Register a new user", response_model=UserRegisterResponse)
79
+ def register_user(user_req: UserRegisterRequest):
80
+ """Register a new user with configuration and default cube."""
81
+ try:
82
+ # Get configuration for the user
83
+ time_start_register = time.time()
84
+ user_config, default_mem_cube = APIConfig.create_user_config(
85
+ user_name=user_req.user_id, user_id=user_req.user_id
86
+ )
87
+ logger.info(f"user_config: {user_config.model_dump(mode='json')}")
88
+ logger.info(f"default_mem_cube: {default_mem_cube.config.model_dump(mode='json')}")
89
+ logger.info(
90
+ f"time register api : create user config time user_id: {user_req.user_id} time is: {time.time() - time_start_register}"
91
+ )
92
+ mos_product = get_mos_product_instance()
93
+
94
+ # Register user with default config and mem cube
95
+ result = mos_product.user_register(
96
+ user_id=user_req.user_id,
97
+ user_name=user_req.user_name,
98
+ interests=user_req.interests,
99
+ config=user_config,
100
+ default_mem_cube=default_mem_cube,
101
+ mem_cube_id=user_req.mem_cube_id,
102
+ )
103
+ logger.info(
104
+ f"time register api : register time user_id: {user_req.user_id} time is: {time.time() - time_start_register}"
105
+ )
106
+ if result["status"] == "success":
107
+ return UserRegisterResponse(
108
+ message="User registered successfully",
109
+ data={"user_id": result["user_id"], "mem_cube_id": result["default_cube_id"]},
110
+ )
111
+ else:
112
+ raise HTTPException(status_code=400, detail=result["message"])
113
+
114
+ except Exception as err:
115
+ logger.error(f"Failed to register user: {traceback.format_exc()}")
116
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
117
+
118
+
119
+ @router.get(
120
+ "/suggestions/{user_id}", summary="Get suggestion queries", response_model=SuggestionResponse
121
+ )
122
+ def get_suggestion_queries(user_id: str):
123
+ """Get suggestion queries for a specific user."""
124
+ try:
125
+ mos_product = get_mos_product_instance()
126
+ suggestions = mos_product.get_suggestion_query(user_id)
127
+ return SuggestionResponse(
128
+ message="Suggestions retrieved successfully", data={"query": suggestions}
129
+ )
130
+ except ValueError as err:
131
+ raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
132
+ except Exception as err:
133
+ logger.error(f"Failed to get suggestions: {traceback.format_exc()}")
134
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
135
+
136
+
137
+ @router.post(
138
+ "/suggestions",
139
+ summary="Get suggestion queries with language",
140
+ response_model=SuggestionResponse,
141
+ )
142
+ def get_suggestion_queries_post(suggestion_req: SuggestionRequest):
143
+ """Get suggestion queries for a specific user with language preference."""
144
+ try:
145
+ mos_product = get_mos_product_instance()
146
+ suggestions = mos_product.get_suggestion_query(
147
+ user_id=suggestion_req.user_id,
148
+ language=suggestion_req.language,
149
+ message=suggestion_req.message,
150
+ )
151
+ return SuggestionResponse(
152
+ message="Suggestions retrieved successfully", data={"query": suggestions}
153
+ )
154
+ except ValueError as err:
155
+ raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
156
+ except Exception as err:
157
+ logger.error(f"Failed to get suggestions: {traceback.format_exc()}")
158
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
159
+
160
+
161
+ @router.post("/get_all", summary="Get all memories for user", response_model=MemoryResponse)
162
+ def get_all_memories(memory_req: GetMemoryPlaygroundRequest):
163
+ """Get all memories for a specific user."""
164
+ try:
165
+ mos_product = get_mos_product_instance()
166
+ if memory_req.search_query:
167
+ result = mos_product.get_subgraph(
168
+ user_id=memory_req.user_id,
169
+ query=memory_req.search_query,
170
+ mem_cube_ids=memory_req.mem_cube_ids,
171
+ )
172
+ return MemoryResponse(message="Memories retrieved successfully", data=result)
173
+ else:
174
+ result = mos_product.get_all(
175
+ user_id=memory_req.user_id,
176
+ memory_type=memory_req.memory_type,
177
+ mem_cube_ids=memory_req.mem_cube_ids,
178
+ )
179
+ return MemoryResponse(message="Memories retrieved successfully", data=result)
180
+
181
+ except ValueError as err:
182
+ raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
183
+ except Exception as err:
184
+ logger.error(f"Failed to get memories: {traceback.format_exc()}")
185
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
186
+
187
+
188
+ @router.post("/add", summary="add a new memory", response_model=SimpleResponse)
189
+ def create_memory(memory_req: MemoryCreateRequest):
190
+ """Create a new memory for a specific user."""
191
+ logger.info("DIAGNOSTIC: /product/add endpoint called. This confirms the new code is deployed.")
192
+ # Initialize status_tracker outside try block to avoid NameError in except blocks
193
+ status_tracker = None
194
+
195
+ try:
196
+ time_start_add = time.time()
197
+ mos_product = get_mos_product_instance()
198
+
199
+ # Track task if task_id is provided
200
+ item_id: str | None = None
201
+ if (
202
+ memory_req.task_id
203
+ and hasattr(mos_product, "mem_scheduler")
204
+ and mos_product.mem_scheduler
205
+ ):
206
+ from uuid import uuid4
207
+
208
+ from memos.mem_scheduler.utils.status_tracker import TaskStatusTracker
209
+
210
+ item_id = str(uuid4()) # Generate a unique item_id for this submission
211
+
212
+ # Get Redis client from scheduler
213
+ if (
214
+ hasattr(mos_product.mem_scheduler, "redis_client")
215
+ and mos_product.mem_scheduler.redis_client
216
+ ):
217
+ status_tracker = TaskStatusTracker(mos_product.mem_scheduler.redis_client)
218
+ # Submit task with "product_add" type
219
+ status_tracker.task_submitted(
220
+ task_id=item_id, # Use generated item_id for internal tracking
221
+ user_id=memory_req.user_id,
222
+ task_type="product_add",
223
+ mem_cube_id=memory_req.mem_cube_id or memory_req.user_id,
224
+ business_task_id=memory_req.task_id, # Use memory_req.task_id as business_task_id
225
+ )
226
+ status_tracker.task_started(item_id, memory_req.user_id) # Use item_id here
227
+
228
+ # Execute the add operation
229
+ mos_product.add(
230
+ user_id=memory_req.user_id,
231
+ memory_content=memory_req.memory_content,
232
+ messages=memory_req.messages,
233
+ doc_path=memory_req.doc_path,
234
+ mem_cube_id=memory_req.mem_cube_id,
235
+ source=memory_req.source,
236
+ user_profile=memory_req.user_profile,
237
+ session_id=memory_req.session_id,
238
+ task_id=memory_req.task_id,
239
+ )
240
+
241
+ # Mark task as completed
242
+ if status_tracker and item_id:
243
+ status_tracker.task_completed(item_id, memory_req.user_id)
244
+
245
+ logger.info(
246
+ f"time add api : add time user_id: {memory_req.user_id} time is: {time.time() - time_start_add}"
247
+ )
248
+ return SimpleResponse(message="Memory created successfully")
249
+
250
+ except ValueError as err:
251
+ # Mark task as failed if tracking
252
+ if status_tracker and item_id:
253
+ status_tracker.task_failed(item_id, memory_req.user_id, str(err))
254
+ raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
255
+ except Exception as err:
256
+ # Mark task as failed if tracking
257
+ if status_tracker and item_id:
258
+ status_tracker.task_failed(item_id, memory_req.user_id, str(err))
259
+ logger.error(f"Failed to create memory: {traceback.format_exc()}")
260
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
261
+
262
+
263
+ @router.post("/search", summary="Search memories", response_model=SearchResponse)
264
+ def search_memories(search_req: SearchRequest):
265
+ """Search memories for a specific user."""
266
+ try:
267
+ time_start_search = time.time()
268
+ mos_product = get_mos_product_instance()
269
+ result = mos_product.search(
270
+ query=search_req.query,
271
+ user_id=search_req.user_id,
272
+ install_cube_ids=[search_req.mem_cube_id] if search_req.mem_cube_id else None,
273
+ top_k=search_req.top_k,
274
+ session_id=search_req.session_id,
275
+ )
276
+ logger.info(
277
+ f"time search api : add time user_id: {search_req.user_id} time is: {time.time() - time_start_search}"
278
+ )
279
+ return SearchResponse(message="Search completed successfully", data=result)
280
+
281
+ except ValueError as err:
282
+ raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
283
+ except Exception as err:
284
+ logger.error(f"Failed to search memories: {traceback.format_exc()}")
285
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
286
+
287
+
288
+ @router.post("/chat", summary="Chat with MemOS")
289
+ def chat(chat_req: ChatRequest):
290
+ """Chat with MemOS for a specific user. Returns SSE stream."""
291
+ try:
292
+ mos_product = get_mos_product_instance()
293
+
294
+ def generate_chat_response():
295
+ """Generate chat response as SSE stream."""
296
+ try:
297
+ # Directly yield from the generator without async wrapper
298
+ yield from mos_product.chat_with_references(
299
+ query=chat_req.query,
300
+ user_id=chat_req.user_id,
301
+ cube_id=chat_req.mem_cube_id,
302
+ history=chat_req.history,
303
+ internet_search=chat_req.internet_search,
304
+ moscube=chat_req.moscube,
305
+ session_id=chat_req.session_id,
306
+ )
307
+
308
+ except Exception as e:
309
+ logger.error(f"Error in chat stream: {e}")
310
+ error_data = f"data: {json.dumps({'type': 'error', 'content': str(traceback.format_exc())})}\n\n"
311
+ yield error_data
312
+
313
+ return StreamingResponse(
314
+ generate_chat_response(),
315
+ media_type="text/event-stream",
316
+ headers={
317
+ "Cache-Control": "no-cache",
318
+ "Connection": "keep-alive",
319
+ "Content-Type": "text/event-stream",
320
+ "Access-Control-Allow-Origin": "*",
321
+ "Access-Control-Allow-Headers": "*",
322
+ "Access-Control-Allow-Methods": "*",
323
+ },
324
+ )
325
+
326
+ except ValueError as err:
327
+ raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
328
+ except Exception as err:
329
+ logger.error(f"Failed to start chat: {traceback.format_exc()}")
330
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
331
+
332
+
333
+ @router.post("/chat/complete", summary="Chat with MemOS (Complete Response)")
334
+ def chat_complete(chat_req: ChatCompleteRequest):
335
+ """Chat with MemOS for a specific user. Returns complete response (non-streaming)."""
336
+ try:
337
+ mos_product = get_mos_product_instance()
338
+
339
+ # Collect all responses from the generator
340
+ content, references = mos_product.chat(
341
+ query=chat_req.query,
342
+ user_id=chat_req.user_id,
343
+ cube_id=chat_req.mem_cube_id,
344
+ history=chat_req.history,
345
+ internet_search=chat_req.internet_search,
346
+ moscube=chat_req.moscube,
347
+ base_prompt=chat_req.base_prompt or chat_req.system_prompt,
348
+ # will deprecate base_prompt in the future
349
+ top_k=chat_req.top_k,
350
+ threshold=chat_req.threshold,
351
+ session_id=chat_req.session_id,
352
+ )
353
+
354
+ # Return the complete response
355
+ return {
356
+ "message": "Chat completed successfully",
357
+ "data": {"response": content, "references": references},
358
+ }
359
+
360
+ except ValueError as err:
361
+ raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
362
+ except Exception as err:
363
+ logger.error(f"Failed to start chat: {traceback.format_exc()}")
364
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
365
+
366
+
367
+ @router.get("/users", summary="List all users", response_model=BaseResponse[list])
368
+ def list_users():
369
+ """List all registered users."""
370
+ try:
371
+ mos_product = get_mos_product_instance()
372
+ users = mos_product.list_users()
373
+ return BaseResponse(message="Users retrieved successfully", data=users)
374
+ except Exception as err:
375
+ logger.error(f"Failed to list users: {traceback.format_exc()}")
376
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
377
+
378
+
379
+ @router.get("/users/{user_id}", summary="Get user info", response_model=BaseResponse[dict])
380
+ async def get_user_info(user_id: str):
381
+ """Get user information including accessible cubes."""
382
+ try:
383
+ mos_product = get_mos_product_instance()
384
+ user_info = mos_product.get_user_info(user_id)
385
+ return BaseResponse(message="User info retrieved successfully", data=user_info)
386
+ except ValueError as err:
387
+ raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
388
+ except Exception as err:
389
+ logger.error(f"Failed to get user info: {traceback.format_exc()}")
390
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
391
+
392
+
393
+ @router.get(
394
+ "/configure/{user_id}", summary="Get MOSProduct configuration", response_model=SimpleResponse
395
+ )
396
+ def get_config(user_id: str):
397
+ """Get MOSProduct configuration."""
398
+ global MOS_PRODUCT_INSTANCE
399
+ config = MOS_PRODUCT_INSTANCE.default_config
400
+ return SimpleResponse(message="Configuration retrieved successfully", data=config)
401
+
402
+
403
+ @router.get(
404
+ "/users/{user_id}/config", summary="Get user configuration", response_model=BaseResponse[dict]
405
+ )
406
+ def get_user_config(user_id: str):
407
+ """Get user-specific configuration."""
408
+ try:
409
+ mos_product = get_mos_product_instance()
410
+ config = mos_product.get_user_config(user_id)
411
+ if config:
412
+ return BaseResponse(
413
+ message="User configuration retrieved successfully",
414
+ data=config.model_dump(mode="json"),
415
+ )
416
+ else:
417
+ raise HTTPException(
418
+ status_code=404, detail=f"Configuration not found for user {user_id}"
419
+ )
420
+ except ValueError as err:
421
+ raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
422
+ except Exception as err:
423
+ logger.error(f"Failed to get user config: {traceback.format_exc()}")
424
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
425
+
426
+
427
+ @router.put(
428
+ "/users/{user_id}/config", summary="Update user configuration", response_model=SimpleResponse
429
+ )
430
+ def update_user_config(user_id: str, config_data: dict):
431
+ """Update user-specific configuration."""
432
+ try:
433
+ mos_product = get_mos_product_instance()
434
+
435
+ # Create MOSConfig from the provided data
436
+ config = MOSConfig(**config_data)
437
+
438
+ # Update the configuration
439
+ success = mos_product.update_user_config(user_id, config)
440
+ if success:
441
+ return SimpleResponse(message="User configuration updated successfully")
442
+ else:
443
+ raise HTTPException(status_code=500, detail="Failed to update user configuration")
444
+
445
+ except ValueError as err:
446
+ raise HTTPException(status_code=400, detail=str(traceback.format_exc())) from err
447
+ except Exception as err:
448
+ logger.error(f"Failed to update user config: {traceback.format_exc()}")
449
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
450
+
451
+
452
+ @router.get(
453
+ "/instances/status", summary="Get user configuration status", response_model=BaseResponse[dict]
454
+ )
455
+ def get_instance_status():
456
+ """Get information about active user configurations in memory."""
457
+ try:
458
+ mos_product = get_mos_product_instance()
459
+ status_info = mos_product.get_user_instance_info()
460
+ return BaseResponse(
461
+ message="User configuration status retrieved successfully", data=status_info
462
+ )
463
+ except Exception as err:
464
+ logger.error(f"Failed to get user configuration status: {traceback.format_exc()}")
465
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
466
+
467
+
468
+ @router.get("/instances/count", summary="Get active user count", response_model=BaseResponse[int])
469
+ def get_active_user_count():
470
+ """Get the number of active user configurations in memory."""
471
+ try:
472
+ mos_product = get_mos_product_instance()
473
+ count = mos_product.get_active_user_count()
474
+ return BaseResponse(message="Active user count retrieved successfully", data=count)
475
+ except Exception as err:
476
+ logger.error(f"Failed to get active user count: {traceback.format_exc()}")
477
+ raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err