Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9601ae9
feat: add in mem-reader
CaralHsi Jan 14, 2026
2c0d395
feat: add merge from in mem-reader
CaralHsi Jan 14, 2026
75c6590
feat: set merge ids archived
CaralHsi Jan 14, 2026
9094f96
Merge branch 'dev-20250114-v2.0.3' into feat/add-repeat
CaralHsi Jan 14, 2026
6e80154
feat: update en mem-reader prompt
CaralHsi Jan 14, 2026
cdccd63
Merge branch 'feat/add-repeat' of github.com:CaralHsi/MemOSRealPublic…
CaralHsi Jan 14, 2026
c3991dc
fix: abstract
CaralHsi Jan 14, 2026
4f30e44
fix: set graph db bug
CaralHsi Jan 14, 2026
c4ecfc8
fix: prompt build bug: replace None
CaralHsi Jan 15, 2026
a075316
Merge branch 'dev-20250114-v2.0.3' into feat/add-repeat
CaralHsi Jan 15, 2026
3bc301c
fix: did not pass through username into mem-reader transfer function
CaralHsi Jan 15, 2026
1906b97
Merge branch 'feat/add-repeat' of github.com:CaralHsi/MemOSRealPublic…
CaralHsi Jan 15, 2026
734bc8d
feat: fix user_name not pass bug
CaralHsi Jan 15, 2026
d7d302b
Merge branch 'dev-20250114-v2.0.3' into feat/add-repeat
CaralHsi Jan 15, 2026
7d2528b
feat: tackle with merged nodes when async mode in scheduler
CaralHsi Jan 15, 2026
f24040a
Merge branch 'feat/add-repeat' of github.com:CaralHsi/MemOSRealPublic…
CaralHsi Jan 15, 2026
8b55d63
feat: modify repeat problem
CaralHsi Jan 15, 2026
4279603
feat: modify multi modal struct
CaralHsi Jan 15, 2026
92c952a
feat: update en-version MEMORY_MERGE_PROMPT_EN
CaralHsi Jan 15, 2026
c69cbaa
feat: add status to some graph db func; modify prompt
CaralHsi Jan 15, 2026
6a149d9
fix: conflict
CaralHsi Jan 15, 2026
9b11b07
fix: status filter not specified bug; feat: log merge
CaralHsi Jan 15, 2026
39a38b9
Merge branch 'dev-20260114-v2.0.3' into feat/update-repeat-issue
CaralHsi Jan 16, 2026
22af266
feat: remove log_merge_check
CaralHsi Jan 16, 2026
dda541e
Merge branch 'feat/update-repeat-issue' of github.com:CaralHsi/MemOSR…
CaralHsi Jan 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/memos/graph_dbs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ def add_node(self, id: str, memory: str, metadata: dict[str, Any]) -> None:
"""

@abstractmethod
def update_node(self, id: str, fields: dict[str, Any]) -> None:
def update_node(self, id: str, fields: dict[str, Any], user_name: str | None = None) -> None:
"""
Update attributes of an existing node.
Args:
id: Node identifier to be updated.
fields: Dictionary of fields to update.
user_name: given user_name
"""

@abstractmethod
Expand Down Expand Up @@ -70,7 +71,7 @@ def edge_exists(self, source_id: str, target_id: str, type: str) -> bool:

# Graph Query & Reasoning
@abstractmethod
def get_node(self, id: str, include_embedding: bool = False) -> dict[str, Any] | None:
def get_node(self, id: str, include_embedding: bool = False, **kwargs) -> dict[str, Any] | None:
"""
Retrieve the metadata and content of a node.
Args:
Expand Down
16 changes: 7 additions & 9 deletions src/memos/mem_reader/multi_modal_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,12 @@ def _get_maybe_merged_memory(
)

if not search_results:
# No similar memories found, return original
return extracted_memory_dict

# Get full memory details
similar_memory_ids = [r["id"] for r in search_results if r.get("id")]
similar_memories_list = [
self.graph_db.get_node(mem_id, include_embedding=False)
self.graph_db.get_node(mem_id, include_embedding=False, user_name=user_name)
for mem_id in similar_memory_ids
]

Expand All @@ -505,7 +504,6 @@ def _get_maybe_merged_memory(
)

if not filtered_similar:
# No valid similar memories, return original
return extracted_memory_dict

