MemoryOS 0.0.1__py3-none-any.whl → 0.1.13__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 (124) hide show
  1. memoryos-0.1.13.dist-info/METADATA +288 -0
  2. memoryos-0.1.13.dist-info/RECORD +122 -0
  3. memos/__init__.py +20 -1
  4. memos/api/start_api.py +420 -0
  5. memos/chunkers/__init__.py +4 -0
  6. memos/chunkers/base.py +24 -0
  7. memos/chunkers/factory.py +22 -0
  8. memos/chunkers/sentence_chunker.py +35 -0
  9. memos/configs/__init__.py +0 -0
  10. memos/configs/base.py +82 -0
  11. memos/configs/chunker.py +45 -0
  12. memos/configs/embedder.py +53 -0
  13. memos/configs/graph_db.py +45 -0
  14. memos/configs/internet_retriever.py +81 -0
  15. memos/configs/llm.py +71 -0
  16. memos/configs/mem_chat.py +81 -0
  17. memos/configs/mem_cube.py +89 -0
  18. memos/configs/mem_os.py +74 -0
  19. memos/configs/mem_reader.py +53 -0
  20. memos/configs/mem_scheduler.py +78 -0
  21. memos/configs/memory.py +195 -0
  22. memos/configs/parser.py +38 -0
  23. memos/configs/utils.py +8 -0
  24. memos/configs/vec_db.py +64 -0
  25. memos/deprecation.py +262 -0
  26. memos/embedders/__init__.py +0 -0
  27. memos/embedders/base.py +15 -0
  28. memos/embedders/factory.py +23 -0
  29. memos/embedders/ollama.py +74 -0
  30. memos/embedders/sentence_transformer.py +40 -0
  31. memos/exceptions.py +30 -0
  32. memos/graph_dbs/__init__.py +0 -0
  33. memos/graph_dbs/base.py +215 -0
  34. memos/graph_dbs/factory.py +21 -0
  35. memos/graph_dbs/neo4j.py +827 -0
  36. memos/hello_world.py +97 -0
  37. memos/llms/__init__.py +0 -0
  38. memos/llms/base.py +16 -0
  39. memos/llms/factory.py +25 -0
  40. memos/llms/hf.py +231 -0
  41. memos/llms/ollama.py +82 -0
  42. memos/llms/openai.py +34 -0
  43. memos/llms/utils.py +14 -0
  44. memos/log.py +78 -0
  45. memos/mem_chat/__init__.py +0 -0
  46. memos/mem_chat/base.py +30 -0
  47. memos/mem_chat/factory.py +21 -0
  48. memos/mem_chat/simple.py +200 -0
  49. memos/mem_cube/__init__.py +0 -0
  50. memos/mem_cube/base.py +29 -0
  51. memos/mem_cube/general.py +146 -0
  52. memos/mem_cube/utils.py +24 -0
  53. memos/mem_os/client.py +5 -0
  54. memos/mem_os/core.py +819 -0
  55. memos/mem_os/main.py +503 -0
  56. memos/mem_os/product.py +89 -0
  57. memos/mem_reader/__init__.py +0 -0
  58. memos/mem_reader/base.py +27 -0
  59. memos/mem_reader/factory.py +21 -0
  60. memos/mem_reader/memory.py +298 -0
  61. memos/mem_reader/simple_struct.py +241 -0
  62. memos/mem_scheduler/__init__.py +0 -0
  63. memos/mem_scheduler/base_scheduler.py +164 -0
  64. memos/mem_scheduler/general_scheduler.py +305 -0
  65. memos/mem_scheduler/modules/__init__.py +0 -0
  66. memos/mem_scheduler/modules/base.py +74 -0
  67. memos/mem_scheduler/modules/dispatcher.py +103 -0
  68. memos/mem_scheduler/modules/monitor.py +82 -0
  69. memos/mem_scheduler/modules/redis_service.py +146 -0
  70. memos/mem_scheduler/modules/retriever.py +41 -0
  71. memos/mem_scheduler/modules/schemas.py +146 -0
  72. memos/mem_scheduler/scheduler_factory.py +21 -0
  73. memos/mem_scheduler/utils.py +26 -0
  74. memos/mem_user/user_manager.py +488 -0
  75. memos/memories/__init__.py +0 -0
  76. memos/memories/activation/__init__.py +0 -0
  77. memos/memories/activation/base.py +42 -0
  78. memos/memories/activation/item.py +25 -0
  79. memos/memories/activation/kv.py +232 -0
  80. memos/memories/base.py +19 -0
  81. memos/memories/factory.py +34 -0
  82. memos/memories/parametric/__init__.py +0 -0
  83. memos/memories/parametric/base.py +19 -0
  84. memos/memories/parametric/item.py +11 -0
  85. memos/memories/parametric/lora.py +41 -0
  86. memos/memories/textual/__init__.py +0 -0
  87. memos/memories/textual/base.py +89 -0
  88. memos/memories/textual/general.py +286 -0
  89. memos/memories/textual/item.py +167 -0
  90. memos/memories/textual/naive.py +185 -0
  91. memos/memories/textual/tree.py +321 -0
  92. memos/memories/textual/tree_text_memory/__init__.py +0 -0
  93. memos/memories/textual/tree_text_memory/organize/__init__.py +0 -0
  94. memos/memories/textual/tree_text_memory/organize/manager.py +305 -0
  95. memos/memories/textual/tree_text_memory/retrieve/__init__.py +0 -0
  96. memos/memories/textual/tree_text_memory/retrieve/internet_retriever.py +263 -0
  97. memos/memories/textual/tree_text_memory/retrieve/internet_retriever_factory.py +89 -0
  98. memos/memories/textual/tree_text_memory/retrieve/reasoner.py +61 -0
  99. memos/memories/textual/tree_text_memory/retrieve/recall.py +158 -0
  100. memos/memories/textual/tree_text_memory/retrieve/reranker.py +111 -0
  101. memos/memories/textual/tree_text_memory/retrieve/retrieval_mid_structs.py +13 -0
  102. memos/memories/textual/tree_text_memory/retrieve/searcher.py +208 -0
  103. memos/memories/textual/tree_text_memory/retrieve/task_goal_parser.py +68 -0
  104. memos/memories/textual/tree_text_memory/retrieve/utils.py +48 -0
  105. memos/memories/textual/tree_text_memory/retrieve/xinyusearch.py +335 -0
  106. memos/parsers/__init__.py +0 -0
  107. memos/parsers/base.py +15 -0
  108. memos/parsers/factory.py +19 -0
  109. memos/parsers/markitdown.py +22 -0
  110. memos/settings.py +8 -0
  111. memos/templates/__init__.py +0 -0
  112. memos/templates/mem_reader_prompts.py +98 -0
  113. memos/templates/mem_scheduler_prompts.py +65 -0
  114. memos/templates/mos_prompts.py +63 -0
  115. memos/types.py +55 -0
  116. memos/vec_dbs/__init__.py +0 -0
  117. memos/vec_dbs/base.py +105 -0
  118. memos/vec_dbs/factory.py +21 -0
  119. memos/vec_dbs/item.py +43 -0
  120. memos/vec_dbs/qdrant.py +292 -0
  121. memoryos-0.0.1.dist-info/METADATA +0 -53
  122. memoryos-0.0.1.dist-info/RECORD +0 -5
  123. {memoryos-0.0.1.dist-info → memoryos-0.1.13.dist-info}/LICENSE +0 -0
  124. {memoryos-0.0.1.dist-info → memoryos-0.1.13.dist-info}/WHEEL +0 -0
