离线助手记忆更新:相似度只负责召回
作者用实际嵌入模型测试发现,0.8 的余弦阈值会漏掉事实改写与更新,且早期评估误用了 L2 距离。修正后改用约 0.5 的阈值召回候选,再交给大模型判断事实变更。
AI 深度解读
给 AI 助手加长期记忆,难点不只是把事实存下来。用户说「我不再喜欢国际象棋」,系统还得判断:这是新增信息、修改旧偏好,还是撤回一条记忆?Neo 作者最初用余弦相似度大于 0.8 判断矛盾,实测后发现,这条规则连改写和更新都可能漏掉。
他的调整很实用:相似度负责找候选,LLM 负责提出操作,代码负责检查操作能不能执行。做 AI 编程和记忆系统的人,可以从中看到模型判断与程序规则该怎样分工。
为什么 0.8 没能识别记忆变化
Neo 是一个本地 AI 助手,通过 Ollama 运行 llama3.1,用 LanceDB 存向量、SQLite 存事实,并通过自托管的 SearXNG 搜索网页,不依赖云端模型和 API keys。这里的「离线」主要指模型与记忆在本地,网页搜索仍需要网络。
作者最初的规则是:新旧事实的余弦相似度超过 0.8,就当作矛盾处理。
问题分两层。首先,阈值没有经过实际模型校准。作者用 Ollama 中实际使用的 embedding 模型测试了 10 组真实句子对,发现 0.8 会漏掉改写和更新;无关句子的分数只有 0.29 到 0.41,有用的区分范围比他预想的低。
其次,语义相近只能说明值得比较,不能直接说明事实矛盾。「我喜欢国际象棋」和「我很喜欢下国际象棋」可能只是重复表达,而「我不再喜欢国际象棋」才涉及旧偏好的变化。一个相似度分数承担不了这些分类。
作者还发现,早期检索评估实际测的是 L2 距离,而非余弦相似度。修正指标后,Recall@k 为 0.95,MRR 为 0.925。前者关注正确结果是否进入前 k 个候选,后者关注正确结果排得是否靠前。原文没有交代评估集规模和 k 值,不能据此推断整个记忆系统已经可靠。
把模型判断夹在检索和代码校验之间
新方案把候选阈值降到约 0.5,只检索仍有效的事实。下面这段流程解决的是「先找到可能相关的旧记忆,再决定怎么处理」:
new fact
↓
find candidates (cosine ≥ 0.5, active facts only)
↓
no candidates → ADD
candidates found → LLM returns {action, target_id}
↓
code validates the answer
↓
write to SQLite + LanceDB
要盯住的是 code validates the answer:LLM 返回结果之后,还有一道程序校验,随后才写入数据库。
模型只能选择 ADD、UPDATE、DELETE、NONE,并提供目标 id。代码再执行两条明确规则:
- 目标 id 不存在或格式错误,就回退为 ADD。
- UPDATE 的目标文本与新事实完全一致,就改为 NONE。
作者观察到,llama3.1 有时会对已经存在的事实返回 UPDATE,也会选错目标。调整提示词有所帮助,但他认为,真正让流程稳定下来的是代码守卫。
这套分工保留了模型理解自然语言的能力,也把可确定的检查交给了程序。目标是否存在、文本是否完全相同,都没有必要再让模型猜一次。
我的判断
我认同这次调整的方向:相似度适合筛选候选,结构化输出适合约束模型,程序规则适合守住写入条件。相比继续把所有判断塞进一个阈值或不断补提示词,这种流程更容易逐项测试。
但它仍有边界。**0.5 是作者当前实验中的选择,不能直接当成通用阈值。**10 组句子对足以暴露问题,还不足以覆盖大量表达方式。原文也没给出新旧方案在事实处理准确率上的完整对照,因此「更可靠」目前主要是作者的工程经验。
两条守卫也没有覆盖所有错误。错误 id 回退 ADD,可能留下重复或互相冲突的事实;模型选中一个真实存在、但语义上错误的目标,单靠 id 校验拦不住。文本完全相同才能转为 NONE,也处理不了措辞不同的重复事实。
作者还交代了项目状态:v1.9 大部分借助 Claude 编写,但运行不稳定,因此他从 v1.8.5 出发,手动重建了 v1.9.5,以理解各个部分。README 标注了 AI 协助,KNOWN_ISSUES.md 列出了限制,包括无法提取比较型偏好、后续网页查询丢失上下文,以及需要能在本地运行 8B 模型的硬件。这些信息比单独报一个检索分数更有助于判断项目是否适合自己。
能拿来做什么
- 给 Node 记忆服务定阈值前,先用实际 embedding 模型测试重复、改写、更新、否定和无关句子,并确认评估使用的是 L2 还是 cosine。
- 把模型输出限制为
{action, target_id}这样的窄接口,在数据库写入前检查操作类型、目标是否存在和重复内容。 - 用假的 LLM 调用测试分支逻辑,覆盖错误 id、相同文本 UPDATE、无候选 ADD 等情况,让这些检查无需启动 Ollama。
- 接手 AI 生成的记忆系统代码时,先梳理「检索、决策、校验、写入」这条路径,逐段确认规则,并记录尚未覆盖的行为。