MemoryOS 0.2.1__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (175) hide show
  1. {memoryos-0.2.1 → memoryos-0.2.2}/PKG-INFO +2 -1
  2. {memoryos-0.2.1 → memoryos-0.2.2}/pyproject.toml +2 -1
  3. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/__init__.py +1 -1
  4. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/api/config.py +156 -65
  5. memoryos-0.2.2/src/memos/api/context/context.py +147 -0
  6. memoryos-0.2.2/src/memos/api/context/dependencies.py +90 -0
  7. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/api/product_models.py +5 -1
  8. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/api/routers/product_router.py +54 -26
  9. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/graph_db.py +49 -1
  10. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/internet_retriever.py +6 -0
  11. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/mem_os.py +5 -0
  12. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/mem_reader.py +9 -0
  13. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/mem_scheduler.py +18 -4
  14. memoryos-0.2.2/src/memos/configs/mem_user.py +58 -0
  15. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/graph_dbs/base.py +9 -1
  16. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/graph_dbs/factory.py +2 -0
  17. memoryos-0.2.2/src/memos/graph_dbs/nebular.py +1364 -0
  18. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/graph_dbs/neo4j.py +4 -4
  19. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/log.py +1 -1
  20. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_cube/utils.py +13 -6
  21. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_os/core.py +140 -30
  22. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_os/main.py +1 -1
  23. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_os/product.py +266 -152
  24. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_os/utils/format_utils.py +314 -67
  25. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_reader/simple_struct.py +13 -5
  26. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_scheduler/base_scheduler.py +220 -250
  27. memoryos-0.2.2/src/memos/mem_scheduler/general_scheduler.py +306 -0
  28. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_scheduler/modules/base.py +5 -5
  29. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_scheduler/modules/dispatcher.py +6 -9
  30. memoryos-0.2.2/src/memos/mem_scheduler/modules/misc.py +104 -0
  31. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_scheduler/modules/monitor.py +52 -41
  32. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_scheduler/modules/rabbitmq_service.py +9 -7
  33. memoryos-0.2.2/src/memos/mem_scheduler/modules/retriever.py +185 -0
  34. memoryos-0.2.2/src/memos/mem_scheduler/modules/scheduler_logger.py +255 -0
  35. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_scheduler/mos_for_test_scheduler.py +16 -19
  36. memoryos-0.2.2/src/memos/mem_scheduler/schemas/general_schemas.py +43 -0
  37. memoryos-0.2.2/src/memos/mem_scheduler/schemas/message_schemas.py +148 -0
  38. memoryos-0.2.2/src/memos/mem_scheduler/schemas/monitor_schemas.py +329 -0
  39. memoryos-0.2.2/src/memos/mem_scheduler/utils/filter_utils.py +176 -0
  40. memoryos-0.2.2/src/memos/mem_scheduler/utils/misc_utils.py +61 -0
  41. memoryos-0.2.2/src/memos/mem_user/factory.py +94 -0
  42. memoryos-0.2.2/src/memos/mem_user/mysql_persistent_user_manager.py +271 -0
  43. memoryos-0.2.2/src/memos/mem_user/mysql_user_manager.py +500 -0
  44. memoryos-0.2.2/src/memos/mem_user/persistent_factory.py +96 -0
  45. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_user/user_manager.py +4 -4
  46. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/activation/item.py +4 -0
  47. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/base.py +1 -1
  48. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/general.py +35 -91
  49. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/item.py +5 -33
  50. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree.py +13 -7
  51. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/organize/conflict.py +4 -2
  52. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/organize/relation_reason_detector.py +47 -43
  53. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/organize/reorganizer.py +8 -5
  54. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/retrieve/internet_retriever.py +6 -3
  55. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/retrieve/internet_retriever_factory.py +2 -0
  56. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/retrieve/retrieval_mid_structs.py +2 -0
  57. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/retrieve/searcher.py +46 -23
  58. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/retrieve/task_goal_parser.py +42 -15
  59. memoryos-0.2.2/src/memos/memories/textual/tree_text_memory/retrieve/utils.py +52 -0
  60. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/retrieve/xinyusearch.py +62 -58
  61. memoryos-0.2.2/src/memos/memos_tools/dinding_report_bot.py +422 -0
  62. memoryos-0.2.2/src/memos/memos_tools/notification_service.py +44 -0
  63. memoryos-0.2.2/src/memos/memos_tools/notification_utils.py +96 -0
  64. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/settings.py +3 -1
  65. memoryos-0.2.2/src/memos/templates/__init__.py +0 -0
  66. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/templates/mem_reader_prompts.py +2 -1
  67. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/templates/mem_scheduler_prompts.py +41 -7
  68. memoryos-0.2.2/src/memos/templates/mos_prompts.py +150 -0
  69. memoryos-0.2.2/src/memos/vec_dbs/__init__.py +0 -0
  70. memoryos-0.2.1/src/memos/mem_scheduler/general_scheduler.py +0 -186
  71. memoryos-0.2.1/src/memos/mem_scheduler/modules/misc.py +0 -39
  72. memoryos-0.2.1/src/memos/mem_scheduler/modules/retriever.py +0 -268
  73. memoryos-0.2.1/src/memos/mem_scheduler/modules/schemas.py +0 -328
  74. memoryos-0.2.1/src/memos/mem_scheduler/utils.py +0 -75
  75. memoryos-0.2.1/src/memos/memories/textual/tree_text_memory/retrieve/utils.py +0 -48
  76. memoryos-0.2.1/src/memos/templates/mos_prompts.py +0 -63
  77. {memoryos-0.2.1 → memoryos-0.2.2}/LICENSE +0 -0
  78. {memoryos-0.2.1 → memoryos-0.2.2}/README.md +0 -0
  79. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/api/exceptions.py +0 -0
  80. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/api/mcp_serve.py +0 -0
  81. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/api/product_api.py +0 -0
  82. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/api/routers/__init__.py +0 -0
  83. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/api/start_api.py +0 -0
  84. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/chunkers/__init__.py +0 -0
  85. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/chunkers/base.py +0 -0
  86. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/chunkers/factory.py +0 -0
  87. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/chunkers/sentence_chunker.py +0 -0
  88. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/cli.py +0 -0
  89. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/__init__.py +0 -0
  90. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/base.py +0 -0
  91. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/chunker.py +0 -0
  92. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/embedder.py +0 -0
  93. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/llm.py +0 -0
  94. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/mem_chat.py +0 -0
  95. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/mem_cube.py +0 -0
  96. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/memory.py +0 -0
  97. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/parser.py +0 -0
  98. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/utils.py +0 -0
  99. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/configs/vec_db.py +0 -0
  100. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/dependency.py +0 -0
  101. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/deprecation.py +0 -0
  102. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/embedders/__init__.py +0 -0
  103. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/embedders/ark.py +0 -0
  104. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/embedders/base.py +0 -0
  105. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/embedders/factory.py +0 -0
  106. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/embedders/ollama.py +0 -0
  107. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/embedders/sentence_transformer.py +0 -0
  108. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/embedders/universal_api.py +0 -0
  109. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/exceptions.py +0 -0
  110. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/graph_dbs/__init__.py +0 -0
  111. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/graph_dbs/item.py +0 -0
  112. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/graph_dbs/neo4j_community.py +0 -0
  113. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/hello_world.py +0 -0
  114. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/llms/__init__.py +0 -0
  115. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/llms/base.py +0 -0
  116. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/llms/deepseek.py +0 -0
  117. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/llms/factory.py +0 -0
  118. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/llms/hf.py +0 -0
  119. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/llms/hf_singleton.py +0 -0
  120. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/llms/ollama.py +0 -0
  121. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/llms/openai.py +0 -0
  122. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/llms/qwen.py +0 -0
  123. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/llms/utils.py +0 -0
  124. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/llms/vllm.py +0 -0
  125. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_chat/__init__.py +0 -0
  126. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_chat/base.py +0 -0
  127. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_chat/factory.py +0 -0
  128. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_chat/simple.py +0 -0
  129. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_cube/__init__.py +0 -0
  130. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_cube/base.py +0 -0
  131. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_cube/general.py +0 -0
  132. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_os/client.py +0 -0
  133. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_os/utils/default_config.py +0 -0
  134. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_reader/__init__.py +0 -0
  135. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_reader/base.py +0 -0
  136. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_reader/factory.py +0 -0
  137. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_reader/memory.py +0 -0
  138. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_scheduler/__init__.py +0 -0
  139. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_scheduler/modules/__init__.py +0 -0
  140. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_scheduler/modules/redis_service.py +0 -0
  141. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_scheduler/scheduler_factory.py +0 -0
  142. {memoryos-0.2.1/src/memos/memories → memoryos-0.2.2/src/memos/mem_scheduler/schemas}/__init__.py +0 -0
  143. {memoryos-0.2.1/src/memos/memories/activation → memoryos-0.2.2/src/memos/mem_scheduler/utils}/__init__.py +0 -0
  144. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/mem_user/persistent_user_manager.py +0 -0
  145. {memoryos-0.2.1/src/memos/memories/parametric → memoryos-0.2.2/src/memos/memories}/__init__.py +0 -0
  146. {memoryos-0.2.1/src/memos/memories/textual → memoryos-0.2.2/src/memos/memories/activation}/__init__.py +0 -0
  147. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/activation/base.py +0 -0
  148. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/activation/kv.py +0 -0
  149. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/activation/vllmkv.py +0 -0
  150. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/base.py +0 -0
  151. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/factory.py +0 -0
  152. {memoryos-0.2.1/src/memos/memories/textual/tree_text_memory → memoryos-0.2.2/src/memos/memories/parametric}/__init__.py +0 -0
  153. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/parametric/base.py +0 -0
  154. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/parametric/item.py +0 -0
  155. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/parametric/lora.py +0 -0
  156. {memoryos-0.2.1/src/memos/memories/textual/tree_text_memory/organize → memoryos-0.2.2/src/memos/memories/textual}/__init__.py +0 -0
  157. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/naive.py +0 -0
  158. {memoryos-0.2.1/src/memos/memories/textual/tree_text_memory/retrieve → memoryos-0.2.2/src/memos/memories/textual/tree_text_memory}/__init__.py +0 -0
  159. {memoryos-0.2.1/src/memos/parsers → memoryos-0.2.2/src/memos/memories/textual/tree_text_memory/organize}/__init__.py +0 -0
  160. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/organize/manager.py +0 -0
  161. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/organize/redundancy.py +0 -0
  162. {memoryos-0.2.1/src/memos/templates → memoryos-0.2.2/src/memos/memories/textual/tree_text_memory/retrieve}/__init__.py +0 -0
  163. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/retrieve/reasoner.py +0 -0
  164. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/retrieve/recall.py +0 -0
  165. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/memories/textual/tree_text_memory/retrieve/reranker.py +0 -0
  166. {memoryos-0.2.1/src/memos/vec_dbs → memoryos-0.2.2/src/memos/parsers}/__init__.py +0 -0
  167. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/parsers/base.py +0 -0
  168. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/parsers/factory.py +0 -0
  169. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/parsers/markitdown.py +0 -0
  170. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/templates/tree_reorganize_prompts.py +0 -0
  171. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/types.py +0 -0
  172. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/vec_dbs/base.py +0 -0
  173. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/vec_dbs/factory.py +0 -0
  174. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/vec_dbs/item.py +0 -0
  175. {memoryos-0.2.1 → memoryos-0.2.2}/src/memos/vec_dbs/qdrant.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: MemoryOS
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Intelligence Begins with Memory
5
5
  License: Apache-2.0
