那langchain的reAct是怎么实现的

LangChain 实现 ReAct 的核心逻辑,其实就是把"思考-行动-观察"的循环进行了高度模块化和工程化的封装。它不再需要你手动去拼接字符串和解析文本,而是通过以下几个关键组件协同工作来自动完成:

🧩 LangChain 实现 ReAct 的四大核心组件

  1. ReAct Prompt 模板(指挥棒)

    LangChain 内置了标准的 ReAct 提示词模板(例如 hwchase17/react)。这个模板会明确告诉大模型:"你是一个拥有特定工具的助手,你必须按照 Thought -> Action -> Action Input -> Observation -> Final Answer 的固定格式来输出。" 这保证了模型每次的输出都是结构化的,方便程序后续解析。

  2. 工具集与 Tool Calling(手和脚)

    你需要将搜索、计算器或自定义函数封装成 LangChain 的 @tool。现代 LangChain 结合支持原生工具调用(Function/Tool Calling)的大模型 API,当模型决定使用某个工具时,不会返回普通文本,而是直接返回一个结构化的 tool_call 对象。这让 LangChain 能精准地知道该执行哪个工具以及传入什么参数,完全避免了传统字符串解析容易出错的问题。

  3. Agent Executor 与 Scratchpad(大脑与草稿纸)

    这是 ReAct 循环的发动机。AgentExecutor 负责驱动整个流程:

  • Scratchpad(草稿纸) :这是一个极其重要的概念。每一轮的 Thought(思考)、Action(行动)和 Observation(观察结果)都会被追加到这个"草稿纸"里。在下一轮对话时,LangChain 会把整个草稿纸的内容连同最新的环境反馈一起喂给大模型。这样模型就能清楚地记得"我之前做了什么、得到了什么",从而避免像金鱼一样只有七秒记忆而陷入死循环。
  • 循环控制AgentExecutor 会自动检测模型的输出。如果是工具调用,就暂停生成,去执行工具;拿到结果后,再把结果放回草稿纸,让模型继续下一轮的思考。直到模型输出 Final Answer,或者达到了预设的最大迭代次数(max_iterations),循环才会终止。
  1. Memory(长期记忆)
    除了记录单次任务执行过程的 Scratchpad,LangChain 还允许你挂载独立的 Memory 模块(如 ConversationBufferMemory 或基于 SQLite 的持久化存储)。这能让 Agent 记住跨对话的用户偏好和历史上下文。

💻 代码实战:LangChain 是如何串联这些组件的?

在 LangChain 中,通常只需要几行代码就能启动一个完整的 ReAct Agent。以下是基于最新版 LangChain 的实现方式:

python 复制代码
from langchain.agents import create_react_agent, AgentExecutor
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
import hub # 用于拉取官方预置的 ReAct prompt 模板[[source_group_web_6]]

# 1. 定义工具(Agent 的手和脚)
@tool
def get_weather(location: str) -> str:
    """获取指定城市的天气"""
    return f"{location} 今天是晴天,气温 25°C"

tools = [get_weather]

# 2. 初始化 LLM(需支持 Tool Calling)
llm = ChatOpenAI(model="gpt-4o", temperature=0)

# 3. 拉取标准的 ReAct Prompt 模板(指挥棒)
prompt = hub.pull("hwchase17/react")

# 4. 创建 ReAct Agent(自动组装了 LLM + Prompt + Tools)
agent = create_react_agent(llm, tools, prompt)

# 5. 创建执行器(Agent Executor,包含循环控制和草稿纸管理)
# verbose=True 可以让你在控制台清晰看到 Thought/Action/Observation 的全过程
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, max_iterations=5)

# 6. 运行任务
result = agent_executor.invoke({"input": "北京今天的天气怎么样?"})
print(result["output"])

🚀 进阶演进:从线性链条到状态图 (LangGraph)

虽然上述的 AgentExecutor 已经非常强大,但它在处理极其复杂的分支逻辑、并行任务或多智能体协作时会显得有些线性化。

因此,LangChain 团队推出了更先进的 LangGraph。它将 ReAct 模式从简单的"链条"升级为了"图(Graph)"。在 LangGraph 中,每一个思考步骤、工具调用都是一个节点(Node),你可以自由地定义它们之间的流转关系(比如失败重试、条件分支、人工审批等),并提供了极强的状态管理和持久化能力。对于生产级别的复杂 AI Agent 应用,LangGraph 正在成为新的架构首选。

Action和Action Input不是一步吗?

是的,完全正确!Action 和 Action Input 绝对属于同一步

在 ReAct 的每一次循环中,它们是大模型一次性输出的"一套组合拳",绝对不能被拆开。

我们可以从以下三个角度来理解为什么它们是一体的:

🎯 1. 逻辑上的不可分割

就像你上一秒刚决定"我要给张三打电话"(这是 Action ),下一秒嘴里就必须说出"张三的电话号码是XXX"(这是 Action Input )。

如果只有 Action 没有 Input,程序根本不知道该把参数传给谁;如果只有 Input 没有 Action,程序也不知道该拿这些参数去执行哪个功能。因此,模型在生成 Thought(思考)之后,必须紧接着在同一轮回复里,同时交代清楚 ActionAction Input

💻 2. 代码执行视角的"原子操作"

在你的 Python 代码(Agent Runtime)眼里,解析模型输出时,这两者是作为一个整体被提取出来的。

python 复制代码
# 伪代码演示:程序是在同一时刻抓取这两个信息的
model_output = """
Thought: 我需要查天气。
Action: get_weather          
Action Input: {"city": "杭州"} 
"""

