Agent实战(三)Agent的短期记忆
✅基础记忆:通过实现跨轮次状态保持;✅智能裁剪:利用中间件动态精简上下文,避免 token 耗尽;✅主动遗忘:按需删除敏感或冗余信息,提升安全性与效率。这些能力使得 Agent 不仅“聪明”,而且“可靠”——既能记住重要信息,又不会被冗长的历史拖累。
代码开源Github
在构建智能 Agent 时,一个关键挑战是如何让模型在多轮对话中记住上下文信息——比如用户的名字、偏好或之前的请求。然而,大语言模型(LLM)本身是无状态的,每次调用都是独立的。因此,我们需要一种机制来持久化对话历史,并在后续交互中将其重新注入上下文。
LangChain 结合 LangGraph 提供了强大的 短期记忆(Short-Term Memory) 能力,它不仅支持基础的记忆功能,还能灵活地实现消息裁剪、主动遗忘、上下文摘要等高级策略,从而在保持上下文连贯性的同时,避免超出 LLM 的上下文窗口限制。
📌 核心思想:与 LangGraph 中的状态图一样,Agent 的短期记忆依赖于检查点(Checkpointer) 机制。通过将对话历史持久化到内存或数据库中,Agent 可以在中断后恢复会话,实现真正的“有记忆”的交互。
1. 使用短期记忆:记住用户的名字
最简单的短期记忆场景,就是让 Agent 记住用户在对话初期提供的信息。
使用 InMemorySaver 作为检查点存储(适用于测试),并为会话指定唯一的 thread_id:
from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver
import sys
import os
# 直接指定 src 路径
src_path = "/root/shared-nvme/LLM-Learning/Agent-Learning/src"
sys.path.insert(0, src_path)
from Models import ModelManager
model_manager = ModelManager()
llm = model_manager.get_qwen_model()
checkpointer = InMemorySaver()
agent = create_agent(
model=llm,
tools=[],
checkpointer=checkpointer,
)
config = {"configurable": {"thread_id": "session-1"}}
# 第一轮:用户告诉名字
agent.invoke({"messages": "你好!我叫小李。"}, config)
# 第二轮:随便聊点别的
agent.invoke({"messages": "今天天气真不错。"}, config)
# 第三轮:问名字,看是否还记得
final = agent.invoke({"messages": "我刚才告诉你我叫什么名字?"}, config)
print("\n✅ 最终回答:")
final["messages"][-1].pretty_print()
💡 说明:只要使用了
checkpointer并传入相同的thread_id,Agent 就会在每次调用时自动加载完整的对话历史作为上下文。
预期效果:即使中间插入无关对话,Agent 仍能准确回忆起“小李”这个名字。
✅ 最终回答:
================================== Ai Message ==================================
是的,你刚才告诉我你叫小李。我记住了!😊 有什么我可以帮你或和你聊的吗,小李?
2. 自动裁剪消息:防止上下文爆炸
随着对话轮次增加,消息列表会不断增长。若不加控制,很容易超出 LLM 的上下文长度限制(如 32K tokens),导致性能下降甚至报错。
LangChain 允许我们通过 中间件(middleware) 在模型调用前动态调整消息历史。下面的例子实现了“保留第一条 + 最近 3 条”的策略:
from typing import Any, Optional
from langchain_core.messages import RemoveMessage
from langgraph.checkpoint.memory import MemorySaver
from langchain.agents import create_agent, AgentState
from langchain.agents.middleware import before_model
from langgraph.graph.message import REMOVE_ALL_MESSAGES
@before_model
def trim_messages(state: AgentState, runtime) -> Optional[dict[str, Any]]:
"""保留第一条 + 最近 3 条消息,防止上下文过长"""
messages = state["messages"]
if len(messages) <= 4:
return None
first_msg = messages[0]
recent_msgs = messages[-3:]
new_messages = [first_msg] + recent_msgs
return {
"messages": [
RemoveMessage(id=REMOVE_ALL_MESSAGES),
*new_messages
]
}
tools = []
agent = create_agent(
model=llm,
tools=tools,
middleware=[trim_messages],
checkpointer=MemorySaver(),
)
config = {"configurable": {"thread_id": "1"}}
# 测试对话
agent.invoke({"messages": "你好,我叫小陈。"}, config)
agent.invoke({"messages": "我全名叫陈小春。"}, config)
agent.invoke({"messages": "帮我写一首关于春天的诗。"}, config)
agent.invoke({"messages": "再写一首关于夏天的。"}, config)
agent.invoke({"messages": "秋天呢?也来一首。"}, config)
final = agent.invoke({"messages": "我叫什么名字?你知道我的全名吗?只需要回答我的问题,不需要回答其他内容"}, config)
print("\n✅ 最终回答:")
final["messages"][-1].pretty_print()
🔧 原理:
@before_model装饰器定义了一个在每次 LLM 调用前执行的钩子函数。我们在此函数中构造新的消息列表,并通过RemoveMessage(id=REMOVE_ALL_MESSAGES)清空旧历史,再插入精简后的消息。
预期效果:尽管发送了 5 条消息,但 Agent 实际看到的上下文只有 4 条(首条 + 最近 3 条),因此不能记住“陈小春”这个全名。
✅ 最终回答:
================================== Ai Message ==================================
你叫小陈,我没有你的全名。
3. 主动删除消息:强制“遗忘”早期信息
有时我们希望 Agent 主动丢弃某些敏感或过时的信息。下面的例子演示了如何在每轮对话后自动删除最早的两条消息:
@before_model
def post_model_hook(state: AgentState, runtime) -> Optional[dict[str, Any]]:
messages = state["messages"]
# 如果消息超过 2 条,就删除最早的 2 条
if len(messages) > 2:
return {"messages": [RemoveMessage(id=m.id) for m in messages[:2]]}
return {}
agent = create_agent(
model=llm,
tools=[],
middleware=[post_model_hook],
checkpointer=InMemorySaver(),
)
config = {"configurable": {"thread_id": "session-3"}}
# 发送三条消息
agent.invoke({"messages": "我是张敏。"}, config)
agent.invoke({"messages": "我今年 28 岁。"}, config)
agent.invoke({"messages": "你能记住我的年龄吗?"}, config)
# 再问名字或年龄(应已丢失)
response = agent.invoke({"messages": "我叫什么名字?"}, config)
print("\n✅ 删除后回答(应不记得名字):")
response["messages"][-1].pretty_print()
⚠️ 注意:这里使用的是
@before_model(实际应在模型调用前处理),但逻辑上模拟了“每轮后清理”的行为。严格来说,若要在模型响应后删除,应使用@after_model或post_model_hook。
预期效果:当第三条消息被处理时,前两条(名字和年龄)已被删除,因此 Agent 无法回答“我叫什么名字”。
✅ 删除后回答(应不记得名字):
================================== Ai Message ==================================
你叫“用户”。在我们这次对话中,这是你的默认身份。如果你想告诉我你的名字,我很乐意记住并使用它!
总结
LangChain 的短期记忆机制为 Agent 提供了强大而灵活的上下文管理能力:
- ✅ 基础记忆:通过
checkpointer实现跨轮次状态保持; - ✅ 智能裁剪:利用中间件动态精简上下文,避免 token 耗尽;
- ✅ 主动遗忘:按需删除敏感或冗余信息,提升安全性与效率。
这些能力使得 Agent 不仅“聪明”,而且“可靠”——既能记住重要信息,又不会被冗长的历史拖累。
更多推荐


所有评论(0)