From 4495447b8598dce7cf484c829be1aa826f109e8e Mon Sep 17 00:00:00 2001 From: jianf <2198972886@qq.com> Date: Sun, 19 Jul 2026 14:21:04 +0800 Subject: [PATCH] fix(document memory): dedup graph sync, filter terminal output from archive, add min relevance threshold --- internal/agent/core/agent.go | 19 ++++++++++++++++--- internal/agent/core/context.go | 13 ++++++++++--- internal/memory/vector/store.go | 2 +- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/internal/agent/core/agent.go b/internal/agent/core/agent.go index 8b72946..f133203 100644 --- a/internal/agent/core/agent.go +++ b/internal/agent/core/agent.go @@ -1532,11 +1532,15 @@ func (a *Agent) executeDocTool(tc agentAPI.ToolCall) string { parts = append(parts, " 标签: "+strings.Join(d.Tags, ", ")) } // 每个文档按原始时间写入 context 事件,确保时序正确 + content := d.Content + if len(content) > 2000 { + content = content[:2000] + "..." + } a.context.Append(ContextEvent{ Timestamp: d.CreatedAt, Source: "cold_storage", Input: fmt.Sprintf("加载文档记忆: %s", query), - Response: d.Content, + Response: content, }) refs = append(refs, fmt.Sprintf("#%d(%s)", i+1, d.Summary)) } @@ -2306,9 +2310,18 @@ func (a *Agent) syncGraphToDocs() { } } + summary := fmt.Sprintf("图记忆索引 (%d 实体, %d 关系)", len(result.Entities), len(result.Relations)) + content := strings.Join(summaryParts, "\n") + + // 去重:如果最近一篇 graph 文档内容相同,跳过 + recent := a.docStore.RecentDocs(1) + if len(recent) > 0 && recent[0].Source == "graph" && recent[0].Content == content { + return + } + doc := &document.Doc{ - Summary: fmt.Sprintf("图记忆索引 (%d 实体, %d 关系)", len(result.Entities), len(result.Relations)), - Content: strings.Join(summaryParts, "\n"), + Summary: summary, + Content: content, Tags: []string{"graph_memory", "auto_sync"}, Entities: extractEntityNames(result.Entities), Source: "graph", diff --git a/internal/agent/core/context.go b/internal/agent/core/context.go index 53ac36c..cc97728 100644 --- a/internal/agent/core/context.go +++ b/internal/agent/core/context.go @@ -191,8 +191,15 @@ func (c *RelevanceContext) Prune(currentInput string, topK int, docStore *docume archived := 0 if docStore != nil && len(archive) > 0 { - entries := make([]document.ContextEntry, len(archive)) - for i, s := range archive { + var filtered []scored + for _, s := range archive { + if s.event.Source == "agentcli" || s.event.Source == "terminal" { + continue + } + filtered = append(filtered, s) + } + entries := make([]document.ContextEntry, len(filtered)) + for i, s := range filtered { entries[i] = document.ContextEntry{ Timestamp: s.event.Timestamp, Source: s.event.Source, @@ -202,7 +209,7 @@ func (c *RelevanceContext) Prune(currentInput string, topK int, docStore *docume } doc, err := docStore.ContextToDoc("context_archived", entries, c.embedder) if err == nil && doc != nil { - archived = len(archive) + archived = len(filtered) } } diff --git a/internal/memory/vector/store.go b/internal/memory/vector/store.go index 3f3b422..9011dda 100644 --- a/internal/memory/vector/store.go +++ b/internal/memory/vector/store.go @@ -84,7 +84,7 @@ func (s *Store) Search(query Vector, topK int) []DocVector { for _, d := range s.docs { if d.ID == id { score := CosineSimilarity(query, d.Vector) - if score > 0 { + if score > 0.05 { results = append(results, scored{d, score}) } break