6
6
  Keywords: memory,llm,language model,memoryOS,agent,kv cache,lora
@@ -35,6 +35,7 @@ Requires-Dist: ollama (>=0.4.8,<0.5.0)
35
35
  Requires-Dist: openai (>=1.77.0,<2.0.0)
36
36
  Requires-Dist: pika (>=1.3.2,<2.0.0) ; extra == "all"
37
37
  Requires-Dist: pika (>=1.3.2,<2.0.0) ; extra == "mem-scheduler"
38
+ Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
38
39
  Requires-Dist: qdrant-client (>=1.14.2,<2.0.0) ; extra == "all"
39
40
  Requires-Dist: redis (>=6.2.0,<7.0.0) ; extra == "all"
40
41
  Requires-Dist: redis (>=6.2.0,<7.0.0) ; extra == "mem-scheduler"
@@ -4,7 +4,7 @@
4
4
  ##############################################################################
5
5
 
6
6
  name = "MemoryOS"
7
- version = "0.2.1"
7
+ version = "0.2.2"
8
8
  description = "Intelligence Begins with Memory"
9
9
  license = {text = "Apache-2.0"}
10
10
  readme = "README.md"
@@ -44,6 +44,7 @@ dependencies = [
44
44
  "sqlalchemy (>=2.0.41,<3.0.0)", # SQL toolkit
45
45
  "scikit-learn (>=1.7.0,<2.0.0)", # Machine learning
46
46
  "fastmcp (>=2.10.5,<3.0.0)",
47
+ "python-dateutil (>=2.9.0.post0,<3.0.0)",
47
48
  ]
