langchain :记忆组件混淆概念澄清 & 创建Conversational ReAct后显示指定 记忆组件

Q:但是langchain 0.3的记忆组件有多种,比如ConversationBufferMemory,ConversationBufferWindowMemory, 那么create_react_agent用的是哪一种?或者是否可以显示的指定?

你提的这个问题非常精准,直击了 LangChain 模块化设计的核心!答案会让你对新版 LangChain 的设计有更深的理解。

核心答案:create_react_agent 本身不关心也 不使用任何记忆组件。你可以,也 必须**,在 AgentExecutor 中显式地指定你想要使用的记忆类型。**

这是一个非常重要的设计分离:

  • create_react_agent 的职责是创建 Agent 的核心决策逻辑 。它只负责将 LLM、工具(Tools)和提示(Prompt)三者"粘合"起来,生成一个懂得如何"思考"和"行动"的 Runnable 对象。它本身是无状态的。
  • AgentExecutor 的职责是执行和管理 Agent 的运行循环 。它负责调用 Agent、执行工具、处理错误,以及------正如你所问的------管理对话记忆。

如何为你的 Agent 指定记忆类型?

你可以在创建 AgentExecutor 时,将任何你想要的记忆组件实例通过 memory 参数传递进去。AgentExecutor 会自动处理好后续的一切:

  1. 在每次调用 Agent 之前,从 memory 对象中加载历史对话。
  2. 将加载的历史对话填充到提示模板中名为 chat_history 的占位符里。
  3. 在 Agent 完成一次交互后,将这次新的输入和输出保存回 memory 对象中。
示例:明确使用 ConversationBufferWindowMemory

让我们用一个具体的例子,来创建一个只记住最近 2 轮对话的 Conversational ReAct Agent。

python 复制代码
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain import hub
from langchain.agents import create_react_agent, AgentExecutor
from langchain.memory import ConversationBufferWindowMemory # 明确导入窗口记忆

# 1. 初始化 LLM 和工具
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
tools = [TavilySearchResults(max_results=1)]

# 2. 明确创建你想要的记忆实例
# 我们创建一个只保留最近 k=2 轮对话的窗口记忆
memory = ConversationBufferWindowMemory(
    k=2,
    memory_key="chat_history", # 必须和 prompt 中的占位符名称一致
    return_messages=True
)

# 3. 拉取一个支持对话的 prompt
# "hwchase17/react-chat" 模板内置了 `MessagesPlaceholder(variable_name="chat_history")`
prompt = hub.pull("hwchase17/react-chat")

# 4. 创建 Agent (这里不涉及 memory)
agent = create_react_agent(llm, tools, prompt)

# 5. 创建 AgentExecutor,并在这里"注入"我们选择的记忆组件
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    memory=memory,  # <--- 在这里显式指定!
    verbose=True
)

# --- 开始对话,观察窗口记忆的效果 ---

# 第 1 轮对话 (记忆中: 1)
print("--- Interaction 1 ---")
agent_executor.invoke({"input": "Hi, my name is Bob."})

# 第 2 轮对话 (记忆中: 1, 2)
print("\n--- Interaction 2 ---")
agent_executor.invoke({"input": "I live in New York."})

# 第 3 轮对话 (记忆中: 2, 3。第 1 轮被挤掉了)
print("\n--- Interaction 3 ---")
agent_executor.invoke({"input": "What is my name?"})

输出分析:

当你运行到第三次交互时,你会发现 Agent 已经不记得你的名字是 "Bob" 了。这是因为 ConversationBufferWindowMemory(k=2) 的作用,它只保留了最近的两次交互("我住在纽约" 和 "我叫什么名字?"),而最早的 "我叫 Bob" 已经被"挤出"了记忆窗口。

如果你把 memory = ConversationBufferWindowMemory(k=2, ...) 换成 memory = ConversationBufferMemory(...),那么在第三轮交互时,Agent 就会轻松地回答出你的名字。

常用记忆组件总结

你可以根据需求,选择并实例化不同的记忆组件传入 AgentExecutor:

记忆组件 工作方式 适用场景
ConversationBufferMemory 存储所有对话历史。 需要完整上下文的短对话,但小心过长的对话会超出模型的 token 限制。
ConversationBufferWindowMemory 只存储最近的 k 轮对话。 需要上下文但又想控制 token 数量的持续对话,是最常用的选项之一。
ConversationSummaryMemory 随着对话进行,不断将旧的对话内容用 LLM 进行总结。 非常长的对话,既要保留早期信息又要节省 token 的场景。
ConversationSummaryBufferMemory 结合了 Buffer 和 Summary,保留最近的几轮对话原文,并把更早的对话进行总结。 对近期对话细节和长期对话主线都有要求的复杂场景。

结论: LangChain 的新设计赋予了你完全的控制权。create_react_agent 只负责"思考逻辑",而 AgentExecutor 负责"执行和记忆",你可以像插拔 U 盘一样,轻松地为你的 Agent 配置任何类型的记忆模块。

Q:为什么在创建create_react_agent制定了tool,然后在AgentExecutor又指定了tool?

这是一个非常棒的观察,也是一个能帮助你彻底理解 LangChain 新版模块化设计的关键问题!

简单来说,Agent 和 AgentExecutor 是两个独立的角色,它们都需要知道 tools 的信息,但用途完全不同。

我们可以用一个 "经理" 和 "工人" 的比喻来理解:

  • create_react_agent 创建的是 "经理 (Agent)" :经理负责决策。他需要一份工具清单(包含每个工具的名称和功能描述),这样他才能在接到任务时,聪明地决定"哦,这个任务应该让'搜索工人'去做"。他只下达指令,自己不动手。
  • AgentExecutor 是 "负责执行的工头" :工头负责执行 。他手下管理着所有真正的工人(工具对象)。当他收到经理的指令(例如"使用'搜索工具'去查'LangChain CEO'"),他需要根据指令中的工具名称,找到那个真正会干活的"搜索工人"对象,然后命令他去工作。

现在,我们把这个比喻对应到代码中:

1. create_react_agent(..., tools, ...) 的职责 (经理做决策)

create_react_agent 需要 tools 列表,是为了生成给 LLM 看的提示 (Prompt)。

它会遍历你传入的 tools 列表,提取出每个工具的 name (名称) 和 description (功能描述),然后将它们格式化成一段文本,插入到提示模板的 {tools} 和 {tool_names} 占位符中。

例如,提示模板中的这部分:

text 复制代码
You have access to the following tools:
{tools}

Use the following format:
...
Action: the action to take, should be one of [{tool_names}]
...

会被 create_react_agent 填充成:

text 复制代码
You have access to the following tools:
TavilySearchResults: A search engine optimized for comprehensive, accurate, and trusted results.

Use the following format:
...
Action: the action to take, should be one of [TavilySearchResults]
...

所以,传给 create_react_agent 的 tools,是为了让 LLM (经理) 知道自己有哪些工具可用,以及它们分别能干什么,从而做出正确的决策。

2. AgentExecutor(..., tools, ...) 的职责 (工头去执行)

AgentExecutor 需要 tools 列表,是为了在接收到 LLM 的决策后,能真正地执行工具。

当 LLM (经理) 输出它的决策后,例如:

复制代码
Thought: I need to find the CEO of LangChain.
Action: TavilySearchResults
Action Input: "Who is the CEO of LangChain?"

AgentExecutor (工头) 会解析这段文本。它看到 Action: TavilySearchResults,就会在自己持有的 tools 列表(一个包含真实工具对象的 Python 列表)中,查找那个 name 属性为 "TavilySearchResults" 的工具对象。找到后,它会调用这个对象的 .invoke("Who is the CEO of LangChain?") 方法来执行搜索。

所以,传给 AgentExecutor 的 tools,是为了在 LLM 做出选择后,能够找到并运行那个具体的、可执行的工具对象。

总结

组件 角色 为什么需要 tools?
create_react_agent 决策者 (经理) 为了"看":读取工具的名称和描述,生成提示,让 LLM 知道有哪些选项可选。
AgentExecutor 执行者 (工头) 为了"用":根据 LLM 输出的工具名称,查找并调用实际的工具对象来完成任务。

这种设计上的分离,正是 LangChain 模块化和灵活性的体现。它将"决策逻辑"和"执行逻辑"解耦,使得你可以独立地修改和配置它们,例如,你可以用同一个 AgentExecutor 来运行不同逻辑的 Agent,反之亦然。

相关推荐
怪奇云呼军15 小时前
教育试听预约后没到课,闪电智能 Voice Agent 如何做分层回访?
人工智能·python·算法·云计算·音视频
ajassi200015 小时前
AI语音智能体开发日记(十八)智能体服务器xiaozhi-esp32-server源码部署指南
运维·服务器·人工智能·ai·ai编程
云淡风轻~窗明几净15 小时前
角谷猜想的进展之三 移动了群山/沸騰的群山 2026-10-10
人工智能·算法·dubbo·图论
AliCloudROS15 小时前
计算巢支持一键私有化部署Qwen3.8-27B
人工智能
汇智信科15 小时前
汇智兵棋:AI赋能的一体化智能兵棋推演平台
人工智能
Joecien15 小时前
AI 生成透明背景图实战:Qwen-Image-2.1-Pro API 实测(21 次实验 + 完整调用代码 + 避坑指南)
人工智能
龙亘川16 小时前
设备管理业务建模:从设备信息台账到维护计划执行闭环
大数据·人工智能·智慧城市·开源软件·数据可视化
Psycho_MrZhang16 小时前
多 Agent 研究系统的架构与实践
人工智能·架构
skywalk816316 小时前
在FreeBSD系统的linux仿真环境下安装和使用kiro 这个亚马逊的AI agent
linux·人工智能·freebsd·kiro
ForeverYang201516 小时前
一种无需训练缺陷数据生成算法--O2MAG
人工智能·深度学习·算法