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,232 @@
1
+ import os
2
+ import pickle
3
+
4
+ from datetime import datetime
5
+
6
+ import torch
7
+
8
+ from transformers import DynamicCache
9
+
10
+ from memos.configs.memory import KVCacheMemoryConfig
11
+ from memos.llms.factory import LLMFactory
12
+ from memos.memories.activation.base import BaseActMemory
13
+ from memos.memories.activation.item import KVCacheItem
14
+ from memos.memories.textual.item import TextualMemoryItem
15
+
16
+
17
+ class KVCacheMemory(BaseActMemory):
18
+ """
19
+ Key-Value Cache Memory for activation memories.
20
+ This memory type is designed to store and retrieve key-value caches.
21
+ """
22
+
23
+ def __init__(self, config: KVCacheMemoryConfig) -> None:
24
+ """Initialize the KV Cache Memory with a configuration."""
25
+ self.config = config
26
+ self.llm = LLMFactory.from_config(config.extractor_llm)
27
+ self.kv_cache_memories: dict[str, KVCacheItem] = {}
28
+
29
+ def extract(self, text: str) -> KVCacheItem:
30
+ """Extract memory based on the text.
31
+
32
+ Uses the LLM to build KV caches from the provided text.
33
+
34
+ Args:
35
+ text: Input text to extract memory from
36
+
37
+ Returns:
38
+ Extracted memory item
39
+ """
40
+ # Build KV cache from the text using the LLM
41
+ kv_cache = self.llm.build_kv_cache(text)
42
+
43
+ # Create a KVCacheItem with the extracted cache
44
+ cache_item = KVCacheItem(
45
+ memory=kv_cache,
46
+ metadata={"source_text": text, "extracted_at": datetime.now().isoformat()},
47
+ )
48
+
49
+ return cache_item
50
+
51
+ def add(self, memories: list[KVCacheItem]) -> None:
52
+ """Add memories to the KV cache memory.
53
+
54
+ Args:
55
+ memories: List of KVCacheItem to add
56
+ """
57
+ for memory in memories:
58
+ self.kv_cache_memories[memory.id] = memory
59
+
60
+ def get_cache(self, cache_ids: list[str]) -> DynamicCache | None:
61
+ """Merge multiple KV caches into a single cache.
62
+
63
+ Args:
64
+ cache_ids: List of cache IDs to merge
65
+
66
+ Returns:
67
+ Merged DynamicCache or None if no caches found
68
+ """
69
+ caches_to_merge = []
70
+ for cache_id in cache_ids:
71
+ cache_item = self.kv_cache_memories.get(cache_id)
72
+ if cache_item and cache_item.memory:
73
+ caches_to_merge.append(cache_item.memory)
74
+
75
+ if not caches_to_merge:
76
+ return None
77
+
78
+ return self._concat_caches(caches_to_merge)
79
+
80
+ def get(self, memory_id: str) -> KVCacheItem | None:
81
+ """Get a memory by its ID.
82
+
83
+ Args:
84
+ memory_id: ID of the memory to retrieve
85
+
86
+ Returns:
87
+ Memory dictionary or None if not found
88
+ """
89
+ return self.kv_cache_memories.get(memory_id)
90
+
91
+ def get_by_ids(self, memory_ids: list[str]) -> list[KVCacheItem | None]:
92
+ """Get memories by their IDs.
93
+
94
+ Args:
95
+ memory_ids: List of memory IDs to retrieve
96
+
97
+ Returns:
98
+ List of memory dictionaries or None for missing ones
99
+ """
100
+ results = []
101
+ for memory_id in memory_ids:
102
+ memory = self.get(memory_id)
103
+ results.append(memory)
104
+ return results
105
+
106
+ def get_all(self) -> list[KVCacheItem]:
107
+ """Get all memories.
108
+
109
+ Returns:
110
+ List of all KVCacheItems in the memory
111
+ """
112
+ return list(self.kv_cache_memories.values())
113
+
114
+ def delete(self, memory_ids: list[str]) -> None:
115
+ """Delete memories by their IDs.
116
+
117
+ Args:
118
+ memory_ids: List of memory IDs to delete
119
+ """
120
+ for memory_id in memory_ids:
121
+ self.kv_cache_memories.pop(memory_id, None)
122
+
123
+ def delete_all(self) -> None:
124
+ """Delete all memories."""
125
+ self.kv_cache_memories.clear()
126
+
127
+ def from_textual_memory(self, mem: TextualMemoryItem) -> KVCacheItem:
128
+ """
129
+ Convert a TextualMemoryItem to a KVCacheItem.
130
+ This method extracts the key-value cache from the textual memory.
131
+ """
132
+ # Build KV cache from the textual memory content
133
+ kv_cache = self.llm.build_kv_cache(mem.memory)
134
+ return KVCacheItem(memory=kv_cache, metadata=mem.metadata.model_dump())
135
+
136
+ def load(self, dir: str) -> None:
137
+ """Load memories from os.path.join(dir, self.config.memory_filename)
138
+
139
+ Args:
140
+ dir (str): The directory containing the memory files.
141
+ """
142
+ file_path = os.path.join(dir, self.config.memory_filename)
143
+
144
+ if not os.path.exists(file_path):
145
+ # If file doesn't exist, start with empty memories
146
+ return
147
+
148
+ try:
149
+ # Allow loading DynamicCache and KVCacheItem types
150
+ torch.serialization.add_safe_globals([DynamicCache, KVCacheItem])
151
+
152
+ with open(file_path, "rb") as f:
153
+ data = pickle.load(f)
154
+
155
+ if isinstance(data, dict):
156
+ # Load memories, handle both old and new formats
157
+ if "kv_cache_memories" in data:
158
+ memories = data["kv_cache_memories"]
159
+ if isinstance(memories, list):
160
+ # Convert list to dict format
161
+ self.kv_cache_memories = {item.id: item for item in memories}
162
+ else:
163
+ self.kv_cache_memories = memories
164
+ else:
165
+ # Reset to empty if no memories in data
166
+ self.kv_cache_memories = {}
167
+ elif isinstance(data, list):
168
+ # Backward compatibility: convert list to dict
169
+ self.kv_cache_memories = {item.id: item for item in data}
170
+ else:
171
+ # Reset to empty if data format is unexpected
172
+ self.kv_cache_memories = {}
173
+
174
+ except (EOFError, pickle.UnpicklingError, Exception):
175
+ # If loading fails, start with empty memories
176
+ self.kv_cache_memories = {}
177
+
178
+ def dump(self, dir: str) -> None:
179
+ """Dump memories to os.path.join(dir, self.config.memory_filename)
180
+
181
+ Args:
182
+ dir (str): The directory where the memory files will be saved.
183
+ """
184
+ file_path = os.path.join(dir, self.config.memory_filename)
185
+
186
+ # Create directory if it doesn't exist
187
+ os.makedirs(dir, exist_ok=True)
188
+
189
+ # Prepare data to save (only memories)
190
+ data = {"kv_cache_memories": self.kv_cache_memories}
191
+
192
+ with open(file_path, "wb") as f:
193
+ pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL)
194
+
195
+ def _concat_caches(self, caches: list[DynamicCache]) -> DynamicCache:
196
+ """
197
+ Faster concat merge: for each layer, gather all caches' tensors
198
+ and do a single torch.cat per layer.
199
+ """
200
+ assert caches, "Need at least one cache"
201
+ if len(caches) == 1:
202
+ return caches[0]
203
+
204
+ merged = DynamicCache()
205
+ num_layers = len(caches[0].key_cache)
206
+
207
+ for layer in range(num_layers):
208
+ # gather all K and V for this layer
209
+ keys = [c.key_cache[layer] for c in caches]
210
+ vals = [c.value_cache[layer] for c in caches]
211
+ # single concat per layer
212
+ merged.key_cache.append(torch.cat(keys, dim=-2))
213
+ merged.value_cache.append(torch.cat(vals, dim=-2))
214
+
215
+ return merged
216
+
217
+
218
+ def move_dynamic_cache_htod(dynamic_cache: DynamicCache, device: torch.device) -> DynamicCache:
219
+ """
220
+ In SimpleMemChat.run(), if self.config.enable_activation_memory is enabled,
221
+ we load serialized kv cache from a [class KVCacheMemory] object, which has a kv_cache_memories on CPU.
222
+ So before inferring with DynamicCache, we should move it to GPU in-place first.
223
+ """
224
+ # Currently, we put this function outside [class KVCacheMemory]
225
+ for i in range(len(dynamic_cache.key_cache)):
226
+ if dynamic_cache.key_cache[i] is not None:
227
+ dynamic_cache.key_cache[i] = dynamic_cache.key_cache[i].to(device, non_blocking=True)
228
+ if dynamic_cache.value_cache[i] is not None:
229
+ dynamic_cache.value_cache[i] = dynamic_cache.value_cache[i].to(
230
+ device, non_blocking=True
231
+ )
232
+ return dynamic_cache
memos/memories/base.py ADDED
@@ -0,0 +1,19 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+
4
+ class BaseMemory(ABC):
5
+ """Base class for all memory implementations."""
6
+
7
+ @abstractmethod
8
+ def load(self, dir: str) -> None:
9
+ """Load memories from os.path.join(dir, self.config.memory_filename)
10
+ Args:
11
+ dir (str): The directory containing the memory files.
12
+ """
13
+
14
+ @abstractmethod
15
+ def dump(self, dir: str) -> None:
16
+ """Dump memories to os.path.join(dir, self.config.memory_filename)
17
+ Args:
18
+ dir (str): The directory where the memory files will be saved.
19
+ """
@@ -0,0 +1,34 @@
1
+ from typing import Any, ClassVar
2
+
3
+ from memos.configs.memory import MemoryConfigFactory
4
+ from memos.memories.activation.base import BaseActMemory
5
+ from memos.memories.activation.kv import KVCacheMemory
6
+ from memos.memories.base import BaseMemory
7
+ from memos.memories.parametric.base import BaseParaMemory
8
+ from memos.memories.parametric.lora import LoRAMemory
9
+ from memos.memories.textual.base import BaseTextMemory
10
+ from memos.memories.textual.general import GeneralTextMemory
11
+ from memos.memories.textual.naive import NaiveTextMemory
12
+ from memos.memories.textual.tree import TreeTextMemory
13
+
14
+
15
+ class MemoryFactory(BaseMemory):
16
+ """Factory class for creating memory instances."""
17
+
18
+ backend_to_class: ClassVar[dict[str, Any]] = {
19
+ "naive_text": NaiveTextMemory,
20
+ "general_text": GeneralTextMemory,
21
+ "tree_text": TreeTextMemory,
22
+ "kv_cache": KVCacheMemory,
23
+ "lora": LoRAMemory,
24
+ }
25
+
26
+ @classmethod
27
+ def from_config(
28
+ cls, config_factory: MemoryConfigFactory
29
+ ) -> BaseTextMemory | BaseActMemory | BaseParaMemory:
30
+ backend = config_factory.backend
31
+ if backend not in cls.backend_to_class:
32
+ raise ValueError(f"Invalid backend: {backend}")
33
+ memory_class = cls.backend_to_class[backend]
34
+ return memory_class(config_factory.config)
File without changes
@@ -0,0 +1,19 @@
1
+ ################################################################
2
+ # TODO:
3
+ # This file currently serves as a placeholder.
4
+ # The actual implementation will be added here in the future.
5
+ # Please do not use this as a functional module yet.
6
+ ################################################################
7
+
8
+ from abc import abstractmethod
9
+
10
+ from memos.configs.memory import BaseParaMemoryConfig
11
+ from memos.memories.base import BaseMemory
12
+
13
+
14
+ class BaseParaMemory(BaseMemory):
15
+ """Base class for all parametric memory implementations."""
16
+
17
+ @abstractmethod
18
+ def __init__(self, config: BaseParaMemoryConfig):
19
+ """Initialize memory with the given configuration."""
@@ -0,0 +1,11 @@
1
+ import uuid
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+
8
+ class ParametricMemoryItem(BaseModel):
9
+ id: str = Field(default_factory=lambda: str(uuid.uuid4()))
10
+ memory: Any
11
+ metadata: dict = {}
@@ -0,0 +1,41 @@
1
+ ################################################################
2
+ # TODO:
3
+ # This file currently serves as a placeholder.
4
+ # The actual implementation will be added here in the future.
5
+ # Please do not use this as a functional module yet.
6
+ ################################################################
7
+
8
+ import os
9
+
10
+ from memos.configs.memory import LoRAMemoryConfig
11
+ from memos.memories.parametric.base import BaseParaMemory
12
+
13
+
14
+ class LoRAMemory(BaseParaMemory):
15
+ """
16
+ LoRA Memory for parametric memories.
17
+ This memory type is designed to store and retrieve low-rank adaptation (LoRA) parameters.
18
+ """
19
+
20
+ def __init__(self, config: LoRAMemoryConfig) -> None:
21
+ """Initialize the LoRA Memory with a configuration."""
22
+ self.config = config
23
+
24
+ def load(self, dir: str) -> None:
25
+ """Load memories from os.path.join(dir, self.config.memory_filename)
26
+
27
+ Args:
28
+ dir (str): The directory containing the memory files.
29
+ """
30
+
31
+ def dump(self, dir: str) -> None:
32
+ """Dump memories to os.path.join(dir, self.config.memory_filename)
33
+
34
+ Args:
35
+ dir (str): The directory where the memory files will be saved.
36
+ """
37
+ path = os.path.join(dir, self.config.memory_filename)
38
+ if not os.path.exists(dir):
39
+ os.makedirs(dir, exist_ok=True)
40
+ with open(path, "wb") as f:
41
+ f.write(b"Placeholder")
File without changes
@@ -0,0 +1,89 @@
1
+ from abc import abstractmethod
2
+ from typing import Any
3
+
4
+ from memos.configs.memory import BaseTextMemoryConfig
5
+ from memos.memories.base import BaseMemory
6
+ from memos.memories.textual.item import TextualMemoryItem
7
+ from memos.types import MessageList
8
+
9
+
10
+ class BaseTextMemory(BaseMemory):
11
+ """Base class for all textual memory implementations."""
12
+
13
+ @abstractmethod
14
+ def __init__(self, config: BaseTextMemoryConfig):
15
+ """Initialize memory with the given configuration."""
16
+
17
+ @abstractmethod
18
+ def extract(self, messages: MessageList) -> list[TextualMemoryItem]:
19
+ """Extract memories based on the messages.
20
+ Args:
21
+ messages (MessageList): The messages to extract memories from.
22
+ Returns:
23
+ list[TextualMemoryItem]: List of extracted memory items.
24
+ """
25
+
26
+ @abstractmethod
27
+ def add(self, memories: list[TextualMemoryItem | dict[str, Any]]) -> None:
28
+ """Add memories.
29
+
30
+ Args:
31
+ memories: List of TextualMemoryItem objects or dictionaries to add.
32
+ """
33
+
34
+ @abstractmethod
35
+ def update(self, memory_id: str, new_memory: TextualMemoryItem | dict[str, Any]) -> None:
36
+ """Update a memory by memory_id."""
37
+
38
+ @abstractmethod
39
+ def search(self, query: str, top_k: int, info=None) -> list[TextualMemoryItem]:
40
+ """Search for memories based on a query.
41
+ Args:
42
+ query (str): The query to search for.
43
+ top_k (int): The number of top results to return.
44
+ info (dict): Leave a record of memory consumption.
45
+ Returns:
46
+ list[TextualMemoryItem]: List of matching memories.
47
+ """
48
+
49
+ @abstractmethod
50
+ def get(self, memory_id: str) -> TextualMemoryItem:
51
+ """Get a memory by its ID.
52
+ Args:
53
+ memory_id (str): The ID of the memory to retrieve.
54
+ Returns:
55
+ TextualMemoryItem: The memory with the given ID.
56
+ """
57
+
58
+ @abstractmethod
59
+ def get_by_ids(self, memory_ids: list[str]) -> list[TextualMemoryItem]:
60
+ """Get memories by their IDs.
61
+ Args:
62
+ memory_ids (list[str]): List of memory IDs to retrieve.
63
+ Returns:
64
+ list[TextualMemoryItem]: List of memories with the specified IDs.
65
+ """
66
+
67
+ @abstractmethod
68
+ def get_all(self) -> list[TextualMemoryItem]:
69
+ """Get all memories.
70
+ Returns:
71
+ list[TextualMemoryItem]: List of all memories.
72
+ """
73
+
74
+ @abstractmethod
75
+ def delete(self, memory_ids: list[str]) -> None:
76
+ """Delete memories.
77
+ Args:
78
+ memory_ids (list[str]): List of memory IDs to delete.
79
+ """
80
+
81
+ @abstractmethod
82
+ def delete_all(self) -> None:
83
+ """Delete all memories."""
84
+
85
+ @abstractmethod
86
+ def drop(
87
+ self,
88
+ ) -> None:
89
+ """Drop all databases."""