48
49
 
49
50
  [project.urls]
@@ -1,4 +1,4 @@
1
- __version__ = "0.2.1"
1
+ __version__ = "0.2.2"
2
2
 
3
3
  from memos.configs.mem_cube import GeneralMemCubeConfig
4
4
  from memos.configs.mem_os import MOSConfig
@@ -1,3 +1,4 @@
1
+ import json
1
2
  import os
2
3
 
3
4
  from typing import Any
@@ -115,6 +116,48 @@ class APIConfig:
115
116
  },
116
117
  }
117
118
 
119
+ @staticmethod
120
+ def get_internet_config() -> dict[str, Any]:
121
+ """Get embedder configuration."""
122
+ return {
123
+ "backend": "xinyu",
124
+ "config": {
125
+ "api_key": os.getenv("XINYU_API_KEY"),
126
+ "search_engine_id": os.getenv("XINYU_SEARCH_ENGINE_ID"),
127
+ "max_results": 15,
128
+ "num_per_request": 10,
129
+ "reader": {
130
+ "backend": "simple_struct",
131
+ "config": {
132
+ "llm": {
133
+ "backend": "openai",
134
+ "config": {
135
+ "model_name_or_path": os.getenv("MEMRADER_MODEL"),
136
+ "temperature": 0.6,
137
+ "max_tokens": 5000,
138
+ "top_p": 0.95,
139
+ "top_k": 20,
140
+ "api_key": "EMPTY",
141
+ "api_base": os.getenv("MEMRADER_API_BASE"),
142
+ "remove_think_prefix": True,
143
+ "extra_body": {"chat_template_kwargs": {"enable_thinking": False}},
144
+ },
145
+ },
146
+ "embedder": APIConfig.get_embedder_config(),
147
+ "chunker": {
148
+ "backend": "sentence",
149
+ "config": {
150
+ "tokenizer_or_token_counter": "gpt2",
151
+ "chunk_size": 512,
152
+ "chunk_overlap": 128,
153
+ "min_sentences_per_chunk": 1,
154
+ },
155
+ },
156
+ },
157
+ },
158
+ },
159
+ }
160
+
118
161
  @staticmethod