# 你的程序会一次性把它们都抠出来,然后合并执行:
action = extract_action(model_output)        # 拿到 "get_weather"
action_input = extract_input(model_output)   # 拿到 {"city": "杭州"}

# 真正的"执行一步"是下面这行代码,缺一不可:
result = tools[action](**action_input)  

📝 3. 格式规范上的绑定

在标准的 ReAct Prompt 提示词模板中,它们也是紧挨着出现的:

text 复制代码
Thought: ... (先思考)
Action: ... (决定用什么工具)
Action Input: ... (决定传什么参数)
Observation: ... (系统填入结果)

模型必须在一个完整的回复块(Block)内把这三行(Thought, Action, Action Input)全部写完,然后才会停下来,等待你的程序去执行工具并填入 Observation

总结一下:

你可以把 Action + Action Input 看作是一次完整的**"函数调用请求"**。它们共同构成了 Agent 向外发出的一个完整指令,绝对是密不可分的一步!

Action Input是啥,和 Observation区别

简单来说,Action Input 是模型发出的"指令参数" ,而 Observation 是工具执行后返回的"真实结果"

在 ReAct 架构中,它们处于整个循环的不同阶段,扮演着完全相反的角色:

  • Action Input(行动输入):属于"行动(Action)"的一部分,是模型告诉程序:"我要用这个工具,请传入这些参数。"
  • Observation(观察):是程序执行完工具后,把客观世界的反馈塞回给模型看的内容。

为了让你更直观地理解,我们可以用一个**"点外卖"**的生活场景来打比方:

  • Thought(思考):你心想"我饿了,得看看附近有什么好吃的"。
  • Action(行动):你打开了外卖软件。
  • Action Input(行动输入) :你在搜索框里输入了 "炸鸡" 并点击了搜索。(这是你发出的具体指令和参数)
  • Observation(观察):屏幕上刷出来了一堆真实的店铺列表、价格和配送时间。(这是外部世界给你的真实反馈)

🔍 详细对比与代码示例

在 LangChain 或原生 API 的实现中,它们的区别会更加具体:

Action Input (行动输入)
  • 谁产生的? 由大语言模型(LLM)生成。
  • 本质是什么? 它是调用工具时所需的结构化参数,通常是一个 JSON 对象或者特定的字符串。
  • 作用: 明确告诉系统在执行某个工具时,具体要传什么数据进去。
Observation (观察)
  • 谁产生的? 由外部工具、API 或环境产生,绝对不是模型瞎编的
  • 本质是什么? 它是工具函数执行后的返回值(比如一段网页文本、一个计算结果、数据库的一行记录)。
  • 作用: 把这个真实结果追加到对话历史中,让模型在下一轮思考时能看到它,从而基于事实继续推理。

💻 结合代码看流程

假设用户问:"北京今天多少度?" 你的 Agent 绑定了 get_weather 天气查询工具。整个过程的伪代码如下:

python 复制代码
# --- 第1步:模型输出 Thought 和 Action ---
# 模型经过思考,决定调用天气工具,并生成了以下输出:
model_output = """
Thought: 我需要查询北京的实时气温。
Action: get_weather
Action Input: {"city": "北京"}  
""" 
# 👆 这里的 {"city": "北京"} 就是 Action Input。
# 它是模型生成的,用来指导程序该怎么去调工具。

# --- 第2步:你的程序(Agent Executor)拦截并执行 ---
# 1. 解析出 Action 是 get_weather,Action Input 是 {"city": "北京"}
# 2. 真正去调用你写好的 Python 函数:
tool_result = get_weather(city="北京") 
# 假设这个函数请求了真实的气象API,返回了:"晴天,25°C"

# --- 第3步:将结果包装成 Observation 喂回给模型 ---
observation = f"Observation: {tool_result}" 
# 👆 这里的 "Observation: 晴天,25°C" 就是 Observation。
# 它是客观发生的真实数据。

# --- 第4步:开启下一轮对话 ---
# 程序把上面的 model_output 和 observation 都拼接到聊天记录里,再次发给模型。
# 模型看到 Observation 后,就能自信地输出最终答案(Final Answer)了。

总结一下:
Action Input 是模型向外部世界伸出的"手",带着具体的参数去触碰现实;而 Observation 是外部世界传递给模型的"眼睛",让它看到自己刚才那个动作到底带来了什么真实的结果。

相关推荐
Eloudy9 小时前
定常约束的情况下,质点矢径 r_i 不显含时间t
人工智能·算法·机器学习
海盗12349 小时前
AI科技日报-2026年5月23日
人工智能
HIT_Weston9 小时前
91、【Agent】【OpenCode】grep 工具提示词(参数内容)
人工智能·agent·opencode
南屹川9 小时前
【Python进阶】异步编程完全指南:从asyncio到实战应用
人工智能
Industio_触觉智能9 小时前
瑞芯微RK3576迷你工控整机边缘计算盒子规格书参数配置性能说明,触觉智能IPC7609
人工智能·嵌入式硬件·边缘计算·openharmony·开源鸿蒙·瑞芯微·rk3576
swipe9 小时前
Elasticsearch 全文检索工程教程:倒排索引、IK 分词器与 BM25 从原理到落地
面试·langchain·llm
AI街潜水的八角9 小时前
PyTorch框架——基于深度学习PmrNet神经网络AI去噪图像增强系统(含训练代码、创新对比、数据集和GUI交互界面)
人工智能·pytorch·深度学习
月光船幽幽9 小时前
Helio协议热切换实战解析
人工智能·动态规划·拓扑学
烟雨江南7859 小时前
农田上空的“智慧天眼”:多光谱视觉系统在作物生长监测与病虫害大范围筛查中的落地方案
人工智能·ai质检