@@ -0,0 +1,45 @@
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 BaseGraphDBConfig(BaseConfig):
9
+ """Base class for all graph database configurations."""
10
+
11
+ uri: str
12
+ user: str
13
+ password: str
14
+
15
+
16
+ class Neo4jGraphDBConfig(BaseGraphDBConfig):
17
+ """Neo4j-specific configuration."""
18
+
19
+ db_name: str = Field(..., description="The name of the target Neo4j database")
20
+ auto_create: bool = Field(
21
+ default=False, description="Whether to create the DB if it doesn't exist"
22
+ )
23
+ embedding_dimension: int = Field(default=768, description="Dimension of vector embedding")
24
+
25
+
26
+ class GraphDBConfigFactory(BaseModel):
27
+ backend: str = Field(..., description="Backend for graph database")
28
+ config: dict[str, Any] = Field(..., description="Configuration for the graph database backend")
29
+
30
+ backend_to_class: ClassVar[dict[str, Any]] = {
31
+ "neo4j": Neo4jGraphDBConfig,
32
+ }
33
+
34
+ @field_validator("backend")
35
+ @classmethod
36
+ def validate_backend(cls, backend: str) -> str:
37
+ if backend not in cls.backend_to_class:
38
+ raise ValueError(f"Unsupported graph db backend: {backend}")
39
+ return backend
40
+
41
+ @model_validator(mode="after")
42
+ def instantiate_config(self):
43
+ config_class = self.backend_to_class[self.backend]
44
+ self.config = config_class(**self.config)
45
+ return self
@@ -0,0 +1,81 @@
1
+ """Configuration classes for internet retrievers."""
2
+
3
+ from typing import Any, ClassVar
4
+
5
+ from pydantic import Field, field_validator, model_validator
6
+
7
+ from memos.configs.base import BaseConfig
8
+ from memos.exceptions import ConfigurationError
9
+
10
+
11
+ class BaseInternetRetrieverConfig(BaseConfig):
12
+ """Base configuration class for internet retrievers."""
13
+
14
+ api_key: str = Field(..., description="API key for the search service")
15
+ search_engine_id: str | None = Field(
16
+ None, description="Search engine ID (required for Google Custom Search)"
17
+ )
18
+
19
+
20
+ class GoogleCustomSearchConfig(BaseInternetRetrieverConfig):
21
+ """Configuration class for Google Custom Search API."""
22
+
23
+ search_engine_id: str = Field(..., description="Google Custom Search Engine ID (cx parameter)")
24
+ max_results: int = Field(default=20, description="Maximum number of results to retrieve")
25
+ num_per_request: int = Field(
26
+ default=10, description="Number of results per API request (max 10 for Google)"
27
+ )
28
+
29
+
30
+ class BingSearchConfig(BaseInternetRetrieverConfig):
31
+ """Configuration class for Bing Search API."""
32
+
33
+ endpoint: str = Field(
34
+ default="https://api.bing.microsoft.com/v7.0/search", description="Bing Search API endpoint"
35
+ )
36
+ max_results: int = Field(default=20, description="Maximum number of results to retrieve")
37
+ num_per_request: int = Field(default=10, description="Number of results per API request")
38
+
39
+
40
+ class XinyuSearchConfig(BaseInternetRetrieverConfig):
41
+ """Configuration class for Xinyu Search API."""
42
+
43
+ search_engine_id: str | None = Field(
44
+ None, description="Not used for Xinyu Search (kept for compatibility)"
45
+ )
46
+ max_results: int = Field(default=20, description="Maximum number of results to retrieve")
47
+ num_per_request: int = Field(
48
+ default=10, description="Number of results per API request (not used for Xinyu)"
49
+ )
50
+
51
+
52
+ class InternetRetrieverConfigFactory(BaseConfig):
53
+ """Factory class for creating internet retriever configurations."""
54
+
55
+ backend: str | None = Field(
56
+ None, description="Backend for internet retriever (google, bing, etc.)"
57
+ )
58
+ config: dict[str, Any] | None = Field(
59
+ None, description="Configuration for the internet retriever backend"
60
+ )
61
+
62
+ backend_to_class: ClassVar[dict[str, Any]] = {
63
+ "google": GoogleCustomSearchConfig,
64
+ "bing": BingSearchConfig,
65
+ "xinyu": XinyuSearchConfig,
66
+ }
67
+
68
+ @field_validator("backend")
69
+ @classmethod
70
+ def validate_backend(cls, backend: str | None) -> str | None:
71
+ """Validate the backend field."""
72
+ if backend is not None and backend not in cls.backend_to_class:
73
+ raise ConfigurationError(f"Invalid internet retriever backend: {backend}")
74
+ return backend
75
+
76
+ @model_validator(mode="after")
77
+ def create_config(self) -> "InternetRetrieverConfigFactory":
78
+ if self.backend is not None:
79
+ config_class = self.backend_to_class[self.backend]
80
+ self.config = config_class(**self.config)
81
+ return self
memos/configs/llm.py ADDED
@@ -0,0 +1,71 @@
1
+ from typing import Any, ClassVar
2
+
3
+ from pydantic import Field, field_validator, model_validator
4
+
5
+ from memos.configs.base import BaseConfig
6
+
7
+
8
+ class BaseLLMConfig(BaseConfig):
9
+ """Base configuration class for LLMs."""
10
+
11
+ model_name_or_path: str = Field(..., description="Model name or path")
12
+ temperature: float = Field(default=0.8, description="Temperature for sampling")
13
+ max_tokens: int = Field(default=1024, description="Maximum number of tokens to generate")
14
+ top_p: float = Field(default=0.9, description="Top-p sampling parameter")
15
+ top_k: int = Field(default=50, description="Top-k sampling parameter")
16
+ remove_think_prefix: bool = Field(
17
+ default=False,
18
+ description="Remove content within think tags from the generated text",
19
+ )
20
+
21
+
22
+ class OpenAILLMConfig(BaseLLMConfig):
23
+ api_key: str = Field(..., description="API key for OpenAI")
24
+ api_base: str = Field(
25
+ default="https://api.openai.com/v1", description="Base URL for OpenAI API"
26
+ )
27
+
28
+
29
+ class OllamaLLMConfig(BaseLLMConfig):
30
+ api_base: str = Field(
31
+ default="http://localhost:11434",
32
+ description="Base URL for Ollama API",
33
+ )
34
+
35
+
36
+ class HFLLMConfig(BaseLLMConfig):
37
+ do_sample: bool = Field(
38
+ default=False,
39
+ description="Whether to use sampling (if False, always greedy/argmax decoding)",
40
+ )
41
+ add_generation_prompt: bool = Field(
42
+ default=True,
43
+ description="Apply generation template for the conversation",
44
+ )
45
+
46
+
47
+ class LLMConfigFactory(BaseConfig):
48
+ """Factory class for creating LLM configurations."""
49
+
50
+ backend: str = Field(..., description="Backend for LLM")
51
+ config: dict[str, Any] = Field(..., description="Configuration for the LLM backend")
52
+
53
+ backend_to_class: ClassVar[dict[str, Any]] = {
54
+ "openai": OpenAILLMConfig,
55
+ "ollama": OllamaLLMConfig,
56
+ "huggingface": HFLLMConfig,
57
+ }
58
+
59
+ @field_validator("backend")
60
+ @classmethod
61
+ def validate_backend(cls, backend: str) -> str:
62
+ """Validate the backend field."""
63
+ if backend not in cls.backend_to_class:
64
+ raise ValueError(f"Invalid backend: {backend}")
65
+ return backend
66
+
67
+ @model_validator(mode="after")
68
+ def create_config(self) -> "LLMConfigFactory":
69
+ config_class = self.backend_to_class[self.backend]
70
+ self.config = config_class(**self.config)
71
+ return self
@@ -0,0 +1,81 @@
1
+ import uuid
2
+
3
+ from datetime import datetime
4
+ from typing import Any, ClassVar
5
+
6
+ from pydantic import Field, field_validator, model_validator
7
+
8
+ from memos.configs.base import BaseConfig
9
+ from memos.configs.llm import LLMConfigFactory
10
+
11
+
12
+ class BaseMemChatConfig(BaseConfig):
13
+ """Base configuration class for MemChat."""
14
+
15
+ user_id: str = Field(..., description="User ID for the MemChat")
16
+ session_id: str = Field(
17
+ default_factory=lambda: str(uuid.uuid4()), description="Session ID for the MemChat"
18
+ )
19
+ created_at: datetime = Field(
20
+ default_factory=datetime.now,
21
+ description="Creation timestamp for the MemChat",
22
+ )
23
+ config_filename: str = Field(
24
+ default="config.json",
25
+ description="Filename for storing the MemChat configuration",
26
+ )
27
+
28
+
29
+ class SimpleMemChatConfig(BaseMemChatConfig):
30
+ """Simple MemChat configuration class."""
31
+
32
+ chat_llm: LLMConfigFactory = Field(
33
+ ...,
34
+ default_factory=LLMConfigFactory,
35
+ description="LLM configuration for the MemChat",
36
+ )
37
+ max_turns_window: int = Field(
38
+ default=15,
39
+ description="Maximum number of turns to keep in the conversation history",
40
+ )
41
+ top_k: int = Field(
42
+ default=5,
43
+ description="Maximum number of memories to retrieve for each query",
44
+ )
45
+ enable_textual_memory: bool = Field(
46
+ default=False,
47
+ description="Enable textual memory for the MemChat",
48
+ )
49
+ enable_activation_memory: bool = Field(
50
+ default=False,
51
+ description="Enable activation memory for the MemChat",
52
+ )
53
+ enable_parametric_memory: bool = Field(
54
+ default=False,
55
+ description="Enable parametric memory for the MemChat",
56
+ )
57
+
58
+
59
+ class MemChatConfigFactory(BaseConfig):
60
+ """Factory class for creating MemChat configurations."""
61
+
62
+ backend: str = Field(..., description="Backend for MemChat")
63
+ config: dict[str, Any] = Field(..., description="Configuration for the MemChat backend")
64
+
65
+ backend_to_class: ClassVar[dict[str, Any]] = {
66
+ "simple": SimpleMemChatConfig,
67
+ }
68
+
69
+ @field_validator("backend")
70
+ @classmethod
71
+ def validate_backend(cls, backend: str) -> str:
72
+ """Validate the backend field."""
73
+ if backend not in cls.backend_to_class:
74
+ raise ValueError(f"Invalid backend: {backend}")
75
+ return backend
76
+
77
+ @model_validator(mode="after")
78
+ def create_config(self) -> "MemChatConfigFactory":
79
+ config_class = self.backend_to_class[self.backend]
80
+ self.config = config_class(**self.config)
81
+ return self
@@ -0,0 +1,89 @@
1
+ import uuid
2
+
3
+ from pydantic import Field, field_validator
4
+
5
+ from memos.configs.base import BaseConfig
6
+ from memos.configs.memory import (
7
+ MemoryConfigFactory,
8
+ )
9
+ from memos.exceptions import ConfigurationError
10
+ from memos.log import get_logger
11
+
12
+
13
+ logger = get_logger(__name__)
14
+
15
+
16
+ class BaseMemCubeConfig(BaseConfig):
17
+ """Base configuration class for MemCube."""
18
+
19
+ model_schema: str = Field(
20
+ "NOT_SET",
21
+ description="Schema for configuration. This value will be automatically set.",
22
+ exclude=False,
23
+ )
24
+
25
+ config_filename: str = Field(
26
+ "config.json",
27
+ description="Filename for storing MemCube configuration",
28
+ )
29
+
30
+
31
+ class GeneralMemCubeConfig(BaseMemCubeConfig):
32
+ """General MemCube memory configuration class."""
33
+
34
+ user_id: str = Field(
35
+ "default_user",
36
+ description="User ID for the MemCube. This is used to distinguish between different users' memories.",
37
+ )
38
+ cube_id: str = Field(
39
+ str(uuid.uuid4()),
40
+ description="Cube ID for the MemCube. This is used to distinguish between different MemCubes.",
41
+ )
42
+ text_mem: MemoryConfigFactory = Field(
43
+ ...,
44
+ default_factory=MemoryConfigFactory,
45
+ description="Configuration for the textual memory",
46
+ )
47
+ act_mem: MemoryConfigFactory = Field(
48
+ ...,
49
+ default_factory=MemoryConfigFactory,
50
+ description="Configuration for the activation memory",
51
+ )
52
+ para_mem: MemoryConfigFactory = Field(
53
+ ...,
54
+ default_factory=MemoryConfigFactory,
55
+ description="Configuration for the parametric memory",
56
+ )
57
+
58
+ @field_validator("text_mem")
59
+ @classmethod
60
+ def validate_text_mem(cls, text_mem: MemoryConfigFactory) -> MemoryConfigFactory:
61
+ """Validate the text_mem field."""
62
+ allowed_backends = ["naive_text", "general_text", "tree_text", "uninitialized"]
63
+ if text_mem.backend not in allowed_backends:
64
+ raise ConfigurationError(
65
+ f"GeneralMemCubeConfig requires text_mem backend to be one of {allowed_backends}, got '{text_mem.backend}'"
66
+ )
67
+ return text_mem
68
+
69
+ @field_validator("act_mem")
70
+ @classmethod
71
+ def validate_act_mem(cls, act_mem: MemoryConfigFactory) -> MemoryConfigFactory:
72
+ """Validate the act_mem field."""
73
+ allowed_backends = ["kv_cache", "uninitialized"]
74
+ if act_mem.backend not in allowed_backends:
75
+ raise ConfigurationError(
76
+ f"GeneralMemCubeConfig requires act_mem backend to be one of {allowed_backends}, got '{act_mem.backend}'"
77
+ )
78
+ return act_mem
79
+
80
+ @field_validator("para_mem")
81
+ @classmethod
82
+ def validate_para_mem(cls, para_mem: MemoryConfigFactory) -> MemoryConfigFactory:
83
+ """Validate the para_mem field."""
84
+ allowed_backends = ["lora", "uninitialized"]
85
+ if para_mem.backend not in allowed_backends:
86
+ raise ConfigurationError(
87
+ f"GeneralMemCubeConfig requires para_mem backend to be one of {allowed_backends}, got '{para_mem.backend}'"
88
+ )
89
+ return para_mem
@@ -0,0 +1,74 @@
1
+ import uuid
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import Field, model_validator
6
+
7
+ from memos.configs.base import BaseConfig
8
+ from memos.configs.llm import LLMConfigFactory
9
+ from memos.configs.mem_reader import MemReaderConfigFactory
10
+ from memos.configs.mem_scheduler import SchedulerConfigFactory
11
+
12
+
13
+ class MOSConfig(BaseConfig):
14
+ user_id: str = Field(
15
+ default="root",
16
+ description="User ID for the MOS. This is used to distinguish between different users' memories.",
17
+ )
18
+ session_id: str = Field(
19
+ default=str(uuid.uuid4()),
20
+ description="Session ID for the MOS. This is used to distinguish between different dialogue",
21
+ )
22
+ chat_model: LLMConfigFactory = Field(
23
+ ...,
24
+ default_factory=LLMConfigFactory,
25
+ description="LLM configuration for the chat model in the MOS",
26
+ )
27
+ mem_reader: MemReaderConfigFactory = Field(
28
+ ...,
29
+ default_factory=MemReaderConfigFactory,
30
+ description="MemReader configuration for the MOS",
31
+ )
32
+ mem_scheduler: SchedulerConfigFactory | None = Field(
33
+ default=None,
34
+ description="Memory scheduler configuration for managing memory operations",
35
+ )
36
+ max_turns_window: int = Field(
37
+ default=15,
38
+ description="Maximum number of turns to keep in the conversation history",
39
+ )
40
+ top_k: int = Field(
41
+ default=5,
42
+ description="Maximum number of memories to retrieve for each query",
43
+ )
44
+ enable_textual_memory: bool = Field(
45
+ default=True,
46
+ description="Enable textual memory for the MemChat",
47
+ )
48
+ enable_activation_memory: bool = Field(
49
+ default=False,
50
+ description="Enable activation memory for the MemChat",
51
+ )
52
+ enable_parametric_memory: bool = Field(
53
+ default=False,
54
+ description="Enable parametric memory for the MemChat",
55
+ )
56
+ enable_mem_scheduler: bool = Field(
57
+ default=False,
58
+ description="Enable memory scheduler for automated memory management",
59
+ )
60
+ PRO_MODE: bool = Field(
61
+ default=False,
62
+ description="Enable PRO mode for complex query decomposition",
63
+ )
64
+
65
+
66
+ class MemOSConfigFactory(BaseConfig):
67
+ """Factory class for creating Memos configurations."""
68
+
69
+ config: dict[str, Any] = Field(..., description="Configuration for the MemOS backend")
70
+
71
+ @model_validator(mode="after")
72
+ def create_config(self) -> "MemOSConfigFactory":
73
+ self.config = MOSConfig(**self.config)
74
+ return self
@@ -0,0 +1,53 @@
1
+ from datetime import datetime
2
+ from typing import Any, ClassVar
3
+
4
+ from pydantic import Field, field_validator, model_validator
5
+
6
+ from memos.configs.base import BaseConfig
7
+ from memos.configs.chunker import ChunkerConfigFactory
8
+ from memos.configs.embedder import EmbedderConfigFactory
9
+ from memos.configs.llm import LLMConfigFactory
10
+
11
+
12
+ class BaseMemReaderConfig(BaseConfig):
13
+ """Base configuration class for MemReader."""
14
+
15
+ created_at: datetime = Field(
16
+ default_factory=datetime.now, description="Creation timestamp for the MemReader"
17
+ )
18
+ llm: LLMConfigFactory = Field(..., description="LLM configuration for the MemReader")
19
+ embedder: EmbedderConfigFactory = Field(
20
+ ..., description="Embedder configuration for the MemReader"
21
+ )
22
+ chunker: ChunkerConfigFactory = Field(
23
+ ..., description="Chunker configuration for the MemReader"
24
+ )
25
+
26
+
27
+ class SimpleStructMemReaderConfig(BaseMemReaderConfig):
28
+ """SimpleStruct MemReader configuration class."""
29
+
30
+
31
+ class MemReaderConfigFactory(BaseConfig):
32
+ """Factory class for creating MemReader configurations."""
33
+
34
+ backend: str = Field(..., description="Backend for MemReader")
35
+ config: dict[str, Any] = Field(..., description="Configuration for the MemReader backend")
36
+
37
+ backend_to_class: ClassVar[dict[str, Any]] = {
38
+ "simple_struct": SimpleStructMemReaderConfig,
39
+ }
40
+
41
+ @field_validator("backend")
42
+ @classmethod
43
+ def validate_backend(cls, backend: str) -> str:
44
+ """Validate the backend field."""
45
+ if backend not in cls.backend_to_class:
46
+ raise ValueError(f"Invalid backend: {backend}")
47
+ return backend
48
+
49
+ @model_validator(mode="after")
50
+ def create_config(self) -> "MemReaderConfigFactory":
51
+ config_class = self.backend_to_class[self.backend]
52
+ self.config = config_class(**self.config)
53
+ return self
@@ -0,0 +1,78 @@
1
+ from typing import Any, ClassVar
2
+
3
+ from pydantic import ConfigDict, Field, field_validator, model_validator
4
+
5
+ from memos.configs.base import BaseConfig
6
+ from memos.mem_scheduler.modules.schemas import (
7
+ DEFAULT_ACT_MEM_DUMP_PATH,
8
+ DEFAULT_ACTIVATION_MEM_SIZE,
9
+ DEFAULT_CONSUME_INTERVAL_SECONDS,
10
+ DEFAULT_THREAD__POOL_MAX_WORKERS,
11
+ )
12
+
13
+
14
+ class BaseSchedulerConfig(BaseConfig):
15
+ """Base configuration class for mem_scheduler."""
16
+
17
+ top_k: int = Field(
18
+ default=10, description="Number of top candidates to consider in initial retrieval"
19
+ )
20
+ top_n: int = Field(default=5, description="Number of final results to return after processing")
21
+ enable_parallel_dispatch: bool = Field(
22
+ default=True, description="Whether to enable parallel message processing using thread pool"
23
+ )
24
+ thread_pool_max_workers: int = Field(
25
+ default=DEFAULT_THREAD__POOL_MAX_WORKERS,
26
+ gt=1,
27
+ lt=20,
28
+ description=f"Maximum worker threads in pool (default: {DEFAULT_THREAD__POOL_MAX_WORKERS})",
29
+ )
30
+ consume_interval_seconds: int = Field(
31
+ default=DEFAULT_CONSUME_INTERVAL_SECONDS,
32
+ gt=0,
33
+ le=60,
34
+ description=f"Interval for consuming messages from queue in seconds (default: {DEFAULT_CONSUME_INTERVAL_SECONDS})",
35
+ )
36
+
37
+
38
+ class GeneralSchedulerConfig(BaseSchedulerConfig):
39
+ act_mem_update_interval: int | None = Field(
40
+ default=300, description="Interval in seconds for updating activation memory"
41
+ )
42
+ context_window_size: int | None = Field(
43
+ default=5, description="Size of the context window for conversation history"
44
+ )
45
+ activation_mem_size: int | None = Field(
46
+ default=DEFAULT_ACTIVATION_MEM_SIZE, # Assuming DEFAULT_ACTIVATION_MEM_SIZE is 1000
47
+ description="Maximum size of the activation memory",
48
+ )
49
+ act_mem_dump_path: str | None = Field(
50
+ default=DEFAULT_ACT_MEM_DUMP_PATH, # Replace with DEFAULT_ACT_MEM_DUMP_PATH
51
+ description="File path for dumping activation memory",
52
+ )
53
+
54
+
55
+ class SchedulerConfigFactory(BaseConfig):
56
+ """Factory class for creating scheduler configurations."""
57
+
58
+ backend: str = Field(..., description="Backend for scheduler")
59
+ config: dict[str, Any] = Field(..., description="Configuration for the scheduler backend")
60
+
61
+ model_config = ConfigDict(extra="forbid", strict=True)
62
+ backend_to_class: ClassVar[dict[str, Any]] = {
63
+ "general_scheduler": GeneralSchedulerConfig,
64
+ }
65
+
66
+ @field_validator("backend")
67
+ @classmethod
68
+ def validate_backend(cls, backend: str) -> str:
69
+ """Validate the backend field."""
70
+ if backend not in cls.backend_to_class:
71
+ raise ValueError(f"Invalid backend: {backend}")
72
+ return backend
73
+
74
+ @model_validator(mode="after")
75
+ def create_config(self) -> "SchedulerConfigFactory":
76
+ config_class = self.backend_to_class[self.backend]
77
+ self.config = config_class(**self.config)
78
+ return self