Mnemosyne OS

什么是 AI 记忆:从上下文窗口到持久记忆层

AI 记忆(AI memory)指让大模型在多轮对话、多个会话、多个任务之间保留信息的机制。它不是模型权重的一部分,而是模型之外的一层独立存储与检索系统。本文解释它为什么必需、由哪些部分组成、如何被评测,以及在工程上做取舍时真正重要的那几个问题。

本文的数据来源:基准分数(LongMemEval 96.2 等)来自 Mnemosyne OS 项目公布的测试报告,可复现脚本在仓库 scripts/ 下;延迟数字(召回 p50 3.9 ms 等)是本文作者在 2026-10-27 用 mnemosyne-os 8.1.0.post1 在本机实测所得,样本量与方法写在第五节。两者来源不同,不混为一谈。

一、为什么大模型会「忘记」

把这件事说清楚,比任何产品宣传都重要。大模型忘事有三个彼此独立的原因,任何一个单独存在都会导致遗忘。

1. 上下文窗口是有限的

每次调用模型,你都要把「希望它看到的全部内容」重新发一遍。窗口能装多少,取决于模型的上下文长度——从早期的 4K 到现在常见的 128K、200K,甚至百万级。但无论多大,它都是一个有限容器。一旦对话长度超过它,就必须丢弃一部分。

丢弃是有代价的:被丢掉的往往是开头。而开头恰恰是用户交代背景、身份、偏好的地方。这就是为什么长对话进行到后期,助手会突然不记得你最开始说的约束条件。

2. 每次请求都是无状态调用

模型服务不保存你的会话。你看到的「连续对话」,是客户端每次把历史记录重新拼进请求的结果。换个客户端、换个会话、隔一天再来,历史就断了——不是模型不想记,是它根本没收到过。

3. 模型权重里没有「你」

预训练学到的是世界知识,不是你个人的偏好。你和模型的每一次交互,对权重的影响都是零。微调可以注入风格或领域知识,但成本高、更新慢,且不适合承载「用户昨天说他要搬到上海」这类高频变化的个人事实。

结论:记忆必须由外部系统提供。它不是模型能力的补丁,而是一个独立的基础设施层——就像每个应用都需要数据库,每个有状态的 AI 应用都需要记忆层。

二、AI 记忆系统的七个组成部分

很多人把「AI 记忆」等同于「向量检索」。这个理解会让人在真实场景里反复踩坑。一个能用的记忆系统至少包含七个部分,缺哪一块都会在特定场景下暴露问题。

1. 写入与抽取

用户说的话不能原样存。一段对话里可能同时包含:一条关于身份的稳定事实(「我是南京人」)、一条临时约束(「这次用英文回复」)、一句闲聊(「今天天气不错」)。写入层要做的是把对话拆成可检索的事实单元,并判断哪条值得存。

这里有个关键设计分歧:生成式抽取(让模型改写、摘要、归纳)vs 单遍只增不改(one-pass ADD-only)。前者压缩率高,但会引入原文没有的事实——一旦摘要有偏差,错误会被永久固化。后者每条写入只调用一次模型,记录只增不改,坏抽取最多带来噪音,永远不会销毁真实事实。Mnemosyne OS 选择的是后者,理由是:记忆系统的失败模式应该是「多存了没用的」,而不是「把真的改错了」。

2. 存储与作用域

记忆必须能按主体切分。常见的四个维度是 user_id(谁)、agent_id(哪个智能体)、run_id(哪次任务)、app_id(哪个应用)。

切分有两种实现:逻辑隔离(同一张表,加过滤条件)和物理隔离(每个作用域一个独立存储文件)。逻辑隔离省事,但一次漏写过滤条件就是跨用户数据泄露。物理隔离成本高一点,但隔离由文件系统保证,不依赖每一处查询都记得加条件。对承载个人记忆的系统,物理隔离是更稳的选择。

3. 检索与融合

单一检索方式都有盲区:

生产系统通常把多路结果融合排序(如 RRF),再用一个校准过的相关性下限截断。这个下限很重要:如果永远填满 top-k,最高分恒为 1.0,分数就失去了绝对意义,用户看到的「相关度 0.92」其实毫无信息量。

4. 更新、冲突与时效

用户上周说「我在北京」,这周说「我搬到上海了」。这两条不矛盾,是时间演进;但如果两条都被检索出来且都标为当前事实,就会得到自相矛盾的答案。

需要处理的情形至少有六类:时间更新、偏好变更、作用域差异(工作号 vs 私人号)、精度差异(「大概三十岁」vs「32 岁」)、逻辑矛盾、来源冲突。对应四种动作:新增、保持、更新、并存。把「实体共现」误判成「冲突」是常见 bug——提到同一个人不等于说了矛盾的话。

