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,394 @@
1
+ """
2
+ Server API Router for MemOS (Class-based handlers version).
3
+
4
+ This router demonstrates the improved architecture using class-based handlers
5
+ with dependency injection, providing better modularity and maintainability.
6
+
7
+ Comparison with function-based approach:
8
+ - Cleaner code: No need to pass dependencies in every endpoint
9
+ - Better testability: Easy to mock handler dependencies
10
+ - Improved extensibility: Add new handlers or modify existing ones easily
11
+ - Clear separation of concerns: Router focuses on routing, handlers handle business logic
12
+ """
13
+
14
+ import os
15
+ import random as _random
16
+ import socket
17
+
18
+ from fastapi import APIRouter, HTTPException, Query
19
+
20
+ from memos.api import handlers
21
+ from memos.api.handlers.add_handler import AddHandler
22
+ from memos.api.handlers.base_handler import HandlerDependencies
23
+ from memos.api.handlers.chat_handler import ChatHandler
24
+ from memos.api.handlers.feedback_handler import FeedbackHandler
25
+ from memos.api.handlers.search_handler import SearchHandler
26
+ from memos.api.product_models import (
27
+ AllStatusResponse,
28
+ APIADDRequest,
29
+ APIChatCompleteRequest,
30
+ APIFeedbackRequest,
31
+ APISearchRequest,
32
+ ChatPlaygroundRequest,
33
+ ChatRequest,
34
+ DeleteMemoryRequest,
35
+ DeleteMemoryResponse,
36
+ ExistMemCubeIdRequest,
37
+ ExistMemCubeIdResponse,
38
+ GetMemoryPlaygroundRequest,
39
+ GetMemoryRequest,
40
+ GetMemoryResponse,
41
+ GetUserNamesByMemoryIdsRequest,
42
+ GetUserNamesByMemoryIdsResponse,
43
+ MemoryResponse,
44
+ SearchResponse,
45
+ StatusResponse,
46
+ SuggestionRequest,
47
+ SuggestionResponse,
48
+ TaskQueueResponse,
49
+ )
50
+ from memos.graph_dbs.polardb import PolarDBGraphDB
51
+ from memos.log import get_logger
52
+ from memos.mem_scheduler.base_scheduler import BaseScheduler
53
+ from memos.mem_scheduler.utils.status_tracker import TaskStatusTracker
54
+
55
+
56
+ logger = get_logger(__name__)
57
+
58
+ router = APIRouter(prefix="/product", tags=["Server API"])
59
+
60
+ # Instance ID for identifying this server instance in logs and responses
61
+ INSTANCE_ID = f"{socket.gethostname()}:{os.getpid()}:{_random.randint(1000, 9999)}"
62
+
63
+ # Initialize all server components
64
+ components = handlers.init_server()
65
+
66
+ # Create dependency container
67
+ dependencies = HandlerDependencies.from_init_server(components)
68
+
69
+ # Initialize all handlers with dependency injection
70
+ search_handler = SearchHandler(dependencies)
71
+ add_handler = AddHandler(dependencies)
72
+ chat_handler = (
73
+ ChatHandler(
74
+ dependencies,
75
+ components["chat_llms"],
76
+ search_handler,
77
+ add_handler,
78
+ online_bot=components.get("online_bot"),
79
+ )
80
+ if os.getenv("ENABLE_CHAT_API", "false") == "true"
81
+ else None
82
+ )
83
+ feedback_handler = FeedbackHandler(dependencies)
84
+ # Extract commonly used components for function-based handlers
85
+ # (These can be accessed from the components dict without unpacking all of them)
86
+ mem_scheduler: BaseScheduler = components["mem_scheduler"]
87
+ llm = components["llm"]
88
+ naive_mem_cube = components["naive_mem_cube"]
89
+ redis_client = components["redis_client"]
90
+ status_tracker = TaskStatusTracker(redis_client=redis_client)
91
+ graph_db = components["graph_db"]
92
+ vector_db = components["vector_db"]
93
+
94
+
95
+ # =============================================================================
96
+ # Search API Endpoints
97
+ # =============================================================================
98
+
99
+
100
+ @router.post("/search", summary="Search memories", response_model=SearchResponse)
101
+ def search_memories(search_req: APISearchRequest):
102
+ """
103
+ Search memories for a specific user.
104
+
105
+ This endpoint uses the class-based SearchHandler for better code organization.
106
+ """
107
+ search_results = search_handler.handle_search_memories(search_req)
108
+ return search_results
109
+
110
+
111
+ # =============================================================================
112
+ # Add API Endpoints
113
+ # =============================================================================
114
+
115
+
116
+ @router.post("/add", summary="Add memories", response_model=MemoryResponse)
117
+ def add_memories(add_req: APIADDRequest):
118
+ """
119
+ Add memories for a specific user.
120
+
121
+ This endpoint uses the class-based AddHandler for better code organization.
122
+ """
123
+ return add_handler.handle_add_memories(add_req)
124
+
125
+
126
+ # =============================================================================
127
+ # Scheduler API Endpoints
128
+ # =============================================================================
129
+
130
+
131
+ @router.get( # Changed from post to get
132
+ "/scheduler/allstatus",
133
+ summary="Get detailed scheduler status",
134
+ response_model=AllStatusResponse,
135
+ )
136
+ def scheduler_allstatus():
137
+ """Get detailed scheduler status including running tasks and queue metrics."""
138
+ return handlers.scheduler_handler.handle_scheduler_allstatus(
139
+ mem_scheduler=mem_scheduler, status_tracker=status_tracker
140
+ )
141
+
142
+
143
+ @router.get( # Changed from post to get
144
+ "/scheduler/status", summary="Get scheduler running status", response_model=StatusResponse
145
+ )
146
+ def scheduler_status(
147
+ user_id: str = Query(..., description="User ID"),
148
+ task_id: str | None = Query(None, description="Optional Task ID to query a specific task"),
149
+ ):
150
+ """Get scheduler running status."""
151
+ return handlers.scheduler_handler.handle_scheduler_status(
152
+ user_id=user_id,
153
+ task_id=task_id,
154
+ status_tracker=status_tracker,
155
+ )
156
+
157
+
158
+ @router.get( # Changed from post to get
159
+ "/scheduler/task_queue_status",
160
+ summary="Get scheduler task queue status",
161
+ response_model=TaskQueueResponse,
162
+ )
163
+ def scheduler_task_queue_status(
164
+ user_id: str = Query(..., description="User ID whose queue status is requested"),
165
+ ):
166
+ """Get scheduler task queue backlog/pending status for a user."""
167
+ return handlers.scheduler_handler.handle_task_queue_status(
168
+ user_id=user_id, mem_scheduler=mem_scheduler
169
+ )
170
+
171
+
172
+ @router.post("/scheduler/wait", summary="Wait until scheduler is idle for a specific user")
173
+ def scheduler_wait(
174
+ user_name: str,
175
+ timeout_seconds: float = 120.0,
176
+ poll_interval: float = 0.5,
177
+ ):
178
+ """Wait until scheduler is idle for a specific user."""
179
+ return handlers.scheduler_handler.handle_scheduler_wait(
180
+ user_name=user_name,
181
+ status_tracker=status_tracker,
182
+ timeout_seconds=timeout_seconds,
183
+ poll_interval=poll_interval,
184
+ )
185
+
186
+
187
+ @router.get("/scheduler/wait/stream", summary="Stream scheduler progress for a user")
188
+ def scheduler_wait_stream(
189
+ user_name: str,
190
+ timeout_seconds: float = 120.0,
191
+ poll_interval: float = 0.5,
192
+ ):
193
+ """Stream scheduler progress via Server-Sent Events (SSE)."""
194
+ return handlers.scheduler_handler.handle_scheduler_wait_stream(
195
+ user_name=user_name,
196
+ status_tracker=status_tracker,
197
+ timeout_seconds=timeout_seconds,
198
+ poll_interval=poll_interval,
199
+ instance_id=INSTANCE_ID,
200
+ )
201
+
202
+
203
+ # =============================================================================
204
+ # Chat API Endpoints
205
+ # =============================================================================
206
+
207
+
208
+ @router.post("/chat/complete", summary="Chat with MemOS (Complete Response)")
209
+ def chat_complete(chat_req: APIChatCompleteRequest):
210
+ """
211
+ Chat with MemOS for a specific user. Returns complete response (non-streaming).
212
+
213
+ This endpoint uses the class-based ChatHandler.
214
+ """
215
+ if chat_handler is None:
216
+ raise HTTPException(
217
+ status_code=503, detail="Chat service is not available. Chat handler not initialized."
218
+ )
219
+ return chat_handler.handle_chat_complete(chat_req)
220
+
221
+
222
+ @router.post("/chat/stream", summary="Chat with MemOS")
223
+ def chat_stream(chat_req: ChatRequest):
224
+ """
225
+ Chat with MemOS for a specific user. Returns SSE stream.
226
+
227
+ This endpoint uses the class-based ChatHandler which internally
228
+ composes SearchHandler and AddHandler for a clean architecture.
229
+ """
230
+ if chat_handler is None:
231
+ raise HTTPException(
232
+ status_code=503, detail="Chat service is not available. Chat handler not initialized."
233
+ )
234
+ return chat_handler.handle_chat_stream(chat_req)
235
+
236
+
237
+ @router.post("/chat/stream/playground", summary="Chat with MemOS playground")
238
+ def chat_stream_playground(chat_req: ChatPlaygroundRequest):
239
+ """
240
+ Chat with MemOS for a specific user. Returns SSE stream.
241
+
242
+ This endpoint uses the class-based ChatHandler which internally
243
+ composes SearchHandler and AddHandler for a clean architecture.
244
+ """
245
+ if chat_handler is None:
246
+ raise HTTPException(
247
+ status_code=503, detail="Chat service is not available. Chat handler not initialized."
248
+ )
249
+ return chat_handler.handle_chat_stream_playground(chat_req)
250
+
251
+
252
+ # =============================================================================
253
+ # Suggestion API Endpoints
254
+ # =============================================================================
255
+
256
+
257
+ @router.post(
258
+ "/suggestions",
259
+ summary="Get suggestion queries",
260
+ response_model=SuggestionResponse,
261
+ )
262
+ def get_suggestion_queries(suggestion_req: SuggestionRequest):
263
+ """Get suggestion queries for a specific user with language preference."""
264
+ return handlers.suggestion_handler.handle_get_suggestion_queries(
265
+ user_id=suggestion_req.mem_cube_id,
266
+ language=suggestion_req.language,
267
+ message=suggestion_req.message,
268
+ llm=llm,
269
+ naive_mem_cube=naive_mem_cube,
270
+ )
271
+
272
+
273
+ # =============================================================================
274
+ # Memory Retrieval Delete API Endpoints
275
+ # =============================================================================
276
+
277
+
278
+ @router.post("/get_all", summary="Get all memories for user", response_model=MemoryResponse)
279
+ def get_all_memories(memory_req: GetMemoryPlaygroundRequest):
280
+ """
281
+ Get all memories or subgraph for a specific user.
282
+
283
+ If search_query is provided, returns a subgraph based on the query.
284
+ Otherwise, returns all memories of the specified type.
285
+ """
286
+ if memory_req.search_query:
287
+ return handlers.memory_handler.handle_get_subgraph(
288
+ user_id=memory_req.user_id,
289
+ mem_cube_id=(
290
+ memory_req.mem_cube_ids[0] if memory_req.mem_cube_ids else memory_req.user_id
291
+ ),
292
+ query=memory_req.search_query,
293
+ top_k=20,
294
+ naive_mem_cube=naive_mem_cube,
295
+ )
296
+ else:
297
+ return handlers.memory_handler.handle_get_all_memories(
298
+ user_id=memory_req.user_id,
299
+ mem_cube_id=(
300
+ memory_req.mem_cube_ids[0] if memory_req.mem_cube_ids else memory_req.user_id
301
+ ),
302
+ memory_type=memory_req.memory_type or "text_mem",
303
+ naive_mem_cube=naive_mem_cube,
304
+ )
305
+
306
+
307
+ @router.post("/get_memory", summary="Get memories for user", response_model=GetMemoryResponse)
308
+ def get_memories(memory_req: GetMemoryRequest):
309
+ return handlers.memory_handler.handle_get_memories(
310
+ get_mem_req=memory_req,
311
+ naive_mem_cube=naive_mem_cube,
312
+ )
313
+
314
+
315
+ @router.get("/get_memory/{memory_id}", summary="Get memory by id", response_model=GetMemoryResponse)
316
+ def get_memory_by_id(memory_id: str):
317
+ return handlers.memory_handler.handle_get_memory(
318
+ memory_id=memory_id,
319
+ naive_mem_cube=naive_mem_cube,
320
+ )
321
+
322
+
323
+ @router.post(
324
+ "/delete_memory", summary="Delete memories for user", response_model=DeleteMemoryResponse
325
+ )
326
+ def delete_memories(memory_req: DeleteMemoryRequest):
327
+ return handlers.memory_handler.handle_delete_memories(
328
+ delete_mem_req=memory_req, naive_mem_cube=naive_mem_cube
329
+ )
330
+
331
+
332
+ # =============================================================================
333
+ # Feedback API Endpoints
334
+ # =============================================================================
335
+
336
+
337
+ @router.post("/feedback", summary="Feedback memories", response_model=MemoryResponse)
338
+ def feedback_memories(feedback_req: APIFeedbackRequest):
339
+ """
340
+ Feedback memories for a specific user.
341
+
342
+ This endpoint uses the class-based FeedbackHandler for better code organization.
343
+ """
344
+ return feedback_handler.handle_feedback_memories(feedback_req)
345
+
346
+
347
+ # =============================================================================
348
+ # Other API Endpoints (for internal use)
349
+ # =============================================================================
350
+
351
+
352
+ @router.post(
353
+ "/get_user_names_by_memory_ids",
354
+ summary="Get user names by memory ids",
355
+ response_model=GetUserNamesByMemoryIdsResponse,
356
+ )
357
+ def get_user_names_by_memory_ids(request: GetUserNamesByMemoryIdsRequest):
358
+ """Get user names by memory ids."""
359
+ if not isinstance(graph_db, PolarDBGraphDB):
360
+ raise HTTPException(
361
+ status_code=400,
362
+ detail=(
363
+ "graph_db must be an instance of PolarDBGraphDB to use "
364
+ "get_user_names_by_memory_ids"
365
+ f"current graph_db is: {graph_db.__class__.__name__}"
366
+ ),
367
+ )
368
+ result = graph_db.get_user_names_by_memory_ids(memory_ids=request.memory_ids)
369
+ if vector_db:
370
+ prefs = []
371
+ for collection_name in ["explicit_preference", "implicit_preference"]:
372
+ prefs.extend(
373
+ vector_db.get_by_ids(collection_name=collection_name, ids=request.memory_ids)
374
+ )
375
+ result.update({pref.id: pref.payload.get("mem_cube_id", None) for pref in prefs})
376
+ return GetUserNamesByMemoryIdsResponse(
377
+ code=200,
378
+ message="Successfully",
379
+ data=result,
380
+ )
381
+
382
+
383
+ @router.post(
384
+ "/exist_mem_cube_id",
385
+ summary="Check if mem cube id exists",
386
+ response_model=ExistMemCubeIdResponse,
387
+ )
388
+ def exist_mem_cube_id(request: ExistMemCubeIdRequest):
389
+ """Check if mem cube id exists."""
390
+ return ExistMemCubeIdResponse(
391
+ code=200,
392
+ message="Successfully",
393
+ data=graph_db.exist_user_name(user_name=request.mem_cube_id),
394
+ )
@@ -0,0 +1,44 @@
1
+ import logging
2
+
3
+ from fastapi import FastAPI, HTTPException
4
+ from fastapi.exceptions import RequestValidationError
5
+
6
+ from memos.api.exceptions import APIExceptionHandler
7
+ from memos.api.middleware.request_context import RequestContextMiddleware
8
+ from memos.api.routers.server_router import router as server_router
9
+
10
+
11
+ # Configure logging
12
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
13
+ logger = logging.getLogger(__name__)
14
+
15
+ app = FastAPI(
16
+ title="MemOS Server REST APIs",
17
+ description="A REST API for managing multiple users with MemOS Server.",
18
+ version="1.0.1",
19
+ )
20
+
21
+ app.add_middleware(RequestContextMiddleware, source="server_api")
22
+ # Include routers
23
+ app.include_router(server_router)
24
+
25
+ # Request validation failed
26
+ app.exception_handler(RequestValidationError)(APIExceptionHandler.validation_error_handler)
27
+ # Invalid business code parameters
28
+ app.exception_handler(ValueError)(APIExceptionHandler.value_error_handler)
29
+ # Business layer manual exception
30
+ app.exception_handler(HTTPException)(APIExceptionHandler.http_error_handler)
31
+ # Fallback for unknown errors
32
+ app.exception_handler(Exception)(APIExceptionHandler.global_exception_handler)
33
+
34
+
35
+ if __name__ == "__main__":
36
+ import argparse
37
+
38
+ import uvicorn
39
+
40
+ parser = argparse.ArgumentParser()
41
+ parser.add_argument("--port", type=int, default=8001)
42
+ parser.add_argument("--workers", type=int, default=1)
43
+ args = parser.parse_args()
44
+ uvicorn.run("memos.api.server_api:app", host="0.0.0.0", port=args.port, workers=args.workers)