从零实现 GeekAgent —— Day13 主动记忆

💡 原文中文,约11400字,阅读约需28分钟。
📝

内容提要

本文介绍GeekAgent第13天实现“主动记忆”功能:在每轮对话前自动检索长期记忆,无需模型主动调用搜索工具。实现方法包括将长记忆按320字窗口、80字重叠切块,用BM25算法排序,并将命中结果拼入系统提示。相比手动搜索,自动唤起更早介入,提升记忆利用率。

🔎

延伸解读

自动唤起与手动搜索的取舍

自动唤起在每轮对话前自动检索,模型无需主动调用工具,能避免因模型未想到搜索而遗漏记忆。但手动搜索仍保留,适合模型需要更明确关键词时深挖。两者互补,自动唤起提供默认回忆,手动搜索提供定向查询,共同提升记忆利用率。

BM25 与向量检索的适用场景

本文选择 BM25 而非向量检索,因其无需额外模型和索引,适合记忆量小的场景。BM25 基于词频和常见度打分,能处理字面匹配,但无法理解同义词。向量检索虽能处理语义相近,但需额外资源。当前阶段 BM25 足够,未来可考虑升级。

分块与重叠的设计考量

长记忆按 320 字窗口、80 字重叠切块,既避免返回整条长文,又防止关键信息被切在边界。重叠确保句子完整出现在某一块中,提高检索精度。这种设计在保持磁盘格式不变的同时,实现了更精细的检索粒度。

Q&A

GeekAgent Day13 的主动记忆功能是什么?

主动记忆功能是在每轮对话前自动检索长期记忆,将相关记忆块拼入系统提示,无需模型主动调用 memory_search 工具。

主动记忆和模型自己调用 memory_search 有什么区别?

主动记忆由主程序在每轮对话开始前自动检索,使用用户的原始问题作为查询;而 memory_search 由模型决定何时调用,使用模型整理的关键词。主动记忆更早介入,避免模型忘记搜索。

为什么需要主动记忆功能?

因为模型可能不会主动调用 memory_search,导致长期记忆中的信息无法进入当前对话。此外,原来的搜索存在长记忆整条返回、排序不考虑词频和长度的问题。

主动记忆是如何实现的?

实现步骤包括:将长记忆按320字窗口、80字重叠切块;使用BM25算法对记忆块打分排序;在每轮用户提问后,自动检索并将前五个命中块拼入系统提示。

BM25 算法在主动记忆中是如何应用的?

BM25 是一种关键词检索算法,根据查询词在文档中的出现频率、常见程度和文档长度进行打分。在主动记忆中,中文问题被切成 bigram,英文和数字保留整词,然后对每个记忆块计算 BM25 分数,取前五名作为命中结果。

为什么选择 BM25 而不是向量检索?

因为当前知识量只有几十条记忆,BM25 无需额外模型和索引,代码简单,足以展示完整检索过程。向量检索需要 embedding 模型和向量索引,更适合大规模语义检索。

主动记忆功能有哪些限制?

限制包括:不做向量检索,只按字面匹配;不支持修改、删除和合并记忆;不记录时间,不判断内容是否过期;bigram 不理解同义词,换一种说法可能搜不到。

如何验证主动记忆功能是否正常?

验证步骤:运行 typecheck 和 dev 命令,让模型保存一段超过320字的记忆,确认面板显示至少2个块,重启程序后换一种说法询问压缩阈值,确认回答包含4000且没有调用 memory_search,最后用 /memory 查看磁盘中保存的仍是完整记忆。

🏷️

标签

➡️

继续阅读