6616AI

006|Agent Memory 设计:让 Agent 有记性

Memory 让 Agent 不只是单次推理,而是能记住上下文、用户偏好和历史事实。短期记忆管一次对话,长期记忆管跨会话。

核心结论:Memory(读作:麦·莫·瑞)让 Agent 有"记性"。短期记忆管一次对话,长期记忆管跨会话。Buffer、Window、Summary、Vector、Entity 五种方式各有适用场景。Memory 和 RAG 不一样:一个记"聊过什么",一个查"事实是什么"。


一、为什么 Agent 需要 Memory

LLM 本质上是无状态的。每次调用它,都是一次独立的推理。它不会自动记住你上一轮说了什么。

但 Agent 是要连续做任务的:

用户:帮我查一下上个月广东的销售额。
Agent:好的,上个月广东销售额是 1200 万。
用户:那环比呢?
Agent:???(不知道你说的"那"指什么)

没有 Memory,Agent 就接不住上下文。


二、Memory 解决什么问题

问题Memory 的作用
多轮对话记住历史对话
用户偏好记住用户习惯和设定
任务状态记住任务执行到哪一步
知识积累记住从交互中学到的东西
个性化根据不同用户给出不同回答

三、短期记忆 vs 长期记忆

短期记忆(Short-term Memory / 肖特·特姆 麦·莫·瑞)

定义: 当前会话内的上下文,用完就可能丢。

特点:

  • 存在内存里
  • 会话结束就清空
  • 容量有限,受 Context Window(康·泰克斯特·温·道)限制
  • 访问速度快

例子:

用户:帮我查一下上个月广东的销售额。
Agent:1200 万。
用户:那环比呢?
Agent:根据刚才的结果,环比下降 15%。

这里的"刚才的结果"就是短期记忆。

长期记忆(Long-term Memory / 朗·特姆 麦·莫·瑞)

定义: 跨会话、跨任务保留的信息。

特点:

  • 存在数据库、向量库、文件里
  • 可以持久化
  • 容量大
  • 需要检索
  • 访问速度慢一些

例子:

用户:(昨天)我是做跨境电商的,以后分析都用跨境视角。
用户:(今天)帮我看看美国站的销售额。
Agent:好的,从美国站跨境视角分析,本月销售额...

这里的"做跨境电商"就是长期记忆。

对比表

维度短期记忆长期记忆
存储位置内存数据库 / 向量库
生命周期一次会话长期
容量
速度
检索方式直接读取需要检索
典型实现Context WindowRedis、Chroma、Postgres
面试考点上下文管理个性化、持久化

四、常见的 Memory 类型

1. Buffer Memory(巴·弗·麦·莫·瑞)

最简单粗暴:把所有历史对话原封不动塞进 prompt。

memory = [
    {"role": "user", "content": "查广东销售额"},
    {"role": "assistant", "content": "1200万"},
    {"role": "user", "content": "那环比呢"}
]

prompt = f"历史对话:{memory}

请回答:{最新问题}"

优点: 简单、信息完整

缺点: 上下文长了 token 爆炸,容易超过 Context Window,成本高

适合: 短对话、测试 demo


2. Window Memory(温·道·麦·莫·瑞)

只保留最近 N 轮对话。

memory = 最近5轮对话

prompt = f"历史对话(最近5轮):{memory}

请回答:{最新问题}"

优点: 控制上下文长度,实现简单

缺点: 会丢失更早信息,N 选不好关键信息会丢

适合: 多轮对话,对历史依赖不强的任务


3. Summary Memory(萨·莫·瑞·麦·莫·瑞)

让 LLM 把历史对话压缩成摘要。

# 原始对话
history = [
    {"role": "user", "content": "我叫张三,做跨境电商"},
    {"role": "assistant", "content": "好的,我记住了"},
    {"role": "user", "content": "查一下美国站销售额"},
    {"role": "assistant", "content": "100万"},
    ...
]

# 压缩成摘要
summary = LLM总结(history)
# 结果:"用户叫张三,做跨境电商,主要关注美国站销售额。"

prompt = f"历史摘要:{summary}

请回答:{最新问题}"

优点: 极大节省 token,保留关键信息

缺点: 摘要会丢失细节,多一步 LLM 调用增加延迟,摘要质量影响后续效果

适合: 长对话,需要记住核心事实的场景


4. Vector Memory(维克·托·麦·莫·瑞)

把历史对话转向量,存储到向量数据库,按需检索。

# 把每轮对话转成向量
for message in history:
    vector = embedding_model.encode(message)
    vector_db.add(vector, message)

# 提问时检索相关历史
relevant_messages = vector_db.query(最新问题, top_k=5)

prompt = f"相关历史:{relevant_messages}

请回答:{最新问题}"

优点: 只返回相关内容,可以处理大量历史,支持语义匹配

缺点: 检索质量决定效果,延迟更高,需要维护向量库

适合: 超长历史,只需要部分相关信息


5. Entity Memory(恩·梯·梯·麦·莫·瑞)

专门提取和记忆"实体"信息:用户名、身份、偏好、业务关键对象。

entities = {
    "用户名": "张三",
    "行业": "跨境电商",
    "关注站点": "美国站",
    "常用指标": "销售额、转化率"
}

prompt = f"已知用户信息:{entities}

请回答:{最新问题}"

优点: 结构化,检索快,不会丢失关键事实,适合做个性化

缺点: 需要抽取实体,实体关系复杂时难维护

适合: 用户画像、客户关系管理、长期个性化服务


五、Memory 类型对比表