119
162
  def get_neo4j_community_config(user_id: str | None = None) -> dict[str, Any]:
120
163
  """Get Neo4j community configuration."""
@@ -126,14 +169,14 @@ class APIConfig:
126
169
  "user_name": f"memos{user_id.replace('-', '')}",
127
170
  "auto_create": True,
128
171
  "use_multi_db": False,
129
- "embedding_dimension": 3072,
172
+ "embedding_dimension": int(os.getenv("EMBEDDING_DIMENSION", 3072)),
130
173
  "vec_config": {
131
174
  # Pass nested config to initialize external vector DB
132
175
  # If you use qdrant, please use Server instead of local mode.
133
176
  "backend": "qdrant",
134
177
  "config": {
135
178
  "collection_name": "neo4j_vec_db",
136
- "vector_dimension": 3072,
179
+ "vector_dimension": int(os.getenv("EMBEDDING_DIMENSION", 3072)),
137
180
  "distance_metric": "cosine",
138
181
  "host": "localhost",
139
182
  "port": 6333,
@@ -159,7 +202,7 @@ class APIConfig:
159
202
  "password": os.getenv("NEO4J_PASSWORD", "12345678"),
160
203
  "auto_create": True,
161
204
  "use_multi_db": True,
162
- "embedding_dimension": 3072,
205
+ "embedding_dimension": int(os.getenv("EMBEDDING_DIMENSION", 3072)),
163
206
  }
164
207
 
165
208
  @staticmethod
@@ -173,7 +216,33 @@ class APIConfig:
173
216
  "user_name": f"memos{user_id.replace('-', '')}",
174
217
  "auto_create": True,
175
218
  "use_multi_db": False,
176
- "embedding_dimension": 3072,
219
+ "embedding_dimension": int(os.getenv("EMBEDDING_DIMENSION", 3072)),
220
+ }
221
+
222
+ @staticmethod
223
+ def get_nebular_config(user_id: str | None = None) -> dict[str, Any]:
224
+ """Get Nebular configuration."""
225
+ return {
226
+ "uri": json.loads(os.getenv("NEBULAR_HOSTS", '["localhost"]')),
227
+ "user": os.getenv("NEBULAR_USER", "root"),
228
+ "password": os.getenv("NEBULAR_PASSWORD", "xxxxxx"),
229
+ "space": os.getenv("NEBULAR_SPACE", "shared-tree-textual-memory"),
230
+ "user_name": f"memos{user_id.replace('-', '')}",
231
+ "use_multi_db": False,
232
+ "auto_create": True,
233
+ "embedding_dimension": int(os.getenv("EMBEDDING_DIMENSION", 3072)),
234
+ }
235
+
236
+ @staticmethod
237
+ def get_mysql_config() -> dict[str, Any]:
238
+ """Get MySQL configuration."""
239
+ return {
240
+ "host": os.getenv("MYSQL_HOST", "localhost"),
241
+ "port": int(os.getenv("MYSQL_PORT", "3306")),
242
+ "username": os.getenv("MYSQL_USERNAME", "root"),
243
+ "password": os.getenv("MYSQL_PASSWORD", "12345678"),
244
+ "database": os.getenv("MYSQL_DATABASE", "memos_users"),
245
+ "charset": os.getenv("MYSQL_CHARSET", "utf8mb4"),
177
246
  }
178
247
 
179
248
  @staticmethod
@@ -212,6 +281,34 @@ class APIConfig:
212
281
  """Check if default cube config is enabled via environment variable."""
213
282
  return os.getenv("MOS_ENABLE_DEFAULT_CUBE_CONFIG", "false").lower() == "true"
214
283
 
