周二,用户说"我喜欢公制单位"。周五,新会话里智能体报出了英里数。你查日志,周二的对话清清楚楚写着"好的,公制"。但周五的会话打开时,messages数组是空的,周二像没发生过。
这就是"智能体记忆"的真正含义,也是几乎总是被误诊的问题。团队把整段用户历史塞进系统提示词,成本飙升,延迟增加,智能体还是有一半时间抓不住重点——关键信息埋在30页对话的第8页。
解决方法是停止把记忆当成一回事。生产级智能体记忆有2层,混淆它们是bug。
2层记忆:episodic与semantic
Episodic记忆(情景记忆)是这场对话里10分钟前发生了什么。它是当前会话的窗口化对话记录,窗口满了之后变成运行摘要。智能体每轮都读它,知道2消息前说了什么。它持续写入,定期摘要,对话结束就丢弃——或者按会话ID保留,如果产品需要续接。
Semantic记忆(语义记忆)是你对这个用户的稳定认知:名字、偏好、历史订单、他们告诉你的明天仍然成立的事。智能体每轮查询它(或在会话开始时,取决于读取预算的权衡)。它很少写入,只有用户说了值得跨会话保留的事时才更新。冲突是正常的,用户改主意、否定之前的陈述,你需要能更新现有事实而非堆叠重复的写入路径。
它们的生命周期不同,读写路径也不同。下面是用Postgres加pgvector、约100行Python实现的分层方案。
表结构:对话缓冲与事实存储
2张表。Episodic是对话缓冲;semantic是带嵌入的事实存储。
先启用向量扩展:
create extension if not exists vector;
情景记忆表,记录每轮对话:
create table episodic_turn ( id bigserial primary key, session_id text not null, role text not null, content text not null, created_at timestamptz default now() );
create index on episodic_turn (session_id, id);
语义记忆表,存储用户事实与向量:
create table semantic_fact ( id bigserial primary key, user_id text not null, fact_text text not null, fact_embedding vector(1536), created_at timestamptz default now(), updated_at timestamptz default now() );
create index on semantic_fact using ivfflat (fact_embedding vector_cosine_ops);
2张表,2种查询模式。Episodic按会话ID顺序读取;semantic按用户ID做向量相似度搜索。
写入路径:什么时候记什么
情景记忆的写入很简单——每轮对话直接插入。读取时按会话ID取最近N条,或做滑动窗口摘要。
语义记忆的写入需要判断。不是每句话都值得存,只有提取出的"事实"才入库。这里用1个简单启发式:让智能体自己决定。
每次用户说完,先查当前会话的episodic缓冲,生成摘要,然后问模型:"用户是否表达了值得跨会话保留的偏好或信息?只输出事实陈述,没有则输出NONE。"
输出非NONE时,做向量嵌入,入库或更新。更新逻辑检查相似度阈值:新事实与现有事实的向量距离够近,就覆盖;够远,就新增。这处理用户改主意的情况。
读取路径也分离。每轮对话,系统并行做2件事:顺序读取episodic缓冲(快,确定性强),向量检索semantic存储(稍慢,召回相关背景)。合并后进入提示词。
参考实现:2个值得看的库
有2个维护中的库值得先读文档,再决定是自己写还是接入。
mem0走"bolt-on memory"路线,提供即插即用的语义记忆层,支持多后端存储,自带冲突解决和TTL机制。适合想快速验证产品假设的团队,文档清晰,集成约需15分钟。
langgraph-checkpoint更贴近episodic层,专注对话状态的持久化与恢复,支持断点续传、时间旅行调试。如果你的核心痛点是会话中断后恢复上下文,从这里开始。
2者都开源,都生产可用。选型取决于你的瓶颈在哪一层。
常见陷阱与修复
团队最常犯的3个错误:把episodic当semantic用(导致成本爆炸)、semantic写入太频繁(事实漂移)、更新不做冲突检测(同一偏好存10遍)。
修复方案对应:严格区分2层存储、写入前加过滤模型、更新时用向量相似度去重。100行Python的核心就是这3个判断点,其余都是 plumbing。
用户周五看到英里数,不是因为技术做不到,是因为架构把2层混成1层。分开它们,周二的信息会在semantic里等着,周五的会话打开时,向量检索第1毫秒就能召回。
热门跟贴