LangChain Agent 的 Memory(记忆)机制 是实现上下文感知、长期交互、个性化服务的核心能力。它不仅记录历史对话,还能通过工作记忆折叠(Working Memory Folding)、会话档案化(Session Archiving)、记忆演化(Memory Evolution) 等高级策略,让 Agent 从“健忘的聊天机器人”升级为“有记忆、能反思、会成长”的智能体。

下面我将从 原理、架构、代码实现、最佳实践 四个维度,深入讲解 LangChain 中的记忆系统。


一、为什么需要 Memory?

❌ 无记忆 Agent 的问题:

  • 用户说:“帮我订杨国福麻辣烫”,Agent 问:“要什么口味?”
  • 用户答:“少辣,加雪碧”
  • 下一句用户说:“再加一份米饭” → Agent 完全忘记前面在点餐

✅ 有记忆 Agent 的优势:

  • 理解上下文(“再加” = 在原订单上追加)
  • 避免重复提问
  • 支持多轮复杂任务(如规划旅行、写周报)

二、LangChain Memory 的三层架构

graph LR
    A[短期:Working Memory<br>(当前会话上下文)] -->|折叠/摘要| B[中期:Session Archive<br>(单次会话完整记录)]
    B -->|提炼/索引| C[长期:Memory Store<br>(跨会话知识库)]
层级 名称 作用 生命周期
L1 Working Memory 当前对话的即时上下文 单次 invoke()
L2 Conversation Buffer / Summary 整个会话的历史 单次会话(session)
L3 VectorStore Memory / Entity Memory 跨会话的长期记忆 永久存储

三、核心概念详解

1. 工作记忆折叠(Working Memory Folding)

🎯 目标:

在有限上下文窗口(如 LLM 的 128K token)内,动态压缩历史对话,保留关键信息,丢弃冗余细节。

🔧 实现方式:
  • 滑动窗口:只保留最近 N 轮对话
  • 摘要压缩:用 LLM 将多轮对话压缩成一段摘要
  • 关键信息提取:只保留实体、决策、状态变更
✅ 适用场景:
  • 长时间客服对话
  • 复杂任务分解(如写论文)

2. 会话档案化(Session Archiving)

🎯 目标:

一次完整会话结构化存储,用于:

  • 审计追踪
  • 用户行为分析
  • 后续会话冷启动
📁 存储内容:
{
  "session_id": "sess_20240320_abc123",
  "user_id": "user_789",
  "start_time": "2024-03-20T19:00:00Z",
  "end_time": "2024-03-20T19:15:00Z",
  "turns": [
    {"role": "user", "content": "订麻辣烫"},
    {"role": "agent", "content": "要什么口味?", "tool_calls": []},
    {"role": "user", "content": "少辣,加雪碧"},
    {"role": "agent", "content": "已加雪碧", "state": {"order": {...}}}
  ],
  "final_state": {"order_items": ["麻辣烫(微辣)", "雪碧"]}
}

3. 记忆演化(Memory Evolution)

🎯 目标:

让记忆随时间更新、修正、泛化,而非静态存储。

🔄 三种演化机制:
类型 说明 示例
覆盖更新 新信息覆盖旧信息 用户改地址:“我家搬到朝阳区了” → 更新地址
冲突检测 发现矛盾时主动澄清 “你上周说喜欢微辣,今天要重辣?”
知识提炼 从多次交互中抽象偏好 “用户总在周五点麻辣烫” → 周五主动推荐

四、LangChain 内置 Memory 类型对比

Memory 类型 原理 优点 缺点 适用场景
ConversationBufferMemory 存所有历史消息 简单、完整 占 token 多 短对话
ConversationSummaryMemory 用 LLM 生成摘要 节省 token 可能丢失细节 长对话
ConversationBufferWindowMemory 只存最近 K 轮 轻量 忘记早期信息 中等长度任务
VectorStoreRetrieverMemory 向量检索相关历史 跨会话、精准召回 需嵌入模型 个性化服务
EntityMemory 提取并跟踪实体状态 结构化、可更新 实现复杂 多轮状态管理

推荐组合
VectorStoreRetrieverMemory(长期) + ConversationSummaryMemory(短期)


五、代码实现:三层记忆系统

步骤 1:安装依赖

pip install langchain langchain-openai langchain-community faiss-cpu

步骤 2:实现工作记忆折叠(摘要压缩)

from langchain.memory import ConversationSummaryMemory
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)

# 自动将历史对话压缩成摘要
summary_memory = ConversationSummaryMemory(
    llm=llm,
    memory_key="history",
    return_messages=True
)

# 使用示例
summary_memory.save_context(
    {"input": "我想订杨国福麻辣烫"},
    {"output": "好的,请问要什么口味?"}
)
summary_memory.save_context(
    {"input": "少辣,加一瓶雪碧"},
    {"output": "已为您添加雪碧,总价31元"}
)

print(summary_memory.load_memory_variables({}))
# 输出: {'history': [SystemMessage(content='The human wants to order Yang Guofu spicy hotpot with mild spice and a Sprite, totaling 31 yuan.')]}

