fix(memory): 修图记忆召回的两处能力缺失(关系重复 + 原句不回显)

针对 memory_recall / 自动注入这条图记忆召回链路的实测复核:

- Recall(depth>1) 跨层不去重:每层都用已累积的 entityIDs 查邻接,
  上一层刚产出的关系会在下一层被反复查回并再次 append。实测
  小明→小红 在 depth=2 出现两次,memory_recall 的 10 条关系预算被
  同一句话刷屏、真正的新关系(小红→小刚)被截断。改为按 relation ID
  跨层去重(实体本就已去重)。
- memory_recall 从不回显 sentence_text:工具 schema 明写「填了才能日后
  从图谱回到原文」、Recall 也已 JOIN 出句子,但输出只给实体名与关系类型,
  该字段形同虚设。抽出 formatRecallRelations,对非空原句截断 60 字附在
  关系行后;超过 10 条仍截断并提示。

测试:TestRecallWithDepth 增补去重与精确条数断言;
新增 TestFormatRecallRelations_SurfacesSentence / _Truncates。
go build/vet 干净,go test -race ./internal/memory/ ./internal/agent/core/... 全绿。
This commit is contained in:
JianFeeeee
2026-09-15 06:48:36 +08:00
parent c34e7cbb25
commit 990e740a37
5 changed files with 87 additions and 8 deletions

View File

@ -174,13 +174,7 @@ func (a *Agent) executeMemoryTool(tc agentAPI.ToolCall) string {
parts = append(parts, fmt.Sprintf("- %s (提及%d次, 类型:%s)", e.Name, e.MentionCount, e.Type))
}
parts = append(parts, fmt.Sprintf("找到 %d 条关系:", len(result.Relations)))
for i, r := range result.Relations {
if i >= 10 {
parts = append(parts, "...更多关系被截断")
break
}
parts = append(parts, fmt.Sprintf("- %s →(%s)→ %s", r.SourceName, r.RelationType, r.TargetName))
}
parts = append(parts, formatRecallRelations(result.Relations, 10)...)
// 命中的关系若挂着媒体块,把媒体说明附在结果末尾。
//
// 关系行只有实体名和关系类型,看不出"这条记忆当时还带了一张图"。