Skip to content

feat: prevent repeated memories via archival and activated-only retrieval#880

Merged
CaralHsi merged 6 commits intodev-20260112-v2.0.2from
dev-20260114-v2.0.3
Jan 16, 2026
Merged

feat: prevent repeated memories via archival and activated-only retrieval#880
CaralHsi merged 6 commits intodev-20260112-v2.0.2from
dev-20260114-v2.0.3

Conversation

@CaralHsi
Copy link
Collaborator

@CaralHsi CaralHsi commented Jan 16, 2026

Summary

This PR closes the loop on the “repeated memory” problem at the add stage.

Previously, when adding new memories, the system could:

  • create a new node that is semantically identical to an existing one,
  • continue to return both the old and the new memory during recall,
  • allow merged_from memories to keep influencing downstream reasoning.

Now, when a new memory is added, we:

  1. search for similar existing memories,
  2. let a dedicated “memory merge” prompt decide whether they should be merged,
  3. archive any merged_from nodes so they no longer participate in recall.

Combined with stricter filtering on status="activated", this ensures that:

  • stable facts are stored once,
  • merged-away memories are cleanly retired,
  • recall results are less noisy and more consistent.

What’s changed

1. Mem-reader: detect & merge repeated memories on add

  • Inject graph_db into MemReader via MemReaderFactory.from_config(..., graph_db=...), so readers can:
    • look up similar memories before writing,
    • perform semantic deduplication and conflict detection.
  • Add dedicated memory merge prompts (MEMORY_MERGE_PROMPT_EN / MEMORY_MERGE_PROMPT_ZH) to:
    • split the new input into fact units (identity, stable preferences, relationships, one-off plans),
    • distinguish “repeated confirmation of the same fact” from genuinely new information,
    • decide whether to:
      • merge and return { value, merged_from, should_merge: true }, or
      • skip merging with { should_merge: false }.
  • When merging, the new memory:
    • keeps a single, non-redundant value,
    • records the source IDs in merged_from for later archival.

2. Graph DB & recall: only activated memories, plus archival

  • Extend the graph DB base and implementations (Neo4j / PolarDB) to support:
    • update_node(id, fields, user_name=None) with tenant context,
    • get_node(..., **kwargs) and get_nodes(ids, ..., **kwargs) for user-scoped queries,
    • get_by_metadata(filters, status=None) and get_all_memory_items(scope, ..., status=None) with optional status filtering.
  • In TreeText retrieval:
    • all metadata-based lookups now filter with status="activated",
    • all bulk node loads pass user_name to respect multi-tenant isolation.
  • In scheduler & single-cube flows:
    • whenever a memory carries merged_from in metadata.info, the referenced IDs are updated to:
      {"status": "archived"}
      with the proper user_name / mem_cube_id,
    • archived nodes are thus excluded from future recall.

3. Prompt & behavior: make “repeat vs. new” explicit

  • Introduce explicit, language-level rules for memory merging:
    • do not repeat the same fact multiple times or just because it was mentioned at different timestamps,
    • avoid mixing long-term preferences with one-off plans in the same merged value,
    • only include time information when it changes the meaning (e.g. “used to dislike → now likes”).
  • This makes the add-path behavior much more predictable:
    • stable user facts converge into a single clean memory,
    • purely one-off events are not mistakenly merged into long-term profiles,
    • downstream components see a de-duplicated, clearer memory graph.

Fix: #881

Docs Issue/PR: (docs-issue-or-pr-link)

Reviewer: @(reviewer)

Checklist:

  • I have performed a self-review of my own code | 我已自行检查了自己的代码
  • I have commented my code in hard-to-understand areas | 我已在难以理解的地方对代码进行了注释
  • I have added tests that prove my fix is effective or that my feature works | 我已添加测试以证明我的修复有效或功能正常
  • I have created related documentation issue/PR in MemOS-Docs (if applicable) | 我已在 MemOS-Docs 中创建了相关的文档 issue/PR(如果适用)
  • I have linked the issue to this PR (if applicable) | 我已将 issue 链接到此 PR(如果适用)
  • I have mentioned the person who will review this PR | 我已提及将审查此 PR 的人

* feat: add  in mem-reader

* feat: add merge from in mem-reader

* feat: set merge ids archived

* feat: update en mem-reader prompt

* fix: abstract

* fix: set graph db bug
* feat: add  in mem-reader

* feat: add merge from in mem-reader

* feat: set merge ids archived

* feat: update en mem-reader prompt

* fix: abstract

* fix: set graph db bug

* fix: prompt build bug: replace None
* feat: add  in mem-reader

* feat: add merge from in mem-reader

* feat: set merge ids archived

* feat: update en mem-reader prompt

* fix: abstract

* fix: set graph db bug

* fix: prompt build bug: replace None

* fix: did not pass through username into mem-reader transfer function

* feat: fix user_name not pass bug

* feat: tackle with merged nodes when async mode in scheduler

* feat: modify repeat problem

* feat: modify multi modal struct

* feat: update en-version MEMORY_MERGE_PROMPT_EN
* feat: add  in mem-reader

* feat: add merge from in mem-reader

* feat: set merge ids archived

* feat: update en mem-reader prompt

* fix: abstract

* fix: set graph db bug

* fix: prompt build bug: replace None

* fix: did not pass through username into mem-reader transfer function

* feat: fix user_name not pass bug

* feat: tackle with merged nodes when async mode in scheduler

* feat: modify repeat problem

* feat: modify multi modal struct

* feat: update en-version MEMORY_MERGE_PROMPT_EN

* feat: add status to some graph db func; modify prompt
…val (#874)

* feat: add  in mem-reader

* feat: add merge from in mem-reader

* feat: set merge ids archived

* feat: update en mem-reader prompt

* fix: abstract

* fix: set graph db bug

* fix: prompt build bug: replace None

* fix: did not pass through username into mem-reader transfer function

* feat: fix user_name not pass bug

* feat: tackle with merged nodes when async mode in scheduler

* feat: modify repeat problem

* feat: modify multi modal struct

* feat: update en-version MEMORY_MERGE_PROMPT_EN

* feat: add status to some graph db func; modify prompt

* fix: status filter not specified bug; feat: log merge

* feat: remove log_merge_check
@CaralHsi CaralHsi changed the title Dev 20260114 v2.0.3 feat: prevent repeated memories via archival and activated-only retrieval Jan 16, 2026
@CaralHsi CaralHsi marked this pull request as ready for review January 16, 2026 02:58
@CaralHsi CaralHsi merged commit deec71e into dev-20260112-v2.0.2 Jan 16, 2026
32 checks passed
@CarltonXiang CarltonXiang deleted the dev-20260114-v2.0.3 branch January 19, 2026 02:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant