本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续!
- 🚀 魔都架构师 | 全网30W技术追随者
- 🔧 大厂分布式系统/数据中台实战专家
- 🏆 主导交易系统百万级流量调优 & 车联网平台架构
- 🧠 AIGC应用开发先行者 | 区块链落地实践者
- 🌍 以技术驱动创新,我们的征途是改变世界!
- 👉 实战干货:编程严选网
0 前言
在开发复杂的AI应用时,赋予Agent记忆能力是一个关键步骤。这不仅能提高Agent的性能,还能使其在多轮对话中保持上下文连贯性。本文详细介绍如何在Langchain框架中为Agent添加记忆功能,并深入解析每个步骤的原理和最佳实践。
Agent记忆功能的核心组件
Langchain构建具有记忆功能的Agent涉及核心组件:
- 工具(Tools): Agent用来执行特定任务的功能模块
- 记忆(Memory): 存储和检索对话历史的组件
- 大语言模型(LLM): 负责理解输入、决策和生成响应的核心智能体
协同工作,使得Agent在多轮对话中保持连贯性并做出明智决策。
1 构建Agent可用工具
定义Agent可用工具:
老版:
# 构建一个搜索工具,Langchain提供的一个封装,用于进行网络搜索。
search = SerpAPIWrapper()
# 创建一个数学计算工具,特殊的链,它使用LLM来解析和解决数学问题。
llm_math_chain = LLMMathChain(
llm=llm,
verbose=True
)
tools = [
Tool(
name = "Search",
func=search.run,
description="useful for when you need to answer questions about current events or the current state of the world"
),
Tool(
name="Calculator",
func=llm_math_chain.run,
description="useful for when you need to answer questions about math"
),
]
print(tools)
新版:
_ALLOWED_BIN_OPS = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
ast.FloorDiv: operator.floordiv,
ast.Mod: operator.mod,
ast.Pow: operator.pow,
}
_ALLOWED_UNARY_OPS = {
ast.UAdd: operator.pos,
ast.USub: operator.neg,
}
def _safe_eval(node: ast.AST) -> Any:
if isinstance(node, ast.Expression):
return _safe_eval(node.body)
if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
return node.value
if isinstance(node, ast.BinOp) and type(node.op) in _ALLOWED_BIN_OPS:
return _ALLOWED_BIN_OPS[type(node.op)](_safe_eval(node.left), _safe_eval(node.right))
if isinstance(node, ast.UnaryOp) and type(node.op) in _ALLOWED_UNARY_OPS:
return _ALLOWED_UNARY_OPS[type(node.op)](_safe_eval(node.operand))
raise ValueError(f"unsupported expression: {ast.dump(node)}")
@tool
def calculator(expression: str) -> str:
"""Evaluate a basic arithmetic expression, for example '18 * 23 + 7'."""
try:
return str(_safe_eval(ast.parse(expression, mode="eval")))
except Exception as exc:
return f"计算失败:{exc}"
tools = [calculator]
if os.getenv("SERPAPI_API_KEY"):
try:
from langchain_community.utilities import SerpAPIWrapper
_search = SerpAPIWrapper()
@tool
def web_search(query: str) -> str:
"""Search the web for current or external information."""
return _search.run(query)
tools.append(web_search)
except ImportError as exc:
print(f"SerpAPI 搜索工具未启用:{exc}")
tools
2 增加memory组件
为Agent添加记忆功能。
老版:
from langchain.memory import ConversationBufferMemory
# 记忆组件
memory = ConversationBufferMemory(
# 指定了存储对话历史的键名
memory_key="chat_history",
# 确保返回的是消息对象,而不是字符串,这对于某些Agent类型很重要
return_messages=True
)
3 定义agent
有了工具和记忆组件,可初始化Agent。
老版:
agent_chain = initialize_agent(
tools,
llm,
handle_parsing_errors=True,
memory=memory
)
handle_parsing_errors=True: 自动处理解析错误,提高Agent的稳定性。memory=memory: 将我们之前定义的记忆组件传递给Agent。
新版:
# 负责保存状态
checkpointer = InMemorySaver()
agent = create_agent(
model=llm,
tools=tools,
system_prompt="你是一个中文助手。需要计算时优先调用 calculator 工具。回答要简洁。",
checkpointer=checkpointer,
)
# thread_id决定每次调用归属于哪段会话
config = {
"configurable": {
"thread_id": "qwen-memory-demo"}}
相同 thread_id 会读取历史消息,不同 thread_id 彼此隔离。
4 查看默认的agents prompt
了解Agent使用的默认提示词模板非常重要,有助理解Agent的行为并进行调整:
print(agent_chain.agent.prompt.messages)
print(agent_chain.agent.prompt.messages[0])
print(agent_chain.agent.prompt.messages[1])
print(agent_chain.agent.prompt.messages[2])
输出Agent使用的默认提示词模板。包括系统消息、人类消息提示词模板和AI消息模板:

5 优化Agent配置
为了更好地利用记忆功能,修改Agent配置,确保它在每次交互中都能访问对话历史,让Agent每次决策时都能考虑到之前对话内容。
老版
需用agent_kwargs传递参数,将chat_history传入
agent_chain = initialize_agent(
tools,
llm,
handle_parsing_errors=True,#处理解析错误
# 通过该参数可自定义Agent的行为
agent_kwargs={
"extra_prompt_messages":
# chat_history用于插入对话历史
[MessagesPlaceholder(variable_name="chat_history"),
# agent_scratchpad用于Agent的中间思考过程
MessagesPlaceholder(variable_name="agent_scratchpad")],
},
memory=memory #记忆组件
)
老版 memory 思路
这套写法依赖旧 agent 抽象,memory 必须和 prompt 变量名对齐,agent_scratchpad、chat_history 放错就容易失效。
而新版重点是 thread_id。同一个 thread_id 会继续读取历史消息,不同 thread_id 就是独立会话。这更接近现在 LangChain/LangGraph 的状态模型。
6 验证优化后的提示词模板
print(agent_chain.agent.prompt.messages)
print(agent_chain.agent.prompt.messages[0])
print(agent_chain.agent.prompt.messages[1])
print(agent_chain.agent.prompt.messages[2])

能看到新添加的chat_history和agent_scratchpad占位符。
7 总结
LangChain 1.x 主流写法:create_agent + InMemorySaver + thread_id。工具改成 @tool,数学工具不再依赖旧 chain。
为Langchain Agent添加记忆,使得Agent能够在多轮对话中保持上下文连贯性,大大提高其在复杂任务中的表现。
添加记忆功能只是构建高效Agent第一步。按需调整记忆组件的类型和参数,或实现更复杂的记忆管理策略。
注意平衡记忆的深度和Agent响应速度。过多历史信息导致决策缓慢或偏离主题。因此,你可能需实现某种形式的记忆修剪或总结机制。