💡 原理:每次新对话后,调用 LLM 将 (旧摘要 + 新对话) 压缩成新摘要。


步骤 3:实现长期记忆(向量检索)

from langchain.memory import VectorStoreRetrieverMemory
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings

# 初始化向量库
embedding = OpenAIEmbeddings()
vectorstore = FAISS.from_texts([""], embedding)  # 初始空库
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

# 创建记忆
long_term_memory = VectorStoreRetrieverMemory(
    retriever=retriever,
    memory_key="long_term_info",
    input_key="input"  # 用于检索的字段
)

# 添加记忆(通常在会话结束时)
long_term_memory.save_context(
    {"input": "用户偏好"},
    {"output": "喜欢杨国福麻辣烫,口味微辣,常加雪碧,住址:北京市海淀区"}
)

# 在新会话中自动检索
result = long_term_memory.load_memory_variables({"input": "订麻辣烫"})
print(result)
# 输出: {'long_term_info': '喜欢杨国福麻辣烫,口味微辣...'}

🔍 检索机制
用户新输入 → 嵌入向量 → 检索最相关的 3 条历史记忆 → 注入 prompt


步骤 4:组合记忆到 Agent

from langchain.agents import create_openai_functions_agent, AgentExecutor
from langchain import hub

# 合并短期 + 长期记忆
from langchain.memory import CombinedMemory

memory = CombinedMemory(memories=[summary_memory, long_term_memory])

# 创建带记忆的 Agent
prompt = hub.pull("hwchase17/openai-functions-agent")
prompt = prompt.partial(
    history=memory.memories[0].memory_key,  # 短期
    long_term_info=memory.memories[1].memory_key  # 长期
)

agent = create_openai_functions_agent(llm, tools, prompt)

executor = AgentExecutor(
    agent=agent,
    tools=tools,
    memory=memory,  # 关键!注入记忆
    verbose=True
)

# 运行(自动携带记忆)
response = executor.invoke({"input": "再订一份昨天的麻辣烫"})

效果
Agent 会看到:

  • 短期摘要:“用户正在点餐”
  • 长期记忆:“喜欢微辣+雪碧”
    → 直接回复:“已为您下单杨国福麻辣烫(微辣)+ 雪碧,对吗?”

六、高级:自定义记忆演化逻辑

场景:当用户修改偏好时,自动更新长期记忆

def update_user_preference(new_info: str):
    """用新信息覆盖旧偏好"""
    # 1. 检索旧偏好
    old_docs = vectorstore.similarity_search("用户偏好", k=1)
    if old_docs:
        # 2. 让 LLM 合并新旧信息
        merge_prompt = f"""
        旧偏好: {old_docs[0].page_content}
        新信息: {new_info}
        请输出更新后的完整偏好(保留未提及的部分):
        """
        updated = llm.invoke(merge_prompt).content
        
        # 3. 删除旧记录,添加新记录
        vectorstore.delete([old_docs[0].metadata["id"]])
        vectorstore.add_texts([updated], metadatas=[{"type": "preference"}])

🔄 演化流程
用户说“以后不要雪碧了” → 触发 update_user_preference("不要雪碧") → 长期记忆更新


七、会话档案化实现(日志存储)

import json
from datetime import datetime

class SessionArchiver:
    def __init__(self, user_id: str):
        self.user_id = user_id
        self.session_id = f"sess_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
        self.turns = []
    
    def add_turn(self, role: str, content: str, metadata: dict = None):
        self.turns.append({
            "role": role,
            "content": content,
            "timestamp": datetime.utcnow().isoformat(),
            "metadata": metadata or {}
        })
    
    def save_to_disk(self):
        archive = {
            "session_id": self.session_id,
            "user_id": self.user_id,
            "turns": self.turns,
            "end_time": datetime.utcnow().isoformat()
        }
        with open(f"archives/{self.session_id}.json", "w") as f:
            json.dump(archive, f, indent=2, ensure_ascii=False)

# 在 AgentExecutor 中使用
archiver = SessionArchiver("user_789")

# 每次交互后记录
archiver.add_turn("user", "input_text")
archiver.add_turn("agent", "output_text", {"tools_used": [...]})

# 会话结束时保存
archiver.save_to_disk()

八、最佳实践与避坑指南

问题 解决方案
记忆污染 为每个用户/会话隔离记忆存储
Token 超限 优先用 SummaryMemory + VectorStore 组合
隐私泄露 敏感信息(手机号、地址)脱敏后再存记忆
记忆过时 设置 TTL(如 30 天自动清理)
幻觉记忆 所有记忆写入前用 LLM 校验一致性

九、总结:记忆系统的演进路径

阶段 能力 技术栈
V1:无记忆 每次对话独立 Chain
V2:短期记忆 单次会话连贯 ConversationBufferMemory
V3:长期记忆 跨会话个性化 VectorStoreRetrieverMemory
V4:智能记忆 自动更新、冲突检测、偏好学习 自定义演化逻辑 + LangGraph

🚀 未来方向

  • 记忆反思:Agent 定期回顾历史,提炼经验
  • 多模态记忆:存储图像、语音片段
  • 联邦记忆:在保护隐私前提下共享群体知识

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