MemoryOS 0.2.1__py3-none-any.whl → 1.0.0__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.

Potentially problematic release.


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

Files changed (92) hide show
  1. {memoryos-0.2.1.dist-info → memoryos-1.0.0.dist-info}/METADATA +7 -1
  2. {memoryos-0.2.1.dist-info → memoryos-1.0.0.dist-info}/RECORD +87 -64
  3. memos/__init__.py +1 -1
  4. memos/api/config.py +158 -69
  5. memos/api/context/context.py +147 -0
  6. memos/api/context/dependencies.py +101 -0
  7. memos/api/product_models.py +5 -1
  8. memos/api/routers/product_router.py +54 -26
  9. memos/configs/graph_db.py +49 -1
  10. memos/configs/internet_retriever.py +19 -0
  11. memos/configs/mem_os.py +5 -0
  12. memos/configs/mem_reader.py +9 -0
  13. memos/configs/mem_scheduler.py +54 -18
  14. memos/configs/mem_user.py +58 -0
  15. memos/graph_dbs/base.py +38 -3
  16. memos/graph_dbs/factory.py +2 -0
  17. memos/graph_dbs/nebular.py +1612 -0
  18. memos/graph_dbs/neo4j.py +18 -9
  19. memos/log.py +6 -1
  20. memos/mem_cube/utils.py +13 -6
  21. memos/mem_os/core.py +157 -37
  22. memos/mem_os/main.py +2 -2
  23. memos/mem_os/product.py +252 -201
  24. memos/mem_os/utils/default_config.py +1 -1
  25. memos/mem_os/utils/format_utils.py +281 -70
  26. memos/mem_os/utils/reference_utils.py +133 -0
  27. memos/mem_reader/simple_struct.py +13 -5
  28. memos/mem_scheduler/base_scheduler.py +239 -266
  29. memos/mem_scheduler/{modules → general_modules}/base.py +4 -5
  30. memos/mem_scheduler/{modules → general_modules}/dispatcher.py +57 -21
  31. memos/mem_scheduler/general_modules/misc.py +104 -0
  32. memos/mem_scheduler/{modules → general_modules}/rabbitmq_service.py +12 -10
  33. memos/mem_scheduler/{modules → general_modules}/redis_service.py +1 -1
  34. memos/mem_scheduler/general_modules/retriever.py +199 -0
  35. memos/mem_scheduler/general_modules/scheduler_logger.py +261 -0
  36. memos/mem_scheduler/general_scheduler.py +243 -80
  37. memos/mem_scheduler/monitors/__init__.py +0 -0
  38. memos/mem_scheduler/monitors/dispatcher_monitor.py +305 -0
  39. memos/mem_scheduler/{modules/monitor.py → monitors/general_monitor.py} +106 -57
  40. memos/mem_scheduler/mos_for_test_scheduler.py +23 -20
  41. memos/mem_scheduler/schemas/__init__.py +0 -0
  42. memos/mem_scheduler/schemas/general_schemas.py +44 -0
  43. memos/mem_scheduler/schemas/message_schemas.py +149 -0
  44. memos/mem_scheduler/schemas/monitor_schemas.py +337 -0
  45. memos/mem_scheduler/utils/__init__.py +0 -0
  46. memos/mem_scheduler/utils/filter_utils.py +176 -0
  47. memos/mem_scheduler/utils/misc_utils.py +102 -0
  48. memos/mem_user/factory.py +94 -0
  49. memos/mem_user/mysql_persistent_user_manager.py +271 -0
  50. memos/mem_user/mysql_user_manager.py +500 -0
  51. memos/mem_user/persistent_factory.py +96 -0
  52. memos/mem_user/user_manager.py +4 -4
  53. memos/memories/activation/item.py +5 -1
  54. memos/memories/activation/kv.py +20 -8
  55. memos/memories/textual/base.py +2 -2
  56. memos/memories/textual/general.py +36 -92
  57. memos/memories/textual/item.py +5 -33
  58. memos/memories/textual/tree.py +13 -7
  59. memos/memories/textual/tree_text_memory/organize/{conflict.py → handler.py} +34 -50
  60. memos/memories/textual/tree_text_memory/organize/manager.py +8 -96
  61. memos/memories/textual/tree_text_memory/organize/relation_reason_detector.py +49 -43
  62. memos/memories/textual/tree_text_memory/organize/reorganizer.py +107 -142
  63. memos/memories/textual/tree_text_memory/retrieve/bochasearch.py +229 -0
  64. memos/memories/textual/tree_text_memory/retrieve/internet_retriever.py +6 -3
  65. memos/memories/textual/tree_text_memory/retrieve/internet_retriever_factory.py +11 -0
  66. memos/memories/textual/tree_text_memory/retrieve/recall.py +15 -8
  67. memos/memories/textual/tree_text_memory/retrieve/reranker.py +1 -1
  68. memos/memories/textual/tree_text_memory/retrieve/retrieval_mid_structs.py +2 -0
  69. memos/memories/textual/tree_text_memory/retrieve/searcher.py +191 -116
  70. memos/memories/textual/tree_text_memory/retrieve/task_goal_parser.py +47 -15
  71. memos/memories/textual/tree_text_memory/retrieve/utils.py +11 -7
  72. memos/memories/textual/tree_text_memory/retrieve/xinyusearch.py +62 -58
  73. memos/memos_tools/dinding_report_bot.py +422 -0
  74. memos/memos_tools/lockfree_dict.py +120 -0
  75. memos/memos_tools/notification_service.py +44 -0
  76. memos/memos_tools/notification_utils.py +96 -0
  77. memos/memos_tools/thread_safe_dict.py +288 -0
  78. memos/settings.py +3 -1
  79. memos/templates/mem_reader_prompts.py +4 -1
  80. memos/templates/mem_scheduler_prompts.py +62 -15
  81. memos/templates/mos_prompts.py +116 -0
  82. memos/templates/tree_reorganize_prompts.py +24 -17
  83. memos/utils.py +19 -0
  84. memos/mem_scheduler/modules/misc.py +0 -39
  85. memos/mem_scheduler/modules/retriever.py +0 -268
  86. memos/mem_scheduler/modules/schemas.py +0 -328
  87. memos/mem_scheduler/utils.py +0 -75
  88. memos/memories/textual/tree_text_memory/organize/redundancy.py +0 -193
  89. {memoryos-0.2.1.dist-info → memoryos-1.0.0.dist-info}/LICENSE +0 -0
  90. {memoryos-0.2.1.dist-info → memoryos-1.0.0.dist-info}/WHEEL +0 -0
  91. {memoryos-0.2.1.dist-info → memoryos-1.0.0.dist-info}/entry_points.txt +0 -0
  92. /memos/mem_scheduler/{modules → general_modules}/__init__.py +0 -0