284
+ @staticmethod
285
+ def is_dingding_bot_enabled() -> bool:
286
+ """Check if DingDing bot is enabled via environment variable."""
287
+ return os.getenv("ENABLE_DINGDING_BOT", "false").lower() == "true"
288
+
289
+ @staticmethod
290
+ def get_dingding_bot_config() -> dict[str, Any] | None:
291
+ """Get DingDing bot configuration if enabled."""
292
+ if not APIConfig.is_dingding_bot_enabled():
293
+ return None
294
+
295
+ return {
296
+ "enabled": True,
297
+ "access_token_user": os.getenv("DINGDING_ACCESS_TOKEN_USER", ""),
298
+ "secret_user": os.getenv("DINGDING_SECRET_USER", ""),
299
+ "access_token_error": os.getenv("DINGDING_ACCESS_TOKEN_ERROR", ""),
300
+ "secret_error": os.getenv("DINGDING_SECRET_ERROR", ""),
301
+ "robot_code": os.getenv("DINGDING_ROBOT_CODE", ""),
302
+ "app_key": os.getenv("DINGDING_APP_KEY", ""),
303
+ "app_secret": os.getenv("DINGDING_APP_SECRET", ""),
304
+ "oss_endpoint": os.getenv("OSS_ENDPOINT", ""),
305
+ "oss_region": os.getenv("OSS_REGION", ""),
306
+ "oss_bucket_name": os.getenv("OSS_BUCKET_NAME", ""),
307
+ "oss_access_key_id": os.getenv("OSS_ACCESS_KEY_ID", ""),
308
+ "oss_access_key_secret": os.getenv("OSS_ACCESS_KEY_SECRET", ""),
309
+ "oss_public_base_url": os.getenv("OSS_PUBLIC_BASE_URL", ""),
310
+ }
311
+
215
312
  @staticmethod
216
313
  def get_product_default_config() -> dict[str, Any]:
217
314
  """Get default configuration for Product API."""
@@ -224,6 +321,7 @@ class APIConfig:
224
321
  "vllm": vllm_config,
225
322
  }
226
323
  backend = os.getenv("MOS_CHAT_MODEL_PROVIDER", "openai")
324
+ mysql_config = APIConfig.get_mysql_config()
227
325
  config = {
228
326
  "user_id": os.getenv("MOS_USER_ID", "root"),
229
327
  "chat_model": {"backend": backend, "config": backend_model[backend]},
@@ -260,6 +358,13 @@ class APIConfig:
260
358
  else:
261
359
  config["enable_mem_scheduler"] = False
262
360
 
361
+ # Add user manager configuration if enabled
362
+ if os.getenv("MOS_USER_MANAGER_BACKEND", "sqlite").lower() == "mysql":
363
+ config["user_manager"] = {
364
+ "backend": "mysql",
365
+ "config": mysql_config,
366
+ }
367
+
263
368
  return config
264
369
 
265
370
  @staticmethod
@@ -300,9 +405,9 @@ class APIConfig:
300
405
  def create_user_config(user_name: str, user_id: str) -> tuple[MOSConfig, GeneralMemCube]:
301
406
  """Create configuration for a specific user."""
302
407
  openai_config = APIConfig.get_openai_config()
303
-
304
408
  qwen_config = APIConfig.qwen_config()
305
409
  vllm_config = APIConfig.vllm_config()
410
+ mysql_config = APIConfig.get_mysql_config()
306
411
  backend = os.getenv("MOS_CHAT_MODEL_PROVIDER", "openai")
307
412
  backend_model = {
308
413
  "openai": openai_config,
@@ -341,7 +446,6 @@ class APIConfig:
341
446
  "top_k": 30,
342
447
  "max_turns_window": 20,
343
448
  }
344
-
345
449
  # Add scheduler configuration if enabled
346
450
  if APIConfig.is_scheduler_enabled():
347
451
  config_dict["mem_scheduler"] = APIConfig.get_scheduler_config()
@@ -349,11 +453,32 @@ class APIConfig:
349
453
  else:
350
454
  config_dict["enable_mem_scheduler"] = False
351
455
 
456
+ # Add user manager configuration if enabled
457
+ if os.getenv("MOS_USER_MANAGER_BACKEND", "sqlite").lower() == "mysql":
458
+ config_dict["user_manager"] = {
459
+ "backend": "mysql",
460
+ "config": mysql_config,
461
+ }
462
+
352
463
  default_config = MOSConfig(**config_dict)
353
464
 
354
- if os.getenv("NEO4J_BACKEND", "neo4j_community").lower() == "neo4j_community":
355
- neo4j_community_config = APIConfig.get_neo4j_community_config(user_id)
465
+ neo4j_community_config = APIConfig.get_neo4j_community_config(user_id)
466
+ neo4j_config = APIConfig.get_neo4j_config(user_id)
467
+ nebular_config = APIConfig.get_nebular_config(user_id)
468
+ internet_config = (
469
+ APIConfig.get_internet_config()
470
+ if os.getenv("ENABLE_INTERNET", "false").lower() == "true"
471
+ else None
472
+ )
473
+ graph_db_backend_map = {
474
+ "neo4j-community": neo4j_community_config,
475
+ "neo4j": neo4j_config,
476
+ "nebular": nebular_config,
477
+ }
478
+ graph_db_backend = os.getenv("NEO4J_BACKEND", "neo4j-community").lower()
479
+ if graph_db_backend in graph_db_backend_map:
356
480
  # Create MemCube config
481
+
357
482
  default_cube_config = GeneralMemCubeConfig.model_validate(
358
483
  {
359
484
  "user_id": user_id,
@@ -364,10 +489,11 @@ class APIConfig:
364
489
  "extractor_llm": {"backend": "openai", "config": openai_config},
365
490
  "dispatcher_llm": {"backend": "openai", "config": openai_config},
366
491
  "graph_db": {
367
- "backend": "neo4j-community",
368
- "config": neo4j_community_config,
492
+ "backend": graph_db_backend,
493
+ "config": graph_db_backend_map[graph_db_backend],
369
494
  },
370
495
  "embedder": APIConfig.get_embedder_config(),
496
+ "internet_retriever": internet_config,
371
497
  },
372
498
  },
373
499
  "act_mem": {}
@@ -377,31 +503,7 @@ class APIConfig:
377
503
  }