# Create a temporary TextualMemoryItem for merge check
Expand All @@ -529,14 +527,12 @@ def _get_maybe_merged_memory(
if merge_result:
# Return merged memory dict
merged_dict = extracted_memory_dict.copy()
merged_dict["value"] = merge_result.get("value", mem_text)
merged_dict["merged_from"] = merge_result.get("merged_from", [])
logger.info(
f"[MultiModalFine] Merged memory with {len(merged_dict['merged_from'])} existing memories"
)
merged_content = merge_result.get("value", mem_text)
merged_dict["value"] = merged_content
merged_from_ids = merge_result.get("merged_from", [])
merged_dict["merged_from"] = merged_from_ids
return merged_dict
else:
# No merge needed, return original
return extracted_memory_dict

except Exception as e:
Expand Down Expand Up @@ -648,6 +644,7 @@ def _process_one_item(fast_item: TextualMemoryItem) -> list[TextualMemoryItem]:
extracted_memory_dict=m,
mem_text=m.get("value", ""),
sources=sources,
original_query=mem_str,
**kwargs,
)
# Normalize memory_type (same as simple_struct)
Expand Down Expand Up @@ -680,6 +677,7 @@ def _process_one_item(fast_item: TextualMemoryItem) -> list[TextualMemoryItem]:
extracted_memory_dict=resp,
mem_text=resp.get("value", "").strip(),
sources=sources,
original_query=mem_str,
**kwargs,
)
node = self._make_memory_item(
Expand Down
2 changes: 1 addition & 1 deletion src/memos/mem_scheduler/general_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,7 @@ def _process_memories_with_reader(
)

# Mark merged_from memories as archived when provided in memory metadata
if self.mem_reader and self.mem_reader.graph_db:
if self.mem_reader.graph_db:
for memory in flattened_memories:
merged_from = (memory.metadata.info or {}).get("merged_from")
if merged_from:
Expand Down
17 changes: 12 additions & 5 deletions src/memos/memories/textual/tree_text_memory/retrieve/recall.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def retrieve(
include_embedding=self.include_embedding,
user_name=user_name,
filter=search_filter,
status="activated",
)
return [TextualMemoryItem.from_dict(record) for record in working_memories[:top_k]]

Expand Down Expand Up @@ -247,7 +248,7 @@ def process_node(node):

# Load nodes and post-filter
node_dicts = self.graph_store.get_nodes(
list(candidate_ids), include_embedding=self.include_embedding
list(candidate_ids), include_embedding=self.include_embedding, user_name=user_name
)

final_nodes = []
Expand Down Expand Up @@ -277,7 +278,9 @@ def process_node(node):
{"field": "key", "op": "in", "value": parsed_goal.keys},
{"field": "memory_type", "op": "=", "value": memory_scope},
]
key_ids = self.graph_store.get_by_metadata(key_filters, user_name=user_name)
key_ids = self.graph_store.get_by_metadata(
key_filters, user_name=user_name, status="activated"
)
candidate_ids.update(key_ids)

# 2) tag-based OR branch
Expand All @@ -286,7 +289,9 @@ def process_node(node):
{"field": "tags", "op": "contains", "value": parsed_goal.tags},
{"field": "memory_type", "op": "=", "value": memory_scope},
]
tag_ids = self.graph_store.get_by_metadata(tag_filters, user_name=user_name)
tag_ids = self.graph_store.get_by_metadata(
tag_filters, user_name=user_name, status="activated"
)
candidate_ids.update(tag_ids)

# No matches → return empty
Expand Down Expand Up @@ -422,9 +427,11 @@ def _bm25_recall(
value = search_filter[key]
key_filters.append({"field": key, "op": "=", "value": value})
corpus_name += "".join(list(search_filter.values()))
candidate_ids = self.graph_store.get_by_metadata(key_filters, user_name=user_name)
candidate_ids = self.graph_store.get_by_metadata(
key_filters, user_name=user_name, status="activated"
)
node_dicts = self.graph_store.get_nodes(
list(candidate_ids), include_embedding=self.include_embedding
list(candidate_ids), include_embedding=self.include_embedding, user_name=user_name
)

bm25_query = " ".join(list({query, *parsed_goal.keys}))
Expand Down
4 changes: 3 additions & 1 deletion src/memos/multi_mem_cube/single_cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,9 @@ def _process_text_mem(
for old_id in old_ids:
try:
self.mem_reader.graph_db.update_node(
str(old_id), {"status": "archived"}
str(old_id),
{"status": "archived"},
user_name=user_context.mem_cube_id,
)
self.logger.info(
f"[SingleCubeView] Archived merged_from memory: {old_id}"
Expand Down