@@ -6,12 +6,12 @@ from typing import Any, ClassVar
6
6
  from pydantic import ConfigDict, Field, field_validator, model_validator
7
7
 
8
8
  from memos.configs.base import BaseConfig
9
- from memos.mem_scheduler.modules.schemas import (
9
+ from memos.mem_scheduler.general_modules.misc import DictConversionMixin
10
+ from memos.mem_scheduler.schemas.general_schemas import (
10
11
  BASE_DIR,
11
12
  DEFAULT_ACT_MEM_DUMP_PATH,
12
13
  DEFAULT_CONSUME_INTERVAL_SECONDS,
13
14
  DEFAULT_THREAD__POOL_MAX_WORKERS,
14
- DictConversionMixin,
15
15
  )
16
16
 
17
17
 
@@ -21,7 +21,6 @@ class BaseSchedulerConfig(BaseConfig):
21
21
  top_k: int = Field(
22
22
  default=10, description="Number of top candidates to consider in initial retrieval"
23
23
  )
24
- top_n: int = Field(default=5, description="Number of final results to return after processing")
25
24
  enable_parallel_dispatch: bool = Field(
26
25
  default=True, description="Whether to enable parallel message processing using thread pool"
27
26
  )
@@ -44,19 +43,26 @@ class BaseSchedulerConfig(BaseConfig):
44
43
 
45
44
 
46
45
  class GeneralSchedulerConfig(BaseSchedulerConfig):
46
+ model_config = ConfigDict(extra="ignore", strict=True)
47
47
  act_mem_update_interval: int | None = Field(
48
48
  default=300, description="Interval in seconds for updating activation memory"
49
49
  )
50
50
  context_window_size: int | None = Field(
51
- default=5, description="Size of the context window for conversation history"
51
+ default=10, description="Size of the context window for conversation history"
52
52
  )
53
53
  act_mem_dump_path: str | None = Field(
54
54
  default=DEFAULT_ACT_MEM_DUMP_PATH, # Replace with DEFAULT_ACT_MEM_DUMP_PATH
55
55
  description="File path for dumping activation memory",
56
56
  )
57
- enable_act_memory_update: bool = Field(
57
+ enable_activation_memory: bool = Field(
58
58
  default=False, description="Whether to enable automatic activation memory updates"
59
59
  )
60
+ working_mem_monitor_capacity: int = Field(
61
+ default=30, description="Capacity of the working memory monitor"
62
+ )
63
+ activation_mem_monitor_capacity: int = Field(
64
+ default=20, description="Capacity of the activation memory monitor"
65
+ )
60
66
 
61
67
 
62
68
  class SchedulerConfigFactory(BaseConfig):
@@ -105,7 +111,20 @@ class RabbitMQConfig(
105
111
 
106
112
 
107
113
  class GraphDBAuthConfig(BaseConfig):
108
- uri: str = Field(default="localhost", description="URI for graph database access")
114
+ uri: str = Field(
115
+ default="bolt://localhost:7687",
116
+ description="URI for graph database access (e.g., bolt://host:port)",
117
+ )
118
+ user: str = Field(default="neo4j", description="Username for graph database authentication")
119
+ password: str = Field(
120
+ default="",
121
+ description="Password for graph database authentication",
122
+ min_length=8, # 建议密码最小长度
123
+ )
124
+ db_name: str = Field(default="neo4j", description="Database name to connect to")
125
+ auto_create: bool = Field(
126
+ default=True, description="Whether to automatically create the database if it doesn't exist"
127
+ )
109
128
 
110
129
 
111
130
  class OpenAIConfig(BaseConfig):
@@ -123,29 +142,46 @@ class AuthConfig(BaseConfig, DictConversionMixin):
123
142
  )
124
143
 
125
144
  @classmethod
126
- def from_local_yaml(cls, config_path: str | None = None) -> "AuthConfig":
145
+ def from_local_config(cls, config_path: str | Path | None = None) -> "AuthConfig":
127
146
  """
128
- Load configuration from YAML file
147
+ Load configuration from either a YAML or JSON file based on file extension.
148
+
149
+ Automatically detects file type (YAML or JSON) from the file extension
150
+ and uses the appropriate parser. If no path is provided, uses the default
151
+ configuration path (YAML) or its JSON counterpart.
129
152
 
130
153
  Args:
131
- config_path: Path to YAML configuration file
154
+ config_path: Optional path to configuration file.
155
+ If not provided, uses default configuration path.
132
156
 
133
157
  Returns:
134
- AuthConfig instance
158
+ AuthConfig instance populated with data from the configuration file.
135
159
 
136
160
  Raises:
137
- FileNotFoundError: If config file doesn't exist
138
- ValueError: If YAML parsing or validation fails
161
+ FileNotFoundError: If the specified or default configuration file does not exist.
162
+ ValueError: If file extension is not .yaml/.yml or .json, or if parsing fails.
139
163
  """
140
-
164
+ # Determine config path
141
165
  if config_path is None:
142
166
  config_path = cls.default_config_path
143
167
 
144
- # Check file exists
145
- if not Path(config_path).exists():
146
- raise FileNotFoundError(f"Config file not found: {config_path}")
147
-
148
- return cls.from_yaml_file(yaml_path=config_path)
168
+ # Validate file existence
169
+ config_path_obj = Path(config_path)
170
+ if not config_path_obj.exists():
171
+ raise FileNotFoundError(f"Configuration file not found: {config_path}")
172
+
173
+ # Get file extension and determine parser
174
+ file_ext = config_path_obj.suffix.lower()
175
+
176
+ if file_ext in (".yaml", ".yml"):
177
+ return cls.from_yaml_file(yaml_path=str(config_path_obj))
178
+ elif file_ext == ".json":
179
+ return cls.from_json_file(json_path=str(config_path_obj))
180
+ else:
181
+ raise ValueError(
182
+ f"Unsupported file format: {file_ext}. "
183
+ "Please use YAML (.yaml, .yml) or JSON (.json) files."
184
+ )
149
185
 
150
186
  def set_openai_config_to_environment(self):
151
187
  # Set environment variables
@@ -0,0 +1,58 @@
1
+ from typing import Any, ClassVar
2
+
3
+ from pydantic import BaseModel, Field, field_validator, model_validator
4
+
5
+ from memos.configs.base import BaseConfig
6
+
7
+
8
+ class BaseUserManagerConfig(BaseConfig):
9
+ """Base configuration class for user managers."""
10
+
11
+ user_id: str = Field(default="root", description="Default user ID for initialization")
12
+
13
+
14
+ class SQLiteUserManagerConfig(BaseUserManagerConfig):
15
+ """SQLite user manager configuration."""
16
+
17
+ db_path: str | None = Field(
18
+ default=None,
19
+ description="Path to SQLite database file. If None, uses default path in MEMOS_DIR",
20
+ )
21
+
22
+
23
+ class MySQLUserManagerConfig(BaseUserManagerConfig):
24
+ """MySQL user manager configuration."""
25
+
26
+ host: str = Field(default="localhost", description="MySQL server host")
27
+ port: int = Field(default=3306, description="MySQL server port")
28
+ username: str = Field(default="root", description="MySQL username")
29
+ password: str = Field(default="", description="MySQL password")
30
+ database: str = Field(default="memos_users", description="MySQL database name")
31
+ charset: str = Field(default="utf8mb4", description="MySQL charset")
32
+
33
+
34
+ class UserManagerConfigFactory(BaseModel):
35
+ """Factory for user manager configurations."""
36
+
37
+ backend: str = Field(default="sqlite", description="Backend for user manager")
38
+ config: dict[str, Any] = Field(
39
+ default_factory=dict, description="Configuration for the user manager backend"
40
+ )
41
+
42
+ backend_to_class: ClassVar[dict[str, Any]] = {
43
+ "sqlite": SQLiteUserManagerConfig,
44
+ "mysql": MySQLUserManagerConfig,
45
+ }
46
+
47
+ @field_validator("backend")
48
+ @classmethod
49
+ def validate_backend(cls, backend: str) -> str:
50
+ if backend not in cls.backend_to_class:
51
+ raise ValueError(f"Unsupported user manager backend: {backend}")
52
+ return backend
53
+
54
+ @model_validator(mode="after")
55
+ def instantiate_config(self):
56
+ config_class = self.backend_to_class[self.backend]
57
+ self.config = config_class(**self.config)
58
+ return self
memos/graph_dbs/base.py CHANGED
@@ -70,15 +70,27 @@ class BaseGraphDB(ABC):
70
70
 
71
71
  # Graph Query & Reasoning
72
72
  @abstractmethod
73
- def get_node(self, id: str) -> dict[str, Any] | None:
73
+ def get_node(self, id: str, include_embedding: bool = False) -> dict[str, Any] | None:
74
74
  """
75
75
  Retrieve the metadata and content of a node.
76
76
  Args:
77
77
  id: Node identifier.
78
+ include_embedding: with/without embedding
78
79
  Returns:
79
80
  Dictionary of node fields, or None if not found.
80
81
  """
81
82
 
83
+ @abstractmethod
84
+ def get_nodes(self, id: str, include_embedding: bool = False) -> dict[str, Any] | None:
85
+ """
86
+ Retrieve the metadata and memory of a list of nodes.
87
+ Args:
88
+ ids: List of Node identifier.
89
+ include_embedding: with/without embedding
90
+ Returns:
91
+ list[dict]: Parsed node records containing 'id', 'memory', and 'metadata'.
92
+ """
93
+
82
94
  @abstractmethod
83
95
  def get_neighbors(
84
96
  self, id: str, type: str, direction: Literal["in", "out", "both"] = "out"
@@ -146,7 +158,7 @@ class BaseGraphDB(ABC):
146
158
  """
147
159
 
148
160
  @abstractmethod
149
- def get_by_metadata(self, filters: dict[str, Any]) -> list[str]:
161
+ def get_by_metadata(self, filters: list[dict[str, Any]]) -> list[str]:
150
162
  """
151
163
  Retrieve node IDs that match given metadata filters.
152
164
 
@@ -162,6 +174,16 @@ class BaseGraphDB(ABC):
162
174
  - Can be used for faceted recall or prefiltering before embedding rerank.
163
175
  """
164
176
 
177
+ @abstractmethod
178
+ def get_structure_optimization_candidates(
179
+ self, scope: str, include_embedding: bool = False
180
+ ) -> list[dict]:
181
+ """
182
+ Find nodes that are likely candidates for structure optimization:
183
+ - Isolated nodes, nodes with empty background, or nodes with exactly one child.
184
+ - Plus: the child of any parent node that has exactly one child.
185
+ """
186
+
165
187
  # Structure Maintenance
166
188
  @abstractmethod
167
189
  def deduplicate_nodes(self) -> None:
@@ -197,7 +219,7 @@ class BaseGraphDB(ABC):
197
219
  """
198
220
 
199
221
  @abstractmethod
200
- def export_graph(self) -> dict[str, Any]:
222
+ def export_graph(self, include_embedding: bool = False) -> dict[str, Any]:
201
223
  """
202
224
  Export the entire graph as a serializable dictionary.
203
225
 
@@ -213,3 +235,16 @@ class BaseGraphDB(ABC):
213
235
  Args:
214
236
  data: A dictionary containing all nodes and edges to be loaded.
215
237
  """
238
+
239
+ @abstractmethod
240
+ def get_all_memory_items(self, scope: str, include_embedding: bool = False) -> list[dict]:
241
+ """
242
+ Retrieve all memory items of a specific memory_type.
243
+
244
+ Args:
245
+ scope (str): Must be one of 'WorkingMemory', 'LongTermMemory', or 'UserMemory'.
246
+ include_embedding: with/without embedding
247
+
248
+ Returns:
249
+ list[dict]: Full list of memory items under this scope.
250
+ """
@@ -2,6 +2,7 @@ from typing import Any, ClassVar
2
2
 
3
3
  from memos.configs.graph_db import GraphDBConfigFactory
4
4
  from memos.graph_dbs.base import BaseGraphDB
5
+ from memos.graph_dbs.nebular import NebulaGraphDB
5
6
  from memos.graph_dbs.neo4j import Neo4jGraphDB
6
7
  from memos.graph_dbs.neo4j_community import Neo4jCommunityGraphDB
7
8
 
@@ -12,6 +13,7 @@ class GraphStoreFactory(BaseGraphDB):
12
13
  backend_to_class: ClassVar[dict[str, Any]] = {
13
14
  "neo4j": Neo4jGraphDB,
14
15
  "neo4j-community": Neo4jCommunityGraphDB,
16
+ "nebular": NebulaGraphDB,
15
17
  }
16
18
 
17
19
  @classmethod