378
504
  )
379
505
  else:
380
- neo4j_config = APIConfig.get_neo4j_config(user_id)
381
- # Create MemCube config
382
- default_cube_config = GeneralMemCubeConfig.model_validate(
383
- {
384
- "user_id": user_id,
385
- "cube_id": f"{user_name}_default_cube",
386
- "text_mem": {
387
- "backend": "tree_text",
388
- "config": {
389
- "extractor_llm": {"backend": "openai", "config": openai_config},
390
- "dispatcher_llm": {"backend": "openai", "config": openai_config},
391
- "graph_db": {
392
- "backend": "neo4j",
393
- "config": neo4j_config,
394
- },
395
- "embedder": APIConfig.get_embedder_config(),
396
- },
397
- },
398
- "act_mem": {}
399
- if os.getenv("ENABLE_ACTIVATION_MEMORY", "false").lower() == "false"
400
- else APIConfig.get_activation_vllm_config(),
401
- "para_mem": {},
402
- }
403
- )
404
-
506
+ raise ValueError(f"Invalid Neo4j backend: {graph_db_backend}")
405
507
  default_mem_cube = GeneralMemCube(default_cube_config)
406
508
  return default_config, default_mem_cube
407
509
 
@@ -416,9 +518,21 @@ class APIConfig:
416
518
  return None
417
519
 
418
520
  openai_config = APIConfig.get_openai_config()
419
-
420
- if os.getenv("NEO4J_BACKEND", "neo4j_community").lower() == "neo4j_community":
421
- neo4j_community_config = APIConfig.get_neo4j_community_config(user_id="default")
521
+ neo4j_community_config = APIConfig.get_neo4j_community_config(user_id="default")
522
+ neo4j_config = APIConfig.get_neo4j_config(user_id="default")
523
+ nebular_config = APIConfig.get_nebular_config(user_id="default")
524
+ graph_db_backend_map = {
525
+ "neo4j-community": neo4j_community_config,
526
+ "neo4j": neo4j_config,
527
+ "nebular": nebular_config,
528
+ }
529
+ internet_config = (
530
+ APIConfig.get_internet_config()
531
+ if os.getenv("ENABLE_INTERNET", "false").lower() == "true"
532
+ else None
533
+ )
534
+ graph_db_backend = os.getenv("NEO4J_BACKEND", "neo4j-community").lower()
535
+ if graph_db_backend in graph_db_backend_map:
422
536
  return GeneralMemCubeConfig.model_validate(
423
537
  {
424
538
  "user_id": "default",
@@ -429,12 +543,13 @@ class APIConfig:
429
543
  "extractor_llm": {"backend": "openai", "config": openai_config},
430
544
  "dispatcher_llm": {"backend": "openai", "config": openai_config},
431
545
  "graph_db": {
432
- "backend": "neo4j-community",
433
- "config": neo4j_community_config,
546
+ "backend": graph_db_backend,
547
+ "config": graph_db_backend_map[graph_db_backend],
434
548
  },
435
549
  "embedder": APIConfig.get_embedder_config(),
436
550
  "reorganize": os.getenv("MOS_ENABLE_REORGANIZE", "false").lower()
437
551
  == "true",
552
+ "internet_retriever": internet_config,
438
553
  },
439
554
  },
440
555
  "act_mem": {}
@@ -444,28 +559,4 @@ class APIConfig:
444
559
  }
445
560
  )
446
561
  else:
