#0125 纯文本记忆撑不住了,我给 AI Agent 造了个记忆引擎

type
Post
status
Published
date
Feb 20, 2026
slug
30da745569bb815db0a1db7ac45d05e7
summary
你的 AI Agent 系统有记忆吗? 不是那种"把聊天记录塞进 context window"的记忆,是真正能搜索、能分级、能自动遗忘的记忆。
tags
思考
工具
金钱
category
加密货币
icon
password

纯文本记忆撑不住了,我给 AI Agent 造了个记忆引擎

你的 AI Agent 系统有记忆吗?
不是那种"把聊天记录塞进 context window"的记忆,是真正能搜索、能分级、能自动遗忘的记忆。
如果你跟我一样,给自己搭了一个 AI 自动化系统,跑着几十个定时任务、多个 Agent 协作处理日常事务——你迟早会撞上同一堵墙:纯文本记忆,根本不够用。

一个 Markdown 文件能撑多久?

最开始的方案很朴素:一个 MEMORY.md 文件,Agent 每次启动时全量加载,需要记住什么就往里追加。
听起来合理,用起来灾难。
行数会爆。 记忆越积越多,几百行之后,每次启动都要吃掉大量 token。你以为只是"读个文件",实际上每条记忆都在消耗你的 context window——那可是真金白银。
搜索靠 grep。 想找"上次讨论过的那个架构决策"?祝你好运。关键词搜索在记忆场景下约等于没有搜索。你记得的关键词和当初写下来的关键词,大概率不是同一个。
手动维护是噩梦。 过期的记忆谁来删?重复的记忆谁来合并?矛盾的记忆谁来裁决?答案是——你自己,手动,每隔几天就得花时间整理一次。
全量加载太蠢了。 Agent 今天要处理财务相关的任务,但它被迫加载了所有记忆,包括三个月前某次调试的日志、某个已经废弃的配置细节。这不是记忆,这是信息轰炸。
撞墙之后我开始认真想这件事:AI Agent 的记忆,应该怎么做?

市面上的方案,我都看了一遍

在动手造轮子之前,我花了不少时间调研现有方案。
Mem0 — 专门做 AI 记忆的开源项目,功能不错,但它是 Python 生态。我的系统是 Node.js 技术栈,引入一个 Python 服务意味着额外的进程管理、部署复杂度、跨语言通信。为了一个记忆模块把整个运维复杂度拉高一个量级,不值。
Letta(原 MemGPT) — 思路很有意思,把记忆管理融入 Agent 的推理过程。但它本质上是一个完整的 Agent 框架。我已经有自己的 Agent 架构了,再塞一个框架进来,两套系统打架,谁听谁的?
Pinecone / Weaviate / Qdrant — 专业向量数据库,性能没话说。但它们要么是 SaaS(数据上云,我不想),要么需要跑一个独立服务(又多一个进程要维护)。我搭这套系统的核心原则之一就是本地优先——数据在我自己的机器上,不依赖外部服务的可用性。
所有方案看完,结论很明确:没有一个正好适合。
要么生态不匹配,要么太重,要么违反本地优先。那就自己造。

最终架构:SQLite + 向量嵌入

选型的逻辑其实很简单:
存储层用 SQLite。 零依赖、单文件、本地存储、读写性能对记忆场景绰绰有余。不用装数据库、不用管端口、不用担心连接池。一个 .db 文件搞定一切。备份?cp 一下就行。
向量嵌入用 Voyage AI。 把每条记忆转成向量存进 SQLite,搜索时算余弦相似度。Voyage AI 是 API 调用,不需要本地跑模型,一次嵌入请求几毫秒,成本几乎可以忽略。
为什么不直接在本地跑嵌入模型?因为够用就行。本地跑模型意味着 GPU 资源占用、模型更新维护,收益和复杂度不成正比。一个轻量 API 调用,把复杂度推到外面去,本地只管存和查。
整体架构就是这样——存储完全本地,计算按需外调。既满足本地优先,又不用自己维护嵌入模型。

记忆不是平等的:P0 / P1 / P2 分级

这是整个设计里我觉得最关键的一个决策。
不是所有记忆都一样重要。"用户的核心偏好"和"上周二临时查了某个 API 文档",这两条记忆的生命周期、重要性、被召回的频率,完全不同。
所以我给记忆分了三个等级:
P0 — 核心记忆,不会过期。 这是"人格"级别的东西。用户的技术栈偏好、写作风格、沟通习惯、长期目标。一旦写入,除非用户明确要求修改,否则永远存在。Agent 的个性和一致性,全靠这层记忆撑着。
P1 — 阶段性记忆,90 天自动淘汰。 当前在做的项目、近期的技术决策、阶段性的工作方式。它们很重要,但有时效性。三个月前的项目上下文,大概率已经不需要了。
P2 — 临时记忆,30 天自动淘汰。 一次性的调试记录、临时的配置变更、偶发的问题处理。这类记忆如果不自动清理,一个月后你的记忆库就会被噪音淹没。
自动淘汰听起来简单,但它解决了纯文本方案最大的痛点——你再也不用手动清理过期记忆了。 系统自己会做。

