欢迎回到《Python + AI Agent 实战开发完全指南》!

在前五讲中,我们构建了一个具备"大脑"(ReAct推理)、“眼睛耳朵”(输入)和"手脚"(Tool Calling)的Agent。但如果你仔细观察它的行为,会发现它有一个致命的弱点:它没有记忆

一旦对话轮数超过了API的上下文窗口,或者你想让Agent在明天继续昨天的对话,它就会一脸茫然。这就好比一个只有短期记忆的金鱼,永远无法积累"阅历"。

在这一讲中,我们将为Agent装上记忆系统(Memory)。我们将抛弃已被官方弃用的旧版ConversationBufferMemory,全面拥抱LangChain最新的LangGraph Checkpoint(检查点)机制来实现短期记忆,让你的Agent从此具备"人格"和"经验"。


一、核心痛点:为什么你的Agent总是"失忆"?

在第3讲和第5讲的代码中,我们是通过一个简单的messages列表来维持对话的。这种方式存在两个巨大的工程缺陷:

  1. Token爆炸(Context Length Overflow):大模型的上下文窗口是有限的。如果你把几百轮对话全塞进去,不仅速度慢、费用高,还会直接报错context length exceeded
  2. 状态丢失(Stateless):目前的代码运行完就结束了。重启程序后,Agent完全不记得你是谁,之前聊过什么。

要解决这两个问题,我们需要引入短期记忆长期记忆的双层架构。


二、筑牢地基:短期记忆(基于LangGraph Checkpoint)

短期记忆对应的是Working Memory,也就是我们常说的"上下文"。在最新的LangChain生态中,官方强烈推荐使用LangGraph提供的Checkpointers来自动管理对话历史。

2.1 什么是Checkpointer?

你可以把它理解为一个"存档点"。每次Agent执行一步操作,Checkpointer就会自动把当前的messages状态保存到内存或数据库中。下次用户提问时,它会通过一个唯一的thread_id(线程ID)自动加载之前的对话历史。

2.2 安装必要的依赖
pip install langgraph langchain-openai

三、实战:基于LangGraph的完整记忆系统

3.1 核心架构设计

我们将采用您提供的代码架构,这是一个非常标准且优雅的LangGraph状态机实现,完美解决了Agent的短期记忆问题。

3.2 完整代码实现
import os
os.environ["PYTHONUTF8"] = "1"

# --- 1. 配置区 ---
# 你的API密钥和模型配置
API_KEY = "sk-***********************"  # 请替换为你的实际API密钥
BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"
MODEL = "qwen-turbo"

# --- 2. 初始化大模型 ---
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    api_key=API_KEY,
    base_url=BASE_URL,
    model=MODEL
)

# --- 3. 构建LangGraph状态机 ---
from langchain_core.messages import HumanMessage, SystemMessage
from langgraph.graph import StateGraph, MessagesState, START
from langgraph.checkpoint.memory import InMemorySaver

def chat_node(state: MessagesState):
    """
    核心对话逻辑
    state["messages"]: 包含了该会话ID下的所有历史消息
    """
    # 1. 构建系统提示词
    system_prompt = SystemMessage(content="你是一个友好的聊天助手")
    
    # 2. 拼接消息:系统指令 + 历史对话 + 当前输入
    all_msg = [system_prompt] + state["messages"]
    
    # 3. 调用模型
    resp = llm.invoke(all_msg)
    
    # 4. 返回新消息,LangGraph会自动将其存入state["messages"]
    return {"messages": resp}

# --- 4. 编译图 (Graph Compilation) ---
checkpointer = InMemorySaver()  # 使用内存存储检查点(短期记忆)

builder = StateGraph(MessagesState)
builder.add_node("chat", chat_node)
builder.add_edge(START, "chat")

# 编译图,注入记忆机制
chat_graph = builder.compile(checkpointer=checkpointer)
3.3 交互测试
# --- 5. 主交互循环 ---
if __name__ == "__main__":
    print(" 智能体已启动!(输入'exit'退出)")
    
    # 会话配置:同一个thread_id共享记忆
    cfg = {"configurable": {"thread_id": "session_001"}}
    
    while True:
        user_input = input("\n你: ")
        if user_input.lower() in ["exit", "quit"]:
            break
            
        # 调用图执行
        result = chat_graph.invoke(
            {"messages": [HumanMessage(content=user_input)]}, 
            config=cfg
        )
        
        # 提取并打印回复
        ai_response = result["messages"][-1].content
        print(f" 助手: {ai_response}")

四、关键特性分析

4.1 会话隔离机制

通过不同的thread_id,Agent可以轻松区分不同用户的会话:

# 用户A的会话
cfg_user_a = {"configurable": {"thread_id": "user_a_123"}}
# 用户B的会话  
cfg_user_b = {"configurable": {"thread_id": "user_b_456"}}
4.2 自动上下文管理

LangGraph自动处理对话历史的拼接和存储,开发者无需手动维护消息列表。

4.3 状态持久化

通过Checkpointer机制,对话状态在多次调用间自动保持。


五、工程建议与最佳实践

5.1 生产环境配置
  • Checkpointer选择:在生产环境中,建议使用SqliteSaverPostgresSaver替代InMemorySaver,实现真正的持久化存储。
  • 错误处理:添加适当的异常处理机制,确保系统稳定性。
  • 性能优化:对于长对话,考虑实现对话摘要功能,控制上下文长度。
5.2 安全配置
  • API密钥管理:将API密钥存储在环境变量或配置文件中,避免硬编码。
  • 输入验证:对用户输入进行必要的验证和过滤。

六、本节小结

今天我们成功为Agent构建了完整的短期记忆系统:

  1. 状态管理:通过LangGraph的MessagesState,我们实现了自动化的对话历史管理。
  2. 会话隔离:利用thread_id机制,确保不同用户的对话相互独立。
  3. 持久化存储:通过Checkpointer,实现了对话状态的自动保存和恢复。

核心价值:这段代码证明了Agent能够通过thread_id区分不同用户的会话,并在同一个会话中记住用户的信息,实现了真正的个性化对话体验。


七、扩展思考

  1. 长期记忆:如何结合向量数据库实现跨会话的知识存储和检索?
  2. 记忆清理:如何实现对话历史的自动清理,防止内存溢出?
  3. 分布式部署:在微服务架构中,如何实现跨节点的会话状态同步?

八、作业练习

  1. 实践任务:将本讲的代码部署为一个Web服务,支持多用户同时访问。
  2. 扩展挑战:为Agent添加对话摘要功能,当对话过长时自动生成摘要。
  3. 性能测试:测试不同长度对话对系统性能的影响,找出最优的上下文长度。

下一讲预告
在第7讲《RAG(检索增强生成)实战》中,我们将结合今天搭建的记忆系统,接入企业内部的PDF、Word文档,打造一个真正懂业务的私有知识库问答机器人。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