5. 遗忘与压缩

记忆不会只增不减。真正的系统需要遗忘经济学:低价值记忆被降级、被压缩,而不是被静默删除。分层(热 / 温 / 冷)是常见做法:热层全量在内存,温层按需加载,冷层压缩成可还原的胶囊。

压缩这里有个容易夸大的指标。压缩比取决于原文长度和预算:短文本压不动,长文本才压得动。实测(见第五节):一条 23 字符的记忆,在 60 token 预算下压缩比为 1.0——它已经是压缩的下限形态。任何宣称「固定 32 倍压缩」的说法,都需要追问一句:在什么长度、什么预算下。

6. 审计与可追溯

「记住了什么、改了什么、忘了什么」应当有可证明的记录。哈希链(SHA-256 chain)是低成本方案:每次写入把前一条的哈希纳入计算,篡改任何一条都会导致后续全部校验失败,且能定位到具体是哪一条被改。

更细一层是指针链回溯:一条结论是从哪几句原话推出来的。这需要记忆层级(L1 原文 → L2 会话摘要 → L3 主题摘要)和每层保存的 message_ids。

7. 注入与预算

检索出来的内容最终要塞进上下文窗口。这里的问题不是「取多少」,而是「怎么在预算内取最有用的」。渐进披露(先给目录、再展开少量)能把注入成本从 O(全部) 降到 O(目录 + 少数几条)。配额分配(画像 / 任务相关 / 经验 / 未决)也是同一思路。

三、AI 记忆怎么被评测

这个领域最容易造假的地方就是「召回率」。因为检索是「取前 k 条」,如果永远填满 k 条,前 k 条的命中率天然接近 100%。所以看评测必须看它测什么。

基准测什么为什么重要
LongMemEval长跨度对话中的事实召回模拟真实用户几十轮、跨多天的使用
LoCoMo多会话对话记忆跨会话指代消解与事件串联
BEAM (1M / 10M)超大上下文预算下的召回上下文越长,检索噪声越大,越考验排序

Mnemosyne OS 公布的分数是:

基准分数说明
LongMemEval96.2long-horizon conversational recall
LoCoMo94.8multi-session dialogue memory
BEAM (1M)68.5recall under a 1M-token context budget
BEAM (10M)53.9recall under a 10M-token context budget

分数满分 100。作为对照,Mem0 在其官网公布的数字是 LongMemEval 94.4、LoCoMo 92.5、BEAM 1M 64.1、BEAM 10M 48.6。两组数字来自各自的测试报告,不是同一次独立评测,引用时不应合并成一个「第三方研究」。

怎么判断一个基准可不可信:看它有没有把复现脚本一起发出来。Mnemosyne OS 把 scripts/verify_recall_quality.py 与 scripts/verify_precision_recall.py 放在公开仓库里,任何人都能在自己的语料上重跑。没有脚本的分数,只能当宣传看。

四、自建 vs 托管:怎么选

这是用户搜索「AI 记忆」时最终要做的决策。

维度自托管(本地优先)托管 SaaS
数据位置你自己磁盘上的一个 SQLite 文件服务商的服务器
删除的彻底性删文件 = 完全删除,没有副本要追依赖服务商的删除策略与备份周期
运维成本需要自己跑进程、备份注册即用
多端同步需自己解决天然支持
成本模型一次性硬件 / 已有服务器按月订阅
合规审查数据不出境,易举证取决于服务商所在司法辖区

实践中的常见组合是:开发阶段用自托管跑通(零成本、可调试、能看底层数据),上线后按需选托管。同一套引擎两种形态,迁移时不需要重写业务代码——这是把「引擎」和「托管」分开设计带来的好处。

五、一次本机实测:数字长什么样

以下是本文作者在 2026-10-27 的实测,环境为 Windows、Python 3.13.12、mnemosyne-os 8.1.0.post1,默认零配置(未配置 LLM、未配置向量库、未下载任何模型)。

测试方法

结果

指标实测值备注
引擎初始化0.24 ms建库 + 加载插件
单条写入(中位)11.91 ms含抽取,无 LLM 调用
单条写入(P95)21.11 ms
200 条写入总耗时2.4 s串行写入
召回(中位)3.924 ms300 次采样
召回(P95)5.955 ms
召回(最快)1.393 ms
完整性校验4.5 ms120 条记忆的全链校验
120 条记忆占盘5.5 MB含向量与索引

必须说清的一点:这些数字是「默认零配置」下的表现,此时用的是内置 128 维确定性嵌入 + 规则抽取,不需要任何 API Key,也不下载模型。配置了真实嵌入模型(如 BGE-M3 1024 维)后,召回质量会提升,延迟也会变化——通常是单次几十毫秒量级,取决于模型是在本地还是在远端。