语义搜索到底有多大差别?

说个实际例子。
假设记忆库里有这么一条:"系统在高并发场景下偶现 OOM,后来通过限制 worker 数量解决。"
关键词搜索 "内存溢出" —— 搜不到。因为原文写的是 "OOM",不是 "内存溢出"。
语义搜索 "内存溢出" —— 直接命中。因为向量嵌入理解 "OOM" 和 "内存溢出" 是同一个意思。
再来一个:记忆库里有 "部署新版本后 CPU 占用飙升到 95%,回滚后恢复正常。"
关键词搜索 "性能问题" —— 搜不到。
语义搜索 "性能问题" —— 命中,而且相似度评分很高。
这就是语义搜索和关键词搜索的本质区别。关键词搜索要求你的搜索词和记忆原文高度匹配,语义搜索只要求意思对就行。
对 AI Agent 来说,这个差别是致命的。Agent 在执行任务时检索相关记忆,它用的搜索词来自当前对话上下文,和当初记忆被写入时的措辞几乎不可能一模一样。关键词搜索在这个场景下,漏召回率高得离谱。

三个组件,各司其职

整个记忆引擎拆成三个模块:

Engine — 增删改查 + 语义搜索

核心模块。提供记忆的创建、读取、更新、删除,以及基于向量的语义搜索。每条记忆存储时自动生成嵌入向量,搜索时计算余弦相似度,返回最相关的 Top-K 结果。
💡 一个实用的设计细节: 搜索结果不只返回记忆内容,还返回相似度评分。Agent 可以根据评分决定这条记忆是否值得加载到 context 里。评分低于阈值的直接丢弃,避免噪音干扰。

Consolidate — 每晚整理

这是记忆引擎的"大脑清理"机制,每天晚上定时跑一次,做三件事:
去重。 语义相近的记忆合并成一条。比如你在不同时间记录了 "项目 A 用 TypeScript" 和 "项目 A 的技术栈是 TS",consolidate 会把它们合成一条。
降级。 长期未被访问的记忆自动降级。一个 P1 记忆如果三个月没被召回过,说明它已经不重要了,降成 P2。P2 记忆超过 30 天直接清理掉。
矛盾检测。 新记忆如果和已有的 P0 记忆矛盾,不会悄悄覆盖——它会被标记出来,生成一份矛盾报告等待人工裁决。P0 是核心记忆,不能随便被改,这是系统一致性的底线。
💡 为什么矛盾检测这么重要? 想象一下,某次对话中 Agent 误解了用户意图,写入了一条和核心偏好矛盾的记忆。如果直接覆盖,Agent 的行为就会突然变得不一致,而且你很难排查原因——因为旧记忆已经没了。矛盾检测相当于给 P0 记忆加了一道"写保护"。

Migrate — 旧格式迁移

从纯文本 MEMORY.md 迁移到新引擎的一次性工具。解析旧文件里的每条记忆,推断优先级,生成向量嵌入,写入 SQLite。
实际迁移效果:67 条记忆从旧格式平滑迁移,零数据丢失。迁移完成后旧文件保留备份,新引擎无缝接管。
没有什么惊心动魄的迁移故事——设计好了就是这么平淡。这恰恰说明方案靠谱。

实际跑起来是什么感觉?

用了一段时间之后,最明显的变化有三个:
Token 消耗断崖式下降。 不再全量加载所有记忆,而是根据当前任务语义搜索最相关的几条。从"每次启动吃掉几千 token"变成"按需检索,平均几百 token"。
Agent 的表现更一致了。 因为 P0 记忆不会被意外覆盖或丢失,Agent 的核心行为模式稳定了很多。不会再出现"昨天还好好的,今天突然变了"的情况。
完全不用手动维护了。 过期清理、去重合并、矛盾检测,全部自动化。我已经好几周没碰过记忆相关的东西了。

你要不要也搞一个?

如果你的 AI Agent 系统还在用纯文本做记忆,我的建议是——现在就开始考虑升级。
不一定要照搬我的方案。SQLite + 向量嵌入只是一种选择,适合本地优先、不想引入重依赖的场景。如果你的系统已经跑在云上,用 Pinecone 之类的向量数据库可能更省事。如果你是 Python 技术栈,Mem0 也值得一试。
但不管选什么方案,有几个设计原则是通用的:
记忆必须分级。 不分级的记忆库,要么全保留导致噪音爆炸,要么手动清理累死自己。
语义搜索是刚需。 关键词搜索在记忆场景下的召回率太低,不是"nice to have",是"must have"。
自动淘汰不能少。 记忆如果只增不减,三个月后你会后悔。
核心记忆要有写保护。 随便什么对话都能覆盖 Agent 的核心设定?那你的 Agent 迟早会精神分裂。
说到底,AI Agent 的记忆系统不是什么高深技术。SQLite 够了,向量嵌入 API 够了,几百行代码够了。难的不是实现,是想清楚:什么该记住,什么该忘掉,什么绝对不能改。
这不就是记忆的本质吗?
Loading...

© xiyu 2013-2026