Agent 长期持久化记忆搭建实操 - 内部知识库文档
一、引言
在Agent实际落地中,无状态设计是导致多轮交互质量下降的首要原因。用户重复提问、Agent遗忘先前指令、跨会话无法调用历史经验——这些问题本质上是记忆系统缺失所致。本文围绕记忆分层理论,以LangGraph为代码主线,讲解短期记忆与长期记忆的完整搭建流程,并引入Postgres数据库作为结构化持久化方案。
读者完成后将掌握:记忆系统的架构分层设计、短期记忆的上下文窗口管理与状态维护、长期记忆的向量化存储与语义检索,以及记忆数据的生命周期管理策略。
二、记忆分层模型:从短期到长期的架构设计
2.1 三层次记忆模型
Agent记忆系统的设计参考了认知科学中的记忆分层理论。实践中我们一般划分为三个层次:
短期记忆(Short-term Memory) 负责存储当前会话中的原始输入输出,通常是LLM上下文窗口内的历史消息。其特点是读写频繁、容量有限(受模型token上限约束),主要用于维持单次对话的连贯性。
工作记忆(Working Memory) 跟踪Agent正在执行的任务状态。例如用户要求“先查天气,再订酒店”,工作记忆会维护一个任务栈,记录当前执行到第几步、哪些子任务已完成。当Agent需要临时切换到子任务(如查天气时再查核酸政策)时,工作记忆保证能够恢复主任务。
长期记忆(Long-term Memory) 存储跨会话的重要知识,包括用户偏好、业务规则、历史对话关键摘要等。长期记忆的载体通常是外部存储系统(向量数据库、关系型数据库),需要支持持久化、高效检索和过期清理。
三个层次在Agent运行时的协作关系如下:Agent收到用户输入后,首先从长期记忆中检索相关上下文,与短期记忆拼接后送入LLM,同时工作记忆负责管理当前任务栈的执行流转。任何有价值的交互结果,经过重要性评估后回写入长期记忆。
2.2 长期记忆的企业级必要性
在企业Agent场景下,长期记忆不仅是功能增强,更是系统可用性的前提。以下为典型的跨场景需求:
- 用户偏好学习:用户A偏好“详细的技术文档”,用户B偏好“简洁的摘要说明”,长期记忆需记录这些偏好并在后续交互中自动应用。
- 知识复用:某部门在上月的客户沟通中已确认过特定的技术方案,下次交流时Agent应能够参考历史纪要,避免重复讨论。
- 上下文推理:用户在周一咨询“登录失败问题”,周二再问“那还需要更新证书吗”——Agent需从长期记忆中关联到前日的登录失败场景,才能给出正确建议。
没有长期记忆的Agent等同于每次对话都重新初始化的空壳模型,无法沉淀经验,也无法建立用户信任。
三、短期记忆实现:上下文窗口管理与状态维护
3.1 滑动窗口截断策略
短期记忆最基础的管理策略是滑动窗口——只保留最近N轮对话。假设业务要求Agent记住最近5轮用户输入和助手回复,则窗口大小为10条消息(5入5出)。超出范围的消息直接丢弃。
以下为基于LangGraph的BufferWindowMemory实现示例:
1 | |
注意:该方法简单高效,但面临两个局限:(1)如果某轮对话非常长(如用户粘贴了整份日志),窗口可能迅速被单一消息占满;(2)模型无法访问被丢弃的早期上下文,可能导致“遗忘”问题。
3.2 摘要压缩策略
为解决滑动窗口的“一刀切”问题,可以引入ConversationSummaryMemory——定期对早期对话进行摘要压缩,取代原始消息放入窗口。
1 | |
该方案在长对话中表现更稳定,但增加了LLM调用开销(每次保存都需要摘要)。实践中建议:仅在窗口触发截断时执行一次摘要,而非每轮都做。
3.3 状态管理的边界
短期记忆虽然能维持对话连贯性,但无法解决跨会话的“遗忘”问题。例如用户第二天回来问“我昨天说那个方案,你觉得怎么样?”,短期记忆已经清空,必须依赖长期记忆来提供前日讨论内容。这就是短期记忆的职责边界——仅限当前会话内,不应把跨会话知识放在短期记忆里管理。
四、长期记忆存储方案:向量数据库 + Postgres 融合设计
4.1 双载体存储架构
长期记忆需要同时支持两种检索模式:语义检索(模糊搜索“关于数据库优化的经验”)和结构化检索(精确查询“用户A的配置偏好”)。单一存储方案往往难以两全。实践中采用向量数据库(FAISS/Chroma)与关系型数据库(Postgres)融合的方案:
| 存储载体 | 适用场景 | 优势 | 劣势 |
|---|---|---|---|
| 向量数据库 | 语义相似度搜索 | 检索速度快,支持embedding | 结构化查询弱 |
| Postgres | 精确查询、事务管理、报表 | 强事务,ACID | 全文搜索不如向量检索 |
4.2 双写模型设计
当Agent抽取到一条待存储的记忆时,同时写入两个系统:
- 将记忆内容转换为向量(通过Embedding模型如text-embedding-ada-002),存入向量数据库的索引。
- 将记忆的原始文本、实体标签、时间戳、重要性评分等结构化字段写入Postgres表。
检索时,先通过向量数据库获取Top K相似记忆列表,再通过Postgres精准回查这些记忆的完整字段。这样可以兼顾检索速度与数据完整性。
Postgres核心表结构示例:
1 | |
工程提示:写入Postgres时应使用连接池(如psycopg2的ThreadedConnectionPool),避免每次存储都新建连接的开销。向量数据库写入建议使用异步API,不阻塞主流程。
五、记忆生命周期管理:重要性评估与自动清理
5.1 为什么需要生命周期管理
长期记忆不加节制地增长会导致两个问题:存储膨胀(增加成本)和检索噪声(大量无关记忆干扰LLM推理)。必须对记忆进行分级与过期清理。
5.2 基于LLM的重要性评估
使用LLM评估用户输入中的信息是否值得存入长期记忆。评估Prompt示例如下:
1 | |
根据评分设定TTL(Time To Live):
1 | |
注意:不要对所有消息都评估,只针对明显带有陈述性信息的内容(如“我住在北京”),避免不必要的LLM调用。
5.3 定时清理脚本
每天凌晨定时执行清理任务:
1 | |
策略思想:高价值记忆只延长不删除,低价值记忆到点即淘汰。同时保留一条审计日志记录删除操作,以便问题回溯。
六、给Agent添加长期记忆:LangGraph中的Memory模块实操
6.1 在Graph中嵌入Memory节点
LangGraph允许将记忆的写入和检索封装为独立的图节点,在Agent执行流转中自动触发。以下为典型设计:
1 | |
6.2 关键工程细节
检索时机:
retrieve_memory节点放在图执行的最前面,确保LLM在决策前已获取历史上下文。写入节点extract_memory放在图执行结束后,避免干扰当前轮逻辑。去重策略:同一用户对同一实体多次产生记忆时,应更新而非追加。Postgres中的
ON CONFLICT语句可用于实现upsert。错误处理:如果Postgres或向量数据库写入失败,不应导致整个Agent执行失败。在
extract_memory节点内捕获异常,使用graph.set_error_handler定义降级策略(如仅写入日志,继续执行)。
七、检索增强技巧:多模态检索与记忆融合策略
7.1 混合记忆输入
LLM的输入包含两部分记忆:当前会话的短期记忆(原始消息)和长期记忆检索结果。如何融合直接影响推理质量。推荐策略:
1 | |
在LangChain中可通过自定义Memory类实现:
1 | |
7.2 排序融合与重排序
当同时使用语义检索和关键词检索时,需要对结果进行融合排序。RRF(Reciprocal Rank Fusion)是轻量的融合方法:
1 | |
重排序:在融合后,使用一个轻量级模型(如cross-encoder)对Top 20结果重新打分排序,进一步压缩噪声。该步骤在延时敏感场景下可省略,在离线批量场景下推荐使用。
7.3 时间衰减因子
记忆的时效性也很重要。1年前的“用户偏好”与1天前的“用户偏好”可信度不同。在检索阶段加入时间衰减:
1 | |
对于业务规则类记忆,衰减因子通常设为1(不衰减);对于临时偏好的记忆,衰减可以更快。
八、踩坑记录与性能优化实践
8.1 常见问题清单
1. 记忆写入/读取瓶颈
现象:Agent每次执行都要先检索长期记忆,在高并发下Postgres查询延迟从1ms飙升至200ms,整条链路耗时翻倍。
原因:未使用连接池、未对记忆表做分区索引。
优化方案:
- 强制使用连接池(如
psycopg2.pool.ThreadedConnectionPool),最小连接数=并发数×2。 - 按
user_id做哈希分区,每个分区独立索引。
2. 向量维度过高导致检索延迟
现象:使用1536维的embedding模型,在100万条记录上检索耗时超过300ms,无法满足实时对话要求。
优化方案:
- 降维:将embedding从1536维压缩至256维(使用PCA或自编码器),牺牲少量精度换取5倍以上速度提升。
- 索引分片:使用IVF(Inverted File)索引,设置
nprobe=20(检索时仅搜索20个最相关的聚类中心)。
3. Postgres连接池过小
现象:Agent实例从5扩到20后,Postgres连接数仍然只有10,大量请求排队等待。
优化方案:动态扩展连接池,与Agent实例数成正比。上限不宜超过数据库可接受的连接数(通常500以内)。
8.2 性能优化实测数据
以下为内部压测数据(8核32G机器,10万条记忆,并发30):
| 优化措施 | 平均响应耗时 | 内存占用 | 说明 |
|---|---|---|---|
| 无优化(直接查全表) | 1200ms | 600MB | 不可接受 |
| 加索引+连接池 | 230ms | 650MB | 可接受 |
| 异步写入+缓存层 | 85ms | 700MB | 推荐方案 |
| 加缓存层+向量索引分片 | 45ms | 800MB | 高吞吐场景 |
缓存层使用Redis,存储最近1000条高频记忆,避免对Postgres的重复查询。写入时先写Redis(1ms),异步批量写Postgres(每5秒或积压20条写一次)。
九、总结与拓展方向
9.1 核心技术点回顾
本文完整覆盖了Agent长期持久化记忆的搭建流程,要点如下:
分层记忆架构:短期记忆(对话上下文)、工作记忆(任务状态栈)、长期记忆(知识库),三层各有职责与生命周期。
短期记忆窗口管理:滑动窗口截断与摘要压缩两种策略,根据业务场景选择或组合。
长期记忆多模态存储:向量数据库负责语义检索,Postgres负责结构化事务存储,双写保证数据完整性与检索效率。
生命周期管理:LLM评估重要性→设定TTL→定时清理策略,避免存储膨胀与检索噪声。
检索增强融合:短期+长期记忆混合输入,RRF排序融合,时间衰减因子提升相关度。
性能优化:异步写入、连接池、缓存层、索引分片,确保高并发下的响应稳定性。
9.2 落地建议
优先实现短期记忆:大多数Agent应用在短期内(单会话内)表现更好,短期记忆是基础,两周内可完成集成。
长期记忆逐步叠加:先从用户偏好、业务规则等结构化数据开始,再扩展至自由文本的记忆抽取。不要一次性上线所有功能。
监控记忆命中率:在日志中记录每次检索是否返回有效记忆,命中率低于30%说明检索策略或记忆填充策略需要优化。
预留扩展接口:后续可能接入多模态记忆(图像/音频),在存储设计时字段类型建议使用JSONB(Postgres)等可扩展格式。
9.3 拓展方向
- 多模态记忆:Agent不仅能记住文本,还能记住对话中的图片(如产品示意图)、音频(如客户语气),这对工业售后、设计审核等场景有实际价值。
- 基于记忆的主动推理:Agent在空闲时主动检索长期记忆,发现用户之前提到过的问题未解决,主动触发回访流程。
- 联邦记忆:多个Agent实例共享长期记忆库,但需要解决数据安全与冲突合并问题。
例如客服Agent A和客服Agent B遇到同一位客户,如何避免记忆矛盾。
9.4 参考资料
- LangGraph官方Memory文档:[链接待内部wiki补充]
- PostgreSQL AI扩展:pgvector、pg_later
- 向量数据库选型对比:FAISS vs Chroma vs Milvus 性能基准表
- LangChain Memory模块源码解析
文档撰写完毕,如有疑问或需要补充细节,欢迎联系本文作者或所在小组。
总结
通过本文的学习,相信你已经对「Agent长期记忆搭建」有了更深入的理解。建议结合实际项目多加练习。如有疑问,欢迎交流!