diff --git a/go/internal/api/server.go b/go/internal/api/server.go index 5797efd..6109241 100644 --- a/go/internal/api/server.go +++ b/go/internal/api/server.go @@ -864,40 +864,54 @@ func NewServer() http.Handler { ignored := 0 errors_ := 0 + // 按目标分组整合:外层 i 为目标,内层收集所有高相似候选, + // 每个目标只调一次 LLM(UpdatePrompt 原生支持多候选),避免 O(n²) LLM 调用风暴。 + // 2026-09-06 fix(t_04 ④): 原实现每对相似记忆调一次 LLM → limit=100 产生 4950 对 + // → 跑 223s+ 未完成 → 每天 processed=0(不是 namespace 过滤 bug)。 for i := 0; i < len(mems); i++ { + // 收集所有与 mems[i] 高相似的候选(j > i 且未处理) + var cands []distill.MemoryCandidate for j := i + 1; j < len(mems); j++ { + if mems[j].Content == "" { + continue + } sim := distill.TextSimilarity(mems[i].Content, mems[j].Content) if sim < 0.5 { continue } - // 高相似 → LLM 决策(以 j 为目标,i 为候选) - result, err := routes.DistillEngineRef.ConsolidateMemory( - distill.MemoryCandidate{ID: mems[j].ID, Content: mems[j].Content}, - []distill.MemoryCandidate{{ID: mems[i].ID, Content: mems[i].Content}}, - ) - if err != nil { - errors_++ - continue - } - processed++ - switch result.Action { - case "update": - if result.NewMemory != "" { - if err := ldb.UpdateMemoryContent(mems[j].ID, result.NewMemory, "consolidate"); err != nil { - log.Printf("[consolidate] update failed %s: %v", mems[j].ID, err) - } else { - updated++ - } - } - case "delete": - if err := ldb.SoftDelete(mems[j].ID, "consolidate: conflict"); err != nil { - log.Printf("[consolidate] delete failed %s: %v", mems[j].ID, err) + cands = append(cands, distill.MemoryCandidate{ID: mems[j].ID, Content: mems[j].Content}) + } + if len(cands) == 0 { + continue + } + + // 一次 LLM 决策:目标 mems[i] + 全部高相似候选 + result, err := routes.DistillEngineRef.ConsolidateMemory( + distill.MemoryCandidate{ID: mems[i].ID, Content: mems[i].Content}, + cands, + ) + if err != nil { + errors_++ + continue + } + processed++ + switch result.Action { + case "update": + if result.NewMemory != "" { + if err := ldb.UpdateMemoryContent(mems[i].ID, result.NewMemory, "consolidate"); err != nil { + log.Printf("[consolidate] update failed %s: %v", mems[i].ID, err) } else { - deleted++ + updated++ } - default: - ignored++ } + case "delete": + if err := ldb.SoftDelete(mems[i].ID, "consolidate: conflict"); err != nil { + log.Printf("[consolidate] delete failed %s: %v", mems[i].ID, err) + } else { + deleted++ + } + default: + ignored++ } }