447
- neo4j_config = APIConfig.get_neo4j_config(user_id="default")
448
- return GeneralMemCubeConfig.model_validate(
449
- {
450
- "user_id": "default",
451
- "cube_id": "default_cube",
452
- "text_mem": {
453
- "backend": "tree_text",
454
- "config": {
455
- "extractor_llm": {"backend": "openai", "config": openai_config},
456
- "dispatcher_llm": {"backend": "openai", "config": openai_config},
457
- "graph_db": {
458
- "backend": "neo4j",
459
- "config": neo4j_config,
460
- },
461
- "embedder": APIConfig.get_embedder_config(),
462
- "reorganize": os.getenv("MOS_ENABLE_REORGANIZE", "false").lower()
463
- == "true",
464
- },
465
- },
466
- "act_mem": {}
467
- if os.getenv("ENABLE_ACTIVATION_MEMORY", "false").lower() == "false"
468
- else APIConfig.get_activation_vllm_config(),
469
- "para_mem": {},
470
- }
471
- )
562
+ raise ValueError(f"Invalid Neo4j backend: {graph_db_backend}")
@@ -0,0 +1,147 @@
1
+ """
2
+ Global request context management for trace_id and request-scoped data.
3
+
4
+ This module provides optional trace_id functionality that can be enabled
5
+ when using the API components. It uses ContextVar to ensure thread safety
6
+ and request isolation.
7
+ """
8
+
9
+ import uuid
10
+
11
+ from collections.abc import Callable
12
+ from contextvars import ContextVar
13
+ from typing import Any
14
+
15
+
16
+ # Global context variable for request-scoped data
17
+ _request_context: ContextVar[dict[str, Any] | None] = ContextVar("request_context", default=None)
18
+
19
+
20
+ class RequestContext:
21
+ """
22
+ Request-scoped context object that holds trace_id and other request data.
23
+
24
+ This provides a Flask g-like object for FastAPI applications.
25
+ """
26
+
27
+ def __init__(self, trace_id: str | None = None):
28
+ self.trace_id = trace_id or str(uuid.uuid4())
29
+ self._data: dict[str, Any] = {}
30
+
31
+ def set(self, key: str, value: Any) -> None:
32
+ """Set a value in the context."""
33
+ self._data[key] = value
34
+
35
+ def get(self, key: str, default: Any | None = None) -> Any:
36
+ """Get a value from the context."""
37
+ return self._data.get(key, default)
38
+
39
+ def __setattr__(self, name: str, value: Any) -> None:
40
+ if name.startswith("_") or name == "trace_id":
41
+ super().__setattr__(name, value)
42
+ else:
43
+ if not hasattr(self, "_data"):
44
+ super().__setattr__(name, value)
45
+ else:
46
+ self._data[name] = value
47
+
48
+ def __getattr__(self, name: str) -> Any:
49
+ if hasattr(self, "_data") and name in self._data:
50
+ return self._data[name]
51
+ raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")
52
+
53
+ def to_dict(self) -> dict[str, Any]:
54
+ """Convert context to dictionary."""
55
+ return {"trace_id": self.trace_id, "data": self._data.copy()}
56
+
57
+
58
+ def set_request_context(context: RequestContext) -> None:
59
+ """
60
+ Set the current request context.
61
+
62
+ This is typically called by the API dependency injection system.
63
+ """
64
+ _request_context.set(context.to_dict())
65
+
66
+
67
+ def get_current_trace_id() -> str | None:
68
+ """
69
+ Get the current request's trace_id.
70
+
71
+ Returns:
72
+ The trace_id if available, None otherwise.
73
+ """
74
+ context = _request_context.get()
75
+ if context:
76
+ return context.get("trace_id")
77
+ return None
78
+
79
+
80
+ def get_current_context() -> RequestContext | None:
81
+ """
82
+ Get the current request context.
83
+
84
+ Returns:
85
+ The current RequestContext if available, None otherwise.
86
+ """
87
+ context_dict = _request_context.get()
88
+ if context_dict:
89
+ ctx = RequestContext(trace_id=context_dict.get("trace_id"))
90
+ ctx._data = context_dict.get("data", {}).copy()
91
+ return ctx
92
+ return None
93
+
94
+
95
+ def require_context() -> RequestContext:
96
+ """
97
+ Get the current request context, raising an error if not available.
98
+
99
+ Returns:
100
+ The current RequestContext.
101
+
102
+ Raises:
103
+ RuntimeError: If called outside of a request context.
104
+ """
105
+ context = get_current_context()
106
+ if context is None:
107
+ raise RuntimeError(
108
+ "No request context available. This function must be called within a request handler."
109
+ )
110
+ return context
111
+
112
+
113
+ # Type for trace_id getter function
114
+ TraceIdGetter = Callable[[], str | None]
115
+
116
+ # Global variable to hold the trace_id getter function
117
+ _trace_id_getter: TraceIdGetter | None = None
118
+
119
+
120
+ def set_trace_id_getter(getter: TraceIdGetter) -> None:
121
+ """
122
+ Set a custom trace_id getter function.
123
+
124
+ This allows the logging system to retrieve trace_id without importing
125
+ API-specific modules.
126
+ """
127
+ global _trace_id_getter
128
+ _trace_id_getter = getter
129
+
130
+
131
+ def get_trace_id_for_logging() -> str | None:
132
+ """
133
+ Get trace_id for logging purposes.
134
+
135
+ This function is used by the logging system and will use either
136
+ the custom getter function or fall back to the default context.
137
+ """
138
+ if _trace_id_getter:
139
+ try:
140
+ return _trace_id_getter()
141
+ except Exception:
142
+ pass
143
+ return get_current_trace_id()
144
+
145
+
146
+ # Initialize the default trace_id getter
147
+ set_trace_id_getter(get_current_trace_id)
@@ -0,0 +1,90 @@
1
+ import logging
2
+
3
+ from fastapi import Depends, Header, Request
4
+
5
+ from memos.api.context.context import RequestContext, set_request_context
6
+
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ # Type alias for the RequestContext from context module
11
+ G = RequestContext
12
+
13
+
14
+ def get_trace_id_from_header(
15
+ trace_id: str | None = Header(None, alias="trace-id"),
16
+ x_trace_id: str | None = Header(None, alias="x-trace-id"),
17
+ g_trace_id: str | None = Header(None, alias="g-trace-id"),
18
+ ) -> str | None:
19
+ """
20
+ Extract trace_id from various possible headers.
21
+
22
+ Priority: g-trace-id > x-trace-id > trace-id
23
+ """
24
+ return g_trace_id or x_trace_id or trace_id
25
+
26
+
27
+ def get_request_context(
28
+ request: Request, trace_id: str | None = Depends(get_trace_id_from_header)
29
+ ) -> RequestContext:
30
+ """
31
+ Get request context object with trace_id and request metadata.
32
+
33
+ This function creates a RequestContext and automatically sets it
34
+ in the global context for use throughout the request lifecycle.
35
+ """
36
+ # Create context object
37
+ ctx = RequestContext(trace_id=trace_id)
38
+
39
+ # Set the context globally for this request
40
+ set_request_context(ctx)
41
+
42
+ # Log request start
43
+ logger.info(f"Request started with trace_id: {ctx.trace_id}")
44
+
45
+ # Add request metadata to context
46
+ ctx.set("method", request.method)
47
+ ctx.set("path", request.url.path)
48
+ ctx.set("client_ip", request.client.host if request.client else None)
49
+
50
+ return ctx
51
+
52
+
53
+ def get_g_object(trace_id: str | None = Depends(get_trace_id_from_header)) -> G:
54
+ """
55
+ Get Flask g-like object for the current request.
56
+
57
+ This creates a RequestContext and sets it globally for access
58
+ throughout the request lifecycle.
59
+ """
60
+ g = RequestContext(trace_id=trace_id)
61
+ set_request_context(g)
62
+ logger.info(f"Request g object created with trace_id: {g.trace_id}")
63
+ return g
64
+
65
+
66
+ def get_current_g() -> G | None:
67
+ """
68
+ Get the current request's g object from anywhere in the application.
69
+
70
+ Returns:
71
+ The current request's g object if available, None otherwise.
72
+ """
73
+ from memos.context import get_current_context
74
+
75
+ return get_current_context()
76
+
77
+
78
+ def require_g() -> G:
79
+ """
80
+ Get the current request's g object, raising an error if not available.
81
+
82
+ Returns:
83
+ The current request's g object.
84
+
85
+ Raises:
86
+ RuntimeError: If called outside of a request context.
87
+ """
88
+ from memos.context import require_context
89
+
90
+ return require_context()
@@ -83,11 +83,12 @@ class ChatRequest(BaseRequest):
83
83
  query: str = Field(..., description="Chat query message")