Memory 类型读法核心思想优点缺点适合场景
Buffer Memory巴·弗·麦·莫·瑞保留全部对话完整token 多短对话
Window Memory温·道·麦·莫·瑞保留最近 N 轮简单丢失历史一般多轮对话
Summary Memory萨·莫·瑞·麦·莫·瑞摘要压缩省 token丢细节长对话
Vector Memory维克·托·麦·莫·瑞向量检索相关历史可处理大量历史检索质量决定效果超长历史
Entity Memory恩·梯·梯·麦·莫·瑞提取结构化实体快、稳定抽取逻辑复杂用户画像

六、Memory 在代码里怎么实现

简单版:Buffer + Window

class Memory:
    def __init__(self, max_turns=5):
        self.history = []
        self.max_turns = max_turns
    
    def add(self, role, content):
        self.history.append({"role": role, "content": content})
        # 只保留最近 N 轮
        if len(self.history) > self.max_turns * 2:
            self.history = self.history[-self.max_turns * 2:]
    
    def get(self):
        return self.history

高级版:短期 + 长期分离

class AgentMemory:
    def __init__(self):
        # 短期:当前会话上下文
        self.short_term = []
        # 长期:向量数据库
        self.long_term = VectorDB()
    
    def add(self, role, content):
        self.short_term.append({"role": role, "content": content})
        
        # 重要信息存入长期记忆
        if self.is_important(content):
            self.long_term.add(content)
    
    def get_context(self, question):
        # 1. 短期记忆直接拿
        short = self.short_term[-5:]
        
        # 2. 长期记忆检索相关
        long = self.long_term.query(question, top_k=3)
        
        return {
            "short_term": short,
            "long_term": long
        }

七、Memory 和 RAG 的区别

这是面试非常爱问的点。

维度MemoryRAG
数据来源用户历史交互知识库文档
目的让 Agent 记住"谁、聊过什么"让 Agent 有"事实依据"
存储内容对话、偏好、实体文档片段、schema
更新频率每次交互都可能更新相对固定,定期更新
检索方式直接读取 / 向量检索向量检索
典型问题"我昨天说过什么""这个指标怎么算"

一句话区别

Memory 是记住"你和我说过什么",RAG 是知道"这件事本身是什么"。


八、Memory 设计的常见坑

坑 1:上下文太长,token 爆炸

表现: 对话越跑越慢,成本越来越高,超过 Context Window 报错。

解决: Window Memory 限制轮数、Summary Memory 压缩、只保留必要字段。


坑 2:重要信息被窗口截断

表现: 用户说"我是 VIP",过几轮 Agent 忘了,服务降级。

解决: 把关键信息抽成 Entity Memory,单独存到长期记忆,每轮 prompt 都带上。


坑 3:长期记忆检索不准确

表现: 用户问"上次说的那个项目",检索出来的不是那次对话。

解决: 历史记录加 metadata(时间、主题),混合检索(向量 + 关键词),给记忆打分排序。


坑 4:记忆和隐私冲突

表现: 记住用户敏感信息,不同用户互相看到,合规问题。

解决: 按用户 ID 隔离记忆,敏感信息脱敏,设置记忆过期时间,用户可删除自己的记忆。


坑 5:记忆更新冲突

表现: 用户昨天说"我喜欢红色",今天说"我喜欢蓝色",Agent 不知道以哪个为准。

解决: 给记忆加时间戳,标记最新偏好,冲突时主动询问。


九、面试高频问题

Q1:Agent 的 Memory 怎么设计?

答: 我一般会分两层。短期记忆存在内存里,保留当前会话最近 N 轮,控制 Context Window。长期记忆用向量数据库或结构化数据库,存储用户画像、关键实体、历史摘要。提问时,短期直接读,长期按需检索。


Q2:Memory 和 RAG 有什么区别?

答: Memory 是 Agent 记住用户交互历史,RAG 是 Agent 从知识库检索事实。Memory 是"我们聊过什么",RAG 是"这件事本身是什么"。两者可以互补:RAG 提供知识,Memory 提供上下文。


Q3:多轮对话中怎么避免上下文爆炸?

答: 三种方法:1. 用 Window Memory 限制轮数;2. 用 Summary Memory 压缩摘要;3. 用 Vector Memory 只检索相关历史。实际生产中常组合使用。


Q4:长期记忆怎么更新?

答: 可以在每次交互后,用 LLM 提取关键信息,更新 Entity Memory 或 Summary。也可以定期批量总结。更新时要处理冲突,比如新偏好覆盖旧偏好,或者保留多个偏好。


Q5:Memory 怎么和 LangGraph 结合?

答: 在 LangGraph 里,State 的一部分就是 Memory。可以设计一个 memory 字段,每次节点执行前读取相关记忆,执行后把新信息写回记忆。记忆本身可以存在 State 里,也可以外接到 Redis、向量库。


十、Memory 在 LangGraph 里的位置

class AgentState(TypedDict):
    question: str
    # 短期记忆
    short_term_memory: list
    # 长期记忆检索结果
    long_term_memory: list
    # 最终输出
    final_output: str

def 记忆加载节点(state):
    question = state["question"]
    short = state["short_term_memory"][-5:]
    long = vector_db.query(question)
    return {
        "short_term_memory": short,
        "long_term_memory": long
    }

def 记忆保存节点(state):
    new_memory = state["final_output"]
    vector_db.add(new_memory)
    return {}

十一、一句话总结

Memory 让 Agent 有"记性"。短期记忆管一次对话,长期记忆管跨会话。Buffer、Window、Summary、Vector、Entity 五种方式各有适用场景。Memory 和 RAG 不一样:一个记"聊过什么",一个查"事实是什么"。


下一步可以读

  • 007|Agent 面试高频问题串讲(已更新)
  • 008|Agent 项目工程化:代码组织、测试、部署(待更新)