项目 README 里提到的 0.21 ms 召回是他们的测试环境数据,本文没有复现出该数字,因此不引用它作为本机结论。

六、七个组成部分各自的失败模式

知道一个系统有哪些部件意义有限;知道每个部件坏了会表现成什么样,才能排查。

部件坏掉时的症状怎么确认是它的问题
写入与抽取记忆里全是原文复读,或关键事实丢失打印 add() 返回的 results,看抽取出的条目是否包含关键实体
存储与作用域召回总是空,或看到不该看的数据用 get_all(filters=...) 直接查该作用域条数
检索与融合结果和查询无关,或精确串搜不到分别用语义与关键词检索同一查询,对比结果差异
更新与冲突同一事实出现矛盾答案查该实体的版本链,看是否有两条都标为当前
遗忘与压缩上下文总是超预算,或压缩后丢数字对比 expand() 还原的原文与压缩前是否逐字节一致
审计与追溯无法回答「这条从哪来」跑 verify_integrity() 与指针链回溯
注入与预算模型答非所问,或忽略了明显相关的信息打印最终拼进提示词的文本,看关键记忆是否真的在里面

最常见的误判:以为「召回不准」是检索算法的问题。实际上多数情况是写入阶段就没抽对——库里根本没有那条事实,检索再强也取不出来。排查顺序应该是:先确认库里有,再看检索能不能取到,最后才怀疑排序。

七、三个常见的技术误解

误解一:「上下文窗口够大就不需要记忆」

窗口大只解决单次对话的长度问题,解决不了跨会话。而且窗口越大,检索噪声越大——把 100 万 token 全塞进去,模型对其中某一条的注意力反而下降。实测基准也印证这一点:BEAM 1M 的分数(68.5)明显低于 LongMemEval(96.2),说明长上下文下召回确实更难。

误解二:「记忆就是把聊天记录存起来」

原始聊天记录有两个问题:体积大、信噪比低。一句话里可能只有半句是事实,其余是寒暄。真正的记忆系统要在写入时做抽取——把「嗯嗯好的,对了我是南京人,你继续」变成「用户籍贯:南京」。存原文只是第一步。

误解三:「向量相似度高就等于相关」

向量相似度衡量的是语义接近,不是「能回答这个问题」。例如查询「我的订单到哪了」,与「订单系统用 PostgreSQL」的向量相似度可能很高,但后者完全不能回答问题。这就是为什么需要多路融合与相关性下限,而不是单靠向量。

八、常见问题

AI 记忆会不会把隐私存到云端?

取决于你选的实现。本地优先的引擎(如 Mnemosyne OS)默认把数据写在你自己磁盘上的 SQLite 文件里,核心零第三方依赖,不需要任何云账号。托管形态(Mnemosyne OS SaaS)则需要注册账号,数据在服务端,按用户独立命名空间隔离。

一条记忆能存多大?

实测中写入 2400 字符的文本时,引擎会按句子切成多条独立记忆(5 句 → 5 条)。这是刻意的:记忆的检索粒度是「一条事实」,不是「一篇文章」。需要存长文档时,更适合切片后作为多条记忆写入,或者干脆用 RAG。

能不能不用 Python?

引擎核心是 Python,同时提供 REST API(v1/v2/v3)与 MCP 协议接口。任何能发 HTTP 请求的语言都可以通过 API 使用;支持 MCP 的客户端(Claude Desktop、Cursor 等)可以直接接 MCP 服务器,不需要写代码。

零依赖是什么意思?

指核心包的 install_requires 是空列表——安装时不拉取任何第三方包。实测确认:mnemosyne-os 8.1.0.post1 的核心依赖为空,numpy / transformers / tiktoken 都是可选扩展。这意味着它能在没有编译器的机器、气隙环境、受限容器里安装并运行。

压缩比到底是多少?

实测结果:取决于原文长度与预算。一条 23 字符的记忆在 60 token 预算下压缩比为 1.0——它已经是最小形态,压不动。长文本在紧预算下才压得动。因此任何单一数字(如「32 倍」)都需要追问测试条件。这个细节在选购时值得深挖,因为它直接影响上下文预算规划。

记忆和微调有什么区别?

微调改的是模型权重,成本高、更新慢、不能针对单个用户;记忆是模型外的存储,实时写入、按用户隔离、可删除可审计。两者互补:微调注入领域知识,记忆承载用户事实。

九、下一步

如果你是第一次接触这个概念,建议按这个顺序推进:先在自己的机器上跑通一次写入与召回(十分钟内可完成),再决定要不要接真实嵌入模型,最后才考虑多用户与托管。

给 AI Agent 加记忆 →查看源码