84
84
  mem_cube_id: str | None = Field(None, description="Cube ID to use for chat")
85
85
  history: list[MessageDict] | None = Field(None, description="Chat history")
86
+ internet_search: bool = Field(True, description="Whether to use internet search")
86
87
 
87
88
 
88
89
  class UserCreate(BaseRequest):
89
90
  user_name: str | None = Field(None, description="Name of the user")
90
- role: str = Field("user", description="Role of the user")
91
+ role: str = Field("USER", description="Role of the user")
91
92
  user_id: str = Field(..., description="User ID")
92
93
 
93
94
 
@@ -142,6 +143,8 @@ class MemoryCreateRequest(BaseRequest):
142
143
  memory_content: str | None = Field(None, description="Memory content to store")
143
144
  doc_path: str | None = Field(None, description="Path to document to store")
144
145
  mem_cube_id: str | None = Field(None, description="Cube ID")
146
+ source: str | None = Field(None, description="Source of the memory")
147
+ user_profile: bool = Field(False, description="User profile memory")
145
148
 
146
149
 
147
150
  class SearchRequest(BaseRequest):
@@ -150,6 +153,7 @@ class SearchRequest(BaseRequest):
150
153
  user_id: str = Field(..., description="User ID")
151
154
  query: str = Field(..., description="Search query")
152
155
  mem_cube_id: str | None = Field(None, description="Cube ID to search in")
156
+ top_k: int = Field(10, description="Number of results to return")
153
157
 
154
158
 
155
159
  class SuggestionRequest(BaseRequest):