LLM 长期记忆层

llm-long-term-memory · SQLite + FTS5 · MIT

GitHub

面向 LLM Agent 的长期记忆基础设施

知道什么仍然有效,也知道什么时候该回原文

把对话压缩成结构化、带时间边界的事实。事实变化时关闭旧版本而不是堆叠;压缩丢掉细节时回到原始对话把它取回来。每一条记忆都能定位到来源会话、轮次和字符区间。

70.0%
未见测试集准确率
heldout100 · 冻结后单次运行
1,468
上下文 token 中位数
同一次运行 · 整段对话是 109,260
+20pp
由原文档案救回的部分
结构化记忆 50.0% → 最终 70.0%

三种能力,逐个演出来

下面这三个是内置示例,用来说明系统在做什么。想自己动手——写你自己的事实、看旧值被关闭、看检索拒绝了什么——去 实验台,那里跑的是真的引擎。

A
Alex
虚构人物
七段跨越三年的对话已经写入记忆。人物和对话都是为演示编造的,页面不连接任何服务,也不读取你的任何数据。

回答

用了哪些记忆,为什么

架构

对话 原文档案 事实抽取 时间性记忆 查询 记忆够回答吗? 否 → 回原文取证 是 → 回答

SQLite (WAL) + FTS5 · all-MiniLM-L6-v2 384d · FastAPI · MCP

评测

开发集 dev50 — 四种方案对照

每一个设计决定都是在这一组上做的:提示词和阈值照着它的失败案例调过,所以 72.0% 同时也在衡量这些选择对它的拟合程度。它不是未见证据。

冻结未见测试 heldout100

100 道没有参与过任何决策的题,在哈希冻结的系统上跑一次。刻意与上表分开——把调参集和未见集画进同一张图就等于毁掉协议。

最终准确率70.0%
其中:结构化记忆独立答对50.0%
其中:原文档案救回+20.0pp
上下文 token 中位数1,468
重复三次的区间70 – 73

报告 70.0% 而不是均值 71.3,是因为协议在重复实验存在之前就已经承诺只报第一次。基线从未在这 100 道上跑过,所以「结构化记忆追平朴素 RAG」目前只有 dev50 的证据。

它是一个系统,不是一个 notebook

REST API
摄取、检索、回答、原文检索、时间线、遗忘;每次读取都要 user_id,跨命名空间返回 404 而非 403。
MCP Server
stdio 与 streamable HTTP 两种传输,五个工具,与 REST 共用同一个 service 对象。
SQLite + FTS5
单文件、WAL、无外部服务依赖;结构化事实与原文轮次在同一个库里,原文由 BM25 索引。
本地嵌入
all-MiniLM-L6-v2,384 维,归一化后做精确内积;嵌入不出本机。
Docker
镜像不含数据集、模型、凭据或数据库;健康检查会在检索不可用时报 degraded 而不是假装健康。
560 tests
跨 ubuntu / windows / macos 三平台 CI,并把 EncodingWarning 当作错误,使编码缺陷无法悄悄回来。
可复现清单
实验冻结逐文件哈希源码、配置、数据与协议产物;改动其中任何一个都会让已完成的运行失去谱系而被拒绝。
可解释检索
检索同时返回命中与被排除的,并给出理由:superseded(不再成立)或 below_rank(仍成立但没进前列)。