MemoryOS 0.2.1__py3-none-any.whl → 0.2.2__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.
- {memoryos-0.2.1.dist-info → memoryos-0.2.2.dist-info}/METADATA +2 -1
- {memoryos-0.2.1.dist-info → memoryos-0.2.2.dist-info}/RECORD +72 -55
- memos/__init__.py +1 -1
- memos/api/config.py +156 -65
- memos/api/context/context.py +147 -0
- memos/api/context/dependencies.py +90 -0
- memos/api/product_models.py +5 -1
- memos/api/routers/product_router.py +54 -26
- memos/configs/graph_db.py +49 -1
- memos/configs/internet_retriever.py +6 -0
- memos/configs/mem_os.py +5 -0
- memos/configs/mem_reader.py +9 -0
- memos/configs/mem_scheduler.py +18 -4
- memos/configs/mem_user.py +58 -0
- memos/graph_dbs/base.py +9 -1
- memos/graph_dbs/factory.py +2 -0
- memos/graph_dbs/nebular.py +1364 -0
- memos/graph_dbs/neo4j.py +4 -4
- memos/log.py +1 -1
- memos/mem_cube/utils.py +13 -6
- memos/mem_os/core.py +140 -30
- memos/mem_os/main.py +1 -1
- memos/mem_os/product.py +266 -152
- memos/mem_os/utils/format_utils.py +314 -67
- memos/mem_reader/simple_struct.py +13 -5
- memos/mem_scheduler/base_scheduler.py +220 -250
- memos/mem_scheduler/general_scheduler.py +193 -73
- memos/mem_scheduler/modules/base.py +5 -5
- memos/mem_scheduler/modules/dispatcher.py +6 -9
- memos/mem_scheduler/modules/misc.py +81 -16
- memos/mem_scheduler/modules/monitor.py +52 -41
- memos/mem_scheduler/modules/rabbitmq_service.py +9 -7
- memos/mem_scheduler/modules/retriever.py +108 -191
- memos/mem_scheduler/modules/scheduler_logger.py +255 -0
- memos/mem_scheduler/mos_for_test_scheduler.py +16 -19
- memos/mem_scheduler/schemas/__init__.py +0 -0
- memos/mem_scheduler/schemas/general_schemas.py +43 -0
- memos/mem_scheduler/schemas/message_schemas.py +148 -0
- memos/mem_scheduler/schemas/monitor_schemas.py +329 -0
- memos/mem_scheduler/utils/__init__.py +0 -0
- memos/mem_scheduler/utils/filter_utils.py +176 -0
- memos/mem_scheduler/utils/misc_utils.py +61 -0
- memos/mem_user/factory.py +94 -0
- memos/mem_user/mysql_persistent_user_manager.py +271 -0
- memos/mem_user/mysql_user_manager.py +500 -0
- memos/mem_user/persistent_factory.py +96 -0
- memos/mem_user/user_manager.py +4 -4
- memos/memories/activation/item.py +4 -0
- memos/memories/textual/base.py +1 -1
- memos/memories/textual/general.py +35 -91
- memos/memories/textual/item.py +5 -33
- memos/memories/textual/tree.py +13 -7
- memos/memories/textual/tree_text_memory/organize/conflict.py +4 -2
- memos/memories/textual/tree_text_memory/organize/relation_reason_detector.py +47 -43
- memos/memories/textual/tree_text_memory/organize/reorganizer.py +8 -5
- memos/memories/textual/tree_text_memory/retrieve/internet_retriever.py +6 -3
- memos/memories/textual/tree_text_memory/retrieve/internet_retriever_factory.py +2 -0
- memos/memories/textual/tree_text_memory/retrieve/retrieval_mid_structs.py +2 -0
- memos/memories/textual/tree_text_memory/retrieve/searcher.py +46 -23
- memos/memories/textual/tree_text_memory/retrieve/task_goal_parser.py +42 -15
- memos/memories/textual/tree_text_memory/retrieve/utils.py +11 -7
- memos/memories/textual/tree_text_memory/retrieve/xinyusearch.py +62 -58
- memos/memos_tools/dinding_report_bot.py +422 -0
- memos/memos_tools/notification_service.py +44 -0
- memos/memos_tools/notification_utils.py +96 -0
- memos/settings.py +3 -1
- memos/templates/mem_reader_prompts.py +2 -1
- memos/templates/mem_scheduler_prompts.py +41 -7
- memos/templates/mos_prompts.py +87 -0
- memos/mem_scheduler/modules/schemas.py +0 -328
- memos/mem_scheduler/utils.py +0 -75
- {memoryos-0.2.1.dist-info → memoryos-0.2.2.dist-info}/LICENSE +0 -0
- {memoryos-0.2.1.dist-info → memoryos-0.2.2.dist-info}/WHEEL +0 -0
- {memoryos-0.2.1.dist-info → memoryos-0.2.2.dist-info}/entry_points.txt +0 -0
memos/graph_dbs/neo4j.py
CHANGED
|
@@ -114,14 +114,14 @@ class Neo4jGraphDB(BaseGraphDB):
|
|
|
114
114
|
)
|
|
115
115
|
return result.single()["count"]
|
|
116
116
|
|
|
117
|
-
def
|
|
117
|
+
def node_not_exist(self, scope: str) -> int:
|
|
118
118
|
query = """
|
|
119
119
|
MATCH (n:Memory)
|
|
120
120
|
WHERE n.memory_type = $scope
|
|
121
121
|
"""
|
|
122
122
|
if not self.config.use_multi_db and self.config.user_name:
|
|
123
123
|
query += "\nAND n.user_name = $user_name"
|
|
124
|
-
query += "\nRETURN
|
|
124
|
+
query += "\nRETURN n LIMIT 1"
|
|
125
125
|
|
|
126
126
|
with self.driver.session(database=self.db_name) as session:
|
|
127
127
|
result = session.run(
|
|
@@ -131,7 +131,7 @@ class Neo4jGraphDB(BaseGraphDB):
|
|
|
131
131
|
"user_name": self.config.user_name if self.config.user_name else None,
|
|
132
132
|
},
|
|
133
133
|
)
|
|
134
|
-
return result.single()
|
|
134
|
+
return result.single() is None
|
|
135
135
|
|
|
136
136
|
def remove_oldest_memory(self, memory_type: str, keep_latest: int) -> None:
|
|
137
137
|
"""
|
|
@@ -920,7 +920,7 @@ class Neo4jGraphDB(BaseGraphDB):
|
|
|
920
920
|
Returns:
|
|
921
921
|
list[dict]: Full list of memory items under this scope.
|
|
922
922
|
"""
|
|
923
|
-
if scope not in {"WorkingMemory", "LongTermMemory", "UserMemory"}:
|
|
923
|
+
if scope not in {"WorkingMemory", "LongTermMemory", "UserMemory", "OuterMemory"}:
|
|
924
924
|
raise ValueError(f"Unsupported memory type scope: {scope}")
|
|
925
925
|
|
|
926
926
|
where_clause = "WHERE n.memory_type = $scope"
|
memos/log.py
CHANGED
memos/mem_cube/utils.py
CHANGED
|
@@ -71,10 +71,6 @@ def merge_config_with_default(
|
|
|
71
71
|
|
|
72
72
|
# Define graph_db fields to preserve (user-specific)
|
|
73
73
|
preserve_graph_fields = {
|
|
74
|
-
"uri",
|
|
75
|
-
"user",
|
|
76
|
-
"password",
|
|
77
|
-
"db_name",
|
|
78
74
|
"auto_create",
|
|
79
75
|
"user_name",
|
|
80
76
|
"use_multi_db",
|
|
@@ -96,9 +92,20 @@ def merge_config_with_default(
|
|
|
96
92
|
merged_graph_config["db_name"] = default_graph_config.get("db_name")
|
|
97
93
|
else:
|
|
98
94
|
logger.info("use_multi_db is already False, no need to change")
|
|
99
|
-
|
|
95
|
+
if "neo4j" not in default_text_config["graph_db"]["backend"]:
|
|
96
|
+
if "db_name" in merged_graph_config:
|
|
97
|
+
merged_graph_config.pop("db_name")
|
|
98
|
+
logger.info("neo4j is not supported, remove db_name")
|
|
99
|
+
else:
|
|
100
|
+
logger.info("db_name is not in merged_graph_config, no need to remove")
|
|
101
|
+
else:
|
|
102
|
+
if "space" in merged_graph_config:
|
|
103
|
+
merged_graph_config.pop("space")
|
|
104
|
+
logger.info("neo4j is not supported, remove db_name")
|
|
105
|
+
else:
|
|
106
|
+
logger.info("space is not in merged_graph_config, no need to remove")
|
|
100
107
|
preserved_graph_db = {
|
|
101
|
-
"backend":
|
|
108
|
+
"backend": default_text_config["graph_db"]["backend"],
|
|
102
109
|
"config": merged_graph_config,
|
|
103
110
|
}
|
|
104
111
|
|
memos/mem_os/core.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
|
-
import
|
|
3
|
+
import time
|
|
4
4
|
|
|
5
5
|
from datetime import datetime
|
|
6
6
|
from pathlib import Path
|
|
@@ -13,16 +13,18 @@ from memos.log import get_logger
|
|
|
13
13
|
from memos.mem_cube.general import GeneralMemCube
|
|
14
14
|
from memos.mem_reader.factory import MemReaderFactory
|
|
15
15
|
from memos.mem_scheduler.general_scheduler import GeneralScheduler
|
|
16
|
-
from memos.mem_scheduler.
|
|
16
|
+
from memos.mem_scheduler.scheduler_factory import SchedulerFactory
|
|
17
|
+
from memos.mem_scheduler.schemas.general_schemas import (
|
|
17
18
|
ADD_LABEL,
|
|
18
19
|
ANSWER_LABEL,
|
|
19
|
-
|
|
20
|
+
QUERY_LABEL,
|
|
20
21
|
)
|
|
21
|
-
from memos.mem_scheduler.
|
|
22
|
+
from memos.mem_scheduler.schemas.message_schemas import ScheduleMessageItem
|
|
22
23
|
from memos.mem_user.user_manager import UserManager, UserRole
|
|
23
24
|
from memos.memories.activation.item import ActivationMemoryItem
|
|
24
25
|
from memos.memories.parametric.item import ParametricMemoryItem
|
|
25
26
|
from memos.memories.textual.item import TextualMemoryItem, TextualMemoryMetadata
|
|
27
|
+
from memos.templates.mos_prompts import QUERY_REWRITING_PROMPT
|
|
26
28
|
from memos.types import ChatHistory, MessageList, MOSSearchResult
|
|
27
29
|
|
|
28
30
|
|
|
@@ -58,10 +60,15 @@ class MOSCore:
|
|
|
58
60
|
f"User '{self.user_id}' does not exist or is inactive. Please create user first."
|
|
59
61
|
)
|
|
60
62
|
|
|
61
|
-
#
|
|
63
|
+
# Initialize mem_scheduler
|
|
62
64
|
self._mem_scheduler_lock = Lock()
|
|
63
65
|
self.enable_mem_scheduler = self.config.get("enable_mem_scheduler", False)
|
|
64
|
-
self.
|
|
66
|
+
if self.enable_mem_scheduler:
|
|
67
|
+
self._mem_scheduler = self._initialize_mem_scheduler()
|
|
68
|
+
self._mem_scheduler.mem_cubes = self.mem_cubes
|
|
69
|
+
else:
|
|
70
|
+
self._mem_scheduler: GeneralScheduler = None
|
|
71
|
+
|
|
65
72
|
logger.info(f"MOS initialized for user: {self.user_id}")
|
|
66
73
|
|
|
67
74
|
@property
|
|
@@ -93,14 +100,16 @@ class MOSCore:
|
|
|
93
100
|
else:
|
|
94
101
|
logger.debug("Memory scheduler cleared")
|
|
95
102
|
|
|
96
|
-
def _initialize_mem_scheduler(self):
|
|
103
|
+
def _initialize_mem_scheduler(self) -> GeneralScheduler:
|
|
97
104
|
"""Initialize the memory scheduler on first access."""
|
|
98
105
|
if not self.config.enable_mem_scheduler:
|
|
99
106
|
logger.debug("Memory scheduler is disabled in config")
|
|
100
107
|
self._mem_scheduler = None
|
|
108
|
+
return self._mem_scheduler
|
|
101
109
|
elif not hasattr(self.config, "mem_scheduler"):
|
|
102
110
|
logger.error("Config of Memory scheduler is not available")
|
|
103
111
|
self._mem_scheduler = None
|
|
112
|
+
return self._mem_scheduler
|
|
104
113
|
else:
|
|
105
114
|
logger.info("Initializing memory scheduler...")
|
|
106
115
|
scheduler_config = self.config.mem_scheduler
|
|
@@ -111,13 +120,16 @@ class MOSCore:
|
|
|
111
120
|
f"Memory reader of type {type(self.mem_reader).__name__} "
|
|
112
121
|
"missing required 'llm' attribute"
|
|
113
122
|
)
|
|
114
|
-
self._mem_scheduler.initialize_modules(
|
|
123
|
+
self._mem_scheduler.initialize_modules(
|
|
124
|
+
chat_llm=self.chat_llm, process_llm=self.chat_llm
|
|
125
|
+
)
|
|
115
126
|
else:
|
|
116
127
|
# Configure scheduler modules
|
|
117
128
|
self._mem_scheduler.initialize_modules(
|
|
118
129
|
chat_llm=self.chat_llm, process_llm=self.mem_reader.llm
|
|
119
130
|
)
|
|
120
131
|
self._mem_scheduler.start()
|
|
132
|
+
return self._mem_scheduler
|
|
121
133
|
|
|
122
134
|
def mem_scheduler_on(self) -> bool:
|
|
123
135
|
if not self.config.enable_mem_scheduler or self._mem_scheduler is None:
|
|
@@ -157,6 +169,14 @@ class MOSCore:
|
|
|
157
169
|
if mem_cube.text_mem and mem_cube.text_mem.is_reorganize:
|
|
158
170
|
logger.info(f"close reorganizer for {mem_cube.text_mem.config.cube_id}")
|
|
159
171
|
mem_cube.text_mem.memory_manager.close()
|
|
172
|
+
mem_cube.text_mem.memory_manager.wait_reorganizer()
|
|
173
|
+
|
|
174
|
+
def mem_reorganizer_wait(self) -> bool:
|
|
175
|
+
for mem_cube in self.mem_cubes.values():
|
|
176
|
+
logger.info(f"try to close reorganizer for {mem_cube.text_mem.config.cube_id}")
|
|
177
|
+
if mem_cube.text_mem and mem_cube.text_mem.is_reorganize:
|
|
178
|
+
logger.info(f"close reorganizer for {mem_cube.text_mem.config.cube_id}")
|
|
179
|
+
mem_cube.text_mem.memory_manager.wait_reorganizer()
|
|
160
180
|
|
|
161
181
|
def _register_chat_history(self, user_id: str | None = None) -> None:
|
|
162
182
|
"""Initialize chat history with user ID."""
|
|
@@ -257,13 +277,21 @@ class MOSCore:
|
|
|
257
277
|
user_id=target_user_id,
|
|
258
278
|
mem_cube_id=mem_cube_id,
|
|
259
279
|
mem_cube=mem_cube,
|
|
260
|
-
label=
|
|
280
|
+
label=QUERY_LABEL,
|
|
261
281
|
content=query,
|
|
262
282
|
timestamp=datetime.now(),
|
|
263
283
|
)
|
|
264
284
|
self.mem_scheduler.submit_messages(messages=[message_item])
|
|
265
285
|
|
|
266
|
-
memories = mem_cube.text_mem.search(
|
|
286
|
+
memories = mem_cube.text_mem.search(
|
|
287
|
+
query,
|
|
288
|
+
top_k=self.config.top_k,
|
|
289
|
+
info={
|
|
290
|
+
"user_id": target_user_id,
|
|
291
|
+
"session_id": self.session_id,
|
|
292
|
+
"chat_history": chat_history.chat_history,
|
|
293
|
+
},
|
|
294
|
+
)
|
|
267
295
|
memories_all.extend(memories)
|
|
268
296
|
logger.info(f"🧠 [Memory] Searched memories:\n{self._str_memories(memories_all)}\n")
|
|
269
297
|
system_prompt = self._build_system_prompt(memories_all, base_prompt=base_prompt)
|
|
@@ -511,6 +539,8 @@ class MOSCore:
|
|
|
511
539
|
user_id: str | None = None,
|
|
512
540
|
install_cube_ids: list[str] | None = None,
|
|
513
541
|
top_k: int | None = None,
|
|
542
|
+
mode: Literal["fast", "fine"] = "fast",
|
|
543
|
+
internet_search: bool = False,
|
|
514
544
|
) -> MOSSearchResult:
|
|
515
545
|
"""
|
|
516
546
|
Search for textual memories across all registered MemCubes.
|
|
@@ -534,6 +564,10 @@ class MOSCore:
|
|
|
534
564
|
logger.info(
|
|
535
565
|
f"User {target_user_id} has access to {len(user_cube_ids)} cubes: {user_cube_ids}"
|
|
536
566
|
)
|
|
567
|
+
if target_user_id not in self.chat_history_manager:
|
|
568
|
+
self._register_chat_history(target_user_id)
|
|
569
|
+
chat_history = self.chat_history_manager[target_user_id]
|
|
570
|
+
|
|
537
571
|
result: MOSSearchResult = {
|
|
538
572
|
"text_mem": [],
|
|
539
573
|
"act_mem": [],
|
|
@@ -547,13 +581,26 @@ class MOSCore:
|
|
|
547
581
|
and (mem_cube.text_mem is not None)
|
|
548
582
|
and self.config.enable_textual_memory
|
|
549
583
|
):
|
|
584
|
+
time_start = time.time()
|
|
550
585
|
memories = mem_cube.text_mem.search(
|
|
551
|
-
query,
|
|
586
|
+
query,
|
|
587
|
+
top_k=top_k if top_k else self.config.top_k,
|
|
588
|
+
mode=mode,
|
|
589
|
+
manual_close_internet=not internet_search,
|
|
590
|
+
info={
|
|
591
|
+
"user_id": target_user_id,
|
|
592
|
+
"session_id": self.session_id,
|
|
593
|
+
"chat_history": chat_history.chat_history,
|
|
594
|
+
},
|
|
552
595
|
)
|
|
553
596
|
result["text_mem"].append({"cube_id": mem_cube_id, "memories": memories})
|
|
554
597
|
logger.info(
|
|
555
598
|
f"🧠 [Memory] Searched memories from {mem_cube_id}:\n{self._str_memories(memories)}\n"
|
|
556
599
|
)
|
|
600
|
+
search_time_end = time.time()
|
|
601
|
+
logger.info(
|
|
602
|
+
f"time search graph: search graph time user_id: {target_user_id} time is: {search_time_end - time_start}"
|
|
603
|
+
)
|
|
557
604
|
return result
|
|
558
605
|
|
|
559
606
|
def add(
|
|
@@ -576,6 +623,7 @@ class MOSCore:
|
|
|
576
623
|
user_id (str, optional): The identifier of the user to add the memories to.
|
|
577
624
|
If None, the default user is used.
|
|
578
625
|
"""
|
|
626
|
+
# user input messages
|
|
579
627
|
assert (messages is not None) or (memory_content is not None) or (doc_path is not None), (
|
|
580
628
|
"messages_or_doc_path or memory_content or doc_path must be provided."
|
|
581
629
|
)
|
|
@@ -613,25 +661,31 @@ class MOSCore:
|
|
|
613
661
|
memories = self.mem_reader.get_memory(
|
|
614
662
|
messages_list,
|
|
615
663
|
type="chat",
|
|
616
|
-
info={"user_id": target_user_id, "session_id":
|
|
664
|
+
info={"user_id": target_user_id, "session_id": self.session_id},
|
|
617
665
|
)
|
|
666
|
+
|
|
667
|
+
mem_ids = []
|
|
618
668
|
for mem in memories:
|
|
619
|
-
self.mem_cubes[mem_cube_id].text_mem.add(mem)
|
|
669
|
+
mem_id_list: list[str] = self.mem_cubes[mem_cube_id].text_mem.add(mem)
|
|
670
|
+
mem_ids.extend(mem_id_list)
|
|
671
|
+
logger.info(
|
|
672
|
+
f"Added memory user {target_user_id} to memcube {mem_cube_id}: {mem_id_list}"
|
|
673
|
+
)
|
|
620
674
|
|
|
621
675
|
# submit messages for scheduler
|
|
622
|
-
mem_cube = self.mem_cubes[mem_cube_id]
|
|
623
676
|
if self.enable_mem_scheduler and self.mem_scheduler is not None:
|
|
624
|
-
|
|
677
|
+
mem_cube = self.mem_cubes[mem_cube_id]
|
|
625
678
|
message_item = ScheduleMessageItem(
|
|
626
679
|
user_id=target_user_id,
|
|
627
680
|
mem_cube_id=mem_cube_id,
|
|
628
681
|
mem_cube=mem_cube,
|
|
629
682
|
label=ADD_LABEL,
|
|
630
|
-
content=json.dumps(
|
|
683
|
+
content=json.dumps(mem_ids),
|
|
631
684
|
timestamp=datetime.now(),
|
|
632
685
|
)
|
|
633
686
|
self.mem_scheduler.submit_messages(messages=[message_item])
|
|
634
687
|
|
|
688
|
+
# user profile
|
|
635
689
|
if (
|
|
636
690
|
(memory_content is not None)
|
|
637
691
|
and self.config.enable_textual_memory
|
|
@@ -646,34 +700,66 @@ class MOSCore:
|
|
|
646
700
|
)
|
|
647
701
|
else:
|
|
648
702
|
messages_list = [
|
|
649
|
-
[
|
|
650
|
-
|
|
651
|
-
{
|
|
652
|
-
"role": "assistant",
|
|
653
|
-
"content": "",
|
|
654
|
-
}, # add by str to keep the format,assistant role is empty
|
|
655
|
-
]
|
|
656
|
-
]
|
|
703
|
+
[{"role": "user", "content": memory_content}]
|
|
704
|
+
] # for only user-str input and convert message
|
|
657
705
|
memories = self.mem_reader.get_memory(
|
|
658
706
|
messages_list,
|
|
659
707
|
type="chat",
|
|
660
|
-
info={"user_id": target_user_id, "session_id":
|
|
708
|
+
info={"user_id": target_user_id, "session_id": self.session_id},
|
|
661
709
|
)
|
|
710
|
+
|
|
711
|
+
mem_ids = []
|
|
662
712
|
for mem in memories:
|
|
663
|
-
self.mem_cubes[mem_cube_id].text_mem.add(mem)
|
|
713
|
+
mem_id_list: list[str] = self.mem_cubes[mem_cube_id].text_mem.add(mem)
|
|
714
|
+
logger.info(
|
|
715
|
+
f"Added memory user {target_user_id} to memcube {mem_cube_id}: {mem_id_list}"
|
|
716
|
+
)
|
|
717
|
+
mem_ids.extend(mem_id_list)
|
|
718
|
+
|
|
719
|
+
# submit messages for scheduler
|
|
720
|
+
if self.enable_mem_scheduler and self.mem_scheduler is not None:
|
|
721
|
+
mem_cube = self.mem_cubes[mem_cube_id]
|
|
722
|
+
message_item = ScheduleMessageItem(
|
|
723
|
+
user_id=target_user_id,
|
|
724
|
+
mem_cube_id=mem_cube_id,
|
|
725
|
+
mem_cube=mem_cube,
|
|
726
|
+
label=ADD_LABEL,
|
|
727
|
+
content=json.dumps(mem_ids),
|
|
728
|
+
timestamp=datetime.now(),
|
|
729
|
+
)
|
|
730
|
+
self.mem_scheduler.submit_messages(messages=[message_item])
|
|
731
|
+
|
|
732
|
+
# user doc input
|
|
664
733
|
if (
|
|
665
734
|
(doc_path is not None)
|
|
666
735
|
and self.config.enable_textual_memory
|
|
667
736
|
and self.mem_cubes[mem_cube_id].text_mem
|
|
668
737
|
):
|
|
669
738
|
documents = self._get_all_documents(doc_path)
|
|
670
|
-
|
|
739
|
+
doc_memories = self.mem_reader.get_memory(
|
|
671
740
|
documents,
|
|
672
741
|
type="doc",
|
|
673
|
-
info={"user_id": target_user_id, "session_id":
|
|
742
|
+
info={"user_id": target_user_id, "session_id": self.session_id},
|
|
674
743
|
)
|
|
675
|
-
|
|
676
|
-
|
|
744
|
+
|
|
745
|
+
mem_ids = []
|
|
746
|
+
for mem in doc_memories:
|
|
747
|
+
mem_id_list: list[str] = self.mem_cubes[mem_cube_id].text_mem.add(mem)
|
|
748
|
+
mem_ids.extend(mem_id_list)
|
|
749
|
+
|
|
750
|
+
# submit messages for scheduler
|
|
751
|
+
if self.enable_mem_scheduler and self.mem_scheduler is not None:
|
|
752
|
+
mem_cube = self.mem_cubes[mem_cube_id]
|
|
753
|
+
message_item = ScheduleMessageItem(
|
|
754
|
+
user_id=target_user_id,
|
|
755
|
+
mem_cube_id=mem_cube_id,
|
|
756
|
+
mem_cube=mem_cube,
|
|
757
|
+
label=ADD_LABEL,
|
|
758
|
+
content=json.dumps(mem_ids),
|
|
759
|
+
timestamp=datetime.now(),
|
|
760
|
+
)
|
|
761
|
+
self.mem_scheduler.submit_messages(messages=[message_item])
|
|
762
|
+
|
|
677
763
|
logger.info(f"Add memory to {mem_cube_id} successfully")
|
|
678
764
|
|
|
679
765
|
def get(
|
|
@@ -907,3 +993,27 @@ class MOSCore:
|
|
|
907
993
|
raise ValueError(f"Target user '{target_user_id}' does not exist or is inactive.")
|
|
908
994
|
|
|
909
995
|
return self.user_manager.add_user_to_cube(target_user_id, cube_id)
|
|
996
|
+
|
|
997
|
+
def get_query_rewrite(self, query: str, user_id: str | None = None):
|
|
998
|
+
"""
|
|
999
|
+
Rewrite user's query according the context.
|
|
1000
|
+
Args:
|
|
1001
|
+
query (str): The search query that needs rewriting.
|
|
1002
|
+
user_id(str, optional): The identifier of the user that the query belongs to.
|
|
1003
|
+
If None, the default user is used.
|
|
1004
|
+
|
|
1005
|
+
Returns:
|
|
1006
|
+
str: query after rewriting process.
|
|
1007
|
+
"""
|
|
1008
|
+
target_user_id = user_id if user_id is not None else self.user_id
|
|
1009
|
+
chat_history = self.chat_history_manager[target_user_id]
|
|
1010
|
+
|
|
1011
|
+
dialogue = "————{}".format("\n————".join(chat_history.chat_history))
|
|
1012
|
+
user_prompt = QUERY_REWRITING_PROMPT.format(dialogue=dialogue, query=query)
|
|
1013
|
+
messages = {"role": "user", "content": user_prompt}
|
|
1014
|
+
rewritten_result = self.chat_llm.generate(messages=messages)
|
|
1015
|
+
rewritten_result = json.loads(rewritten_result)
|
|
1016
|
+
if rewritten_result.get("former_dialogue_related", False):
|
|
1017
|
+
rewritten_query = rewritten_result.get("rewritten_question")
|
|
1018
|
+
return rewritten_query if len(rewritten_query) > 0 else query
|
|
1019
|
+
return query
|
memos/mem_os/main.py
CHANGED
|
@@ -208,7 +208,7 @@ class MOS(MOSCore):
|
|
|
208
208
|
if self.enable_mem_scheduler and self.mem_scheduler is not None:
|
|
209
209
|
from datetime import datetime
|
|
210
210
|
|
|
211
|
-
from memos.mem_scheduler.
|
|
211
|
+
from memos.mem_scheduler.schemas import (
|
|
212
212
|
ANSWER_LABEL,
|
|
213
213
|
ScheduleMessageItem,
|
|
214
214
|
)
|