71-Agent记忆系统-短期记忆-长期记忆-向量知识库三层架构

文章目录

  • 【71.Python+AI】Agent记忆系统:短期记忆、长期记忆与外部知识库的三层架构
    • 导入语
    • [1 ~> 三层记忆架构总览](#1 ~> 三层记忆架构总览)
      • [1.1 三层分工对照](#1.1 三层分工对照)
    • [2 ~> 短期记忆:对话历史的管理](#2 ~> 短期记忆:对话历史的管理)
      • [2.1 核心矛盾:窗口有限,对话无限](#2.1 核心矛盾:窗口有限,对话无限)
      • [2.2 实现:窗口+摘要混合](#2.2 实现:窗口+摘要混合)
    • [3 ~> 长期记忆:用户画像的持久化](#3 ~> 长期记忆:用户画像的持久化)
      • [3.1 从对话中提炼"关于用户的事实"](#3.1 从对话中提炼"关于用户的事实")
      • [3.2 画像的使用时机](#3.2 画像的使用时机)
    • [4 ~> 外部知识库:经验库的沉淀](#4 ~> 外部知识库:经验库的沉淀)
      • [4.1 与RAG的区别](#4.1 与RAG的区别)
      • [4.2 写入时机的把关](#4.2 写入时机的把关)
    • [5 ~> 三层记忆的读写时机总表](#5 ~> 三层记忆的读写时机总表)
    • [思考 && 总结](#思考 && 总结)
    • 结尾

【71.Python+AI】Agent记忆系统:短期记忆、长期记忆与外部知识库的三层架构

📖 文章简介: 本文系统讲解Agent记忆系统的三层架构设计:短期记忆(对话历史的Token预算管理)、长期记忆(用户画像与偏好的跨会话积累)和外部知识库(向量数据库中沉淀的"经验库")。文章拆解每层的存储介质、读写时机和淘汰策略------短期记忆用滑动窗口+摘要压缩、长期记忆用结构化Profile持久化、经验库用向量检索按需召回,并给出一个三层记忆整合的Python实现骨架。配以Mermaid架构图展示记忆读写时机与数据流向,适合正在开发多轮对话Agent、被"聊着聊着就忘了"问题困扰的开发者。


🎬 个人主页: 源码骑士

专栏传送门: 《Android开发基础》《python基础课程》

⭐️热衷从源码视角拆解技术底层原理,将复杂架构讲得通俗易懂


🎬 源码骑士的简介:

5年Android Framework系统开发经验,曾主导多项系统级性能优化专项

技术栈覆盖Android系统全链路(Binder/Handler/AMS/WMS/启动流程)及Java后端全家桶(Spring + MyBatis + Redis + Oracle)

累计产出原创技术文章100+篇,文章以流程图为特色,被读者评价为"看一篇胜过啃一周源码"


导入语

你跟AI助手聊了半小时,它还记得你第一句说的"我对海鲜过敏"吗?下周再打开它,它还能叫出你的名字吗?

如果两个问题的答案都是"不能",那你的Agent就没有真正的记忆系统------它只是一个"金鱼脑":所有的上下文都活在当前的对话窗口里,窗口满了就丢,会话结束就清零。

真正可用的Agent需要三层记忆:对话内记住说过什么、跨会话记住你是谁、永久记住它积累的经验。 这篇文章就把这三层怎么设计、怎么配合讲清楚。


1 ~> 三层记忆架构总览

#mermaid-svg-BsSjcVnUkZF2aB1m{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BsSjcVnUkZF2aB1m .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BsSjcVnUkZF2aB1m .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BsSjcVnUkZF2aB1m .error-icon{fill:#552222;}#mermaid-svg-BsSjcVnUkZF2aB1m .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BsSjcVnUkZF2aB1m .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BsSjcVnUkZF2aB1m .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BsSjcVnUkZF2aB1m .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BsSjcVnUkZF2aB1m .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BsSjcVnUkZF2aB1m .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BsSjcVnUkZF2aB1m .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BsSjcVnUkZF2aB1m .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BsSjcVnUkZF2aB1m .marker.cross{stroke:#333333;}#mermaid-svg-BsSjcVnUkZF2aB1m svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BsSjcVnUkZF2aB1m p{margin:0;}#mermaid-svg-BsSjcVnUkZF2aB1m .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BsSjcVnUkZF2aB1m .cluster-label text{fill:#333;}#mermaid-svg-BsSjcVnUkZF2aB1m .cluster-label span{color:#333;}#mermaid-svg-BsSjcVnUkZF2aB1m .cluster-label span p{background-color:transparent;}#mermaid-svg-BsSjcVnUkZF2aB1m .label text,#mermaid-svg-BsSjcVnUkZF2aB1m span{fill:#333;color:#333;}#mermaid-svg-BsSjcVnUkZF2aB1m .node rect,#mermaid-svg-BsSjcVnUkZF2aB1m .node circle,#mermaid-svg-BsSjcVnUkZF2aB1m .node ellipse,#mermaid-svg-BsSjcVnUkZF2aB1m .node polygon,#mermaid-svg-BsSjcVnUkZF2aB1m .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BsSjcVnUkZF2aB1m .rough-node .label text,#mermaid-svg-BsSjcVnUkZF2aB1m .node .label text,#mermaid-svg-BsSjcVnUkZF2aB1m .image-shape .label,#mermaid-svg-BsSjcVnUkZF2aB1m .icon-shape .label{text-anchor:middle;}#mermaid-svg-BsSjcVnUkZF2aB1m .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BsSjcVnUkZF2aB1m .rough-node .label,#mermaid-svg-BsSjcVnUkZF2aB1m .node .label,#mermaid-svg-BsSjcVnUkZF2aB1m .image-shape .label,#mermaid-svg-BsSjcVnUkZF2aB1m .icon-shape .label{text-align:center;}#mermaid-svg-BsSjcVnUkZF2aB1m .node.clickable{cursor:pointer;}#mermaid-svg-BsSjcVnUkZF2aB1m .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BsSjcVnUkZF2aB1m .arrowheadPath{fill:#333333;}#mermaid-svg-BsSjcVnUkZF2aB1m .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BsSjcVnUkZF2aB1m .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BsSjcVnUkZF2aB1m .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BsSjcVnUkZF2aB1m .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BsSjcVnUkZF2aB1m .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BsSjcVnUkZF2aB1m .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BsSjcVnUkZF2aB1m .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BsSjcVnUkZF2aB1m .cluster text{fill:#333;}#mermaid-svg-BsSjcVnUkZF2aB1m .cluster span{color:#333;}#mermaid-svg-BsSjcVnUkZF2aB1m div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BsSjcVnUkZF2aB1m .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BsSjcVnUkZF2aB1m rect.text{fill:none;stroke-width:0;}#mermaid-svg-BsSjcVnUkZF2aB1m .icon-shape,#mermaid-svg-BsSjcVnUkZF2aB1m .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BsSjcVnUkZF2aB1m .icon-shape p,#mermaid-svg-BsSjcVnUkZF2aB1m .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BsSjcVnUkZF2aB1m .icon-shape .label rect,#mermaid-svg-BsSjcVnUkZF2aB1m .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BsSjcVnUkZF2aB1m .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BsSjcVnUkZF2aB1m .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BsSjcVnUkZF2aB1m :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户输入
记忆读取层
短期记忆

对话历史窗口
长期记忆

用户画像 Profile
外部知识库

向量经验库
LLM 推理
Agent 响应
记忆写入层
追加对话历史
更新用户画像
沉淀有价值的经验

1.1 三层分工对照

层级 存什么 存活周期 存储介质 类比
短期记忆 当前对话的上下文 单次会话 内存/Redis 人类的"工作记忆"
长期记忆 用户偏好、习惯、画像 永久 数据库(结构化) 你对老朋友的了解
外部知识库 任务经验、领域知识 永久 向量数据库 笔记本和资料库

2 ~> 短期记忆:对话历史的管理

2.1 核心矛盾:窗口有限,对话无限

LLM的上下文窗口是硬约束(比如128K tokens)。对话一长,必须做取舍:

策略 做法 缺点
滑动窗口 只保留最近N轮 早期关键信息被丢弃
摘要压缩 老对话交给LLM总结成摘要 摘要本身消耗Token和调用次数
窗口+摘要 最近N轮原文 + 更早的摘要 实现稍复杂,但效果最好(推荐)

2.2 实现:窗口+摘要混合

python 复制代码
class ShortTermMemory:
    def __init__(self, window_size=10, llm=None):
        self.window_size = window_size
        self.llm = llm
        self.recent = []      # 最近N轮原文
        self.summary = ""     # 更早历史的压缩摘要
    
    def add_turn(self, user_msg, ai_msg):
        self.recent.append({"user": user_msg, "assistant": ai_msg})
        if len(self.recent) > self.window_size:
            # 挤出的最早一轮,合并进摘要
            overflow = self.recent.pop(0)
            self.summary = self.llm.invoke(
                f"把这段对话合并进现有摘要,保持关键信息:\n"
                f"现有摘要:{self.summary}\n新增对话:{overflow}"
            ).content
    
    def get_context(self):
        return f"历史摘要:{self.summary}\n最近对话:{self.recent}"

3 ~> 长期记忆:用户画像的持久化

3.1 从对话中提炼"关于用户的事实"

每轮对话结束后,让LLM提取值得长期记住的信息:

python 复制代码
EXTRACT_PROMPT = """从以下对话中提取关于用户的持久化事实(偏好/身份/习惯),
以JSON列表返回,没有则返回[]。

已有画像:{existing_profile}
新对话:{conversation}

只返回新增的、不重复的事实,如:
["用户对海鲜过敏", "用户是Python后端开发", "用户偏好简洁的回答"]"""


class LongTermMemory:
    def __init__(self, db_path="profiles.db"):
        self.db = sqlite3.connect(db_path)
    
    def update_profile(self, user_id, new_facts):
        """增量合并新事实到用户画像"""
        profile = self.load_profile(user_id)
        for fact in new_facts:
            if fact not in profile["facts"]:
                profile["facts"].append(fact)
        self.save_profile(user_id, profile)

3.2 画像的使用时机

画像不是每轮都全部注入------而是在生成回复前,作为System Prompt的一部分:

python 复制代码
system_prompt = f"""你是用户的私人助手。
已知用户信息:{profile['facts']}
请在回答时考虑这些背景,但不要主动复述。"""

4 ~> 外部知识库:经验库的沉淀

4.1 与RAG的区别

普通RAG的知识是"别人写的文档",经验库的知识是**"Agent自己干过的事"**:

python 复制代码
class ExperienceMemory:
    def __init__(self, vector_store):
        self.store = vector_store
    
    def save_experience(self, task, solution, success):
        """把一次成功任务的解法沉淀进经验库"""
        if success:
            self.store.add_texts([f"任务:{task}\n解法:{solution}"])
    
    def recall(self, new_task, top_k=3):
        """遇到相似任务时召回历史经验"""
        return self.store.similarity_search(new_task, k=top_k)


# 使用
exp = ExperienceMemory(chroma_store)

# 执行新任务前,先查经验
similar = exp.recall("批量处理1000条客服对话并分类")
if similar:
    prompt = f"参考历史经验:{similar}\n\n新任务:..."

4.2 写入时机的把关

经验库最大的坑是垃圾进垃圾出------失败的尝试、错误的结论如果被沉淀,会污染后续召回。两条原则:

  1. 只有用户确认满意的结果才入库(用户给了正反馈才save)
  2. 入库前让LLM做一次泛化(把具体的"1000条客服对话"抽象为"大批量文本分类任务")

5 ~> 三层记忆的读写时机总表

时机 短期记忆 长期记忆 经验库
收到新输入时 读取全文 读取画像 相似任务召回
生成回复时 注入上下文 注入System Prompt 注入参考经验
每轮对话后 追加+压缩 提炼新事实 不写入
任务完成被认可时 --- --- 沉淀成功经验

思考 && 总结

  1. 记忆不是单一概念,而是三种不同生命周期的系统: 短期管"这次对话"、长期管"这个用户"、经验库管"这个Agent的成长"。
  2. 短期记忆的最优解是窗口+摘要: 单纯滑动窗口会丢关键信息,纯摘要又会丢失细节,混合策略是工程上的最佳平衡。
  3. 长期记忆的关键是"增量提炼"而非"全文存储": 把对话原文全存下来既浪费又难用,提炼成事实列表才有价值。
  4. 经验库要严格把关写入质量: 宁缺毋滥------一条错误的经验,会污染之后无数次相似任务的召回。

没有记忆系统的Agent只是聊天机器人,有三层记忆的Agent才开始像一个"越用越懂你的助手"。


结尾

各位小伙伴,本文的内容到这里就全部结束了,源码骑士在这里再次感谢您的阅读!

源码骑士 --- Android Framework & 全栈开发

👀 关注:跟博主一起从源码视角深耕底层原理,见证每一次成长

❤️ 点赞:让优质内容被更多人看见,让知识传递更有力量

收藏:把核心知识点存好,在需要时随时查、随时用

💬 评论:分享你的经验或疑问,评论区一起交流避坑

🔄 一键四连:不要忘记给博主"一键四连"哦!

🗡️ 寄语:技术之路难免有困惑,但同行的人会让前进更有方向

结语:人类靠记忆建立信任,Agent也一样。把三层记忆搭好,你的Agent就从"每次见面都重新认识"进化成了"老朋友"。不要忘记给博主"一键四连"哦!

相关推荐
卷无止境1 小时前
Python 的 exec 与 eval :动态代码执行的能力、风险与工程实践
后端·python
user-猴子1 小时前
从零构建 2048 游戏,解析“Python-Use”范式的完整闭环
开发语言·python·游戏
后端优选官1 小时前
上海Agent开发公司:企业级智能体软件的技术架构与落地评估
数据库·人工智能·架构·软件开发·开发经验·上海
郝学胜_神的一滴1 小时前
Python 高级编程 025:二分利器bisect模块:优雅维系有序序列,极致优化检索性能
python·pycharm
极光技术熊1 小时前
AI应用开发中的流式输出:从协议原理到工程实战的完整指南
后端·架构
小帽子_1231 小时前
PCS 电池双向充放电控制策略与均衡配合方案
架构
行者全栈架构师1 小时前
混元 Hy3 Agent 实战:季度报告 3 小时变 40 分钟
算法·架构·代码规范
ICT系统集成阿祥1 小时前
公司搬迁同网段并行割接方案|新旧场地同时办公,不用改终端 IP
网络·架构·迁移·割接
小陈工1 小时前
第8篇:Flask轻量级框架与扩展生态深度解析(下)
后端·python·面试