news 2026/5/10 16:15:08

ReAct+LangGraph:构建大模型智能体的完整指南(含代码示例)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ReAct+LangGraph:构建大模型智能体的完整指南(含代码示例)

简介

本文详细介绍了如何使用LangGraph框架构建ReAct智能体,分为硬编码和基于大语言模型两种实现方式。ReAct框架通过"推理+行动"的循环流程,使智能体能思考并解决问题。LangGraph允许将智能体行为定义为"图"结构,支持复杂流程设计。文章通过实际代码示例展示了简单和基于LLM的ReAct智能体构建过程,后者通过提示词引导LLM动态决策,实现更灵活的智能体行为,实现了"工作流结构"与"驱动智能"的解耦。


如今大模型落地热潮中,ReAct 框架凭借 “推理 + 行动” 的核心逻辑,成为搭建实用型智能体的关键技术。而 LangGraph 的出现,更是让智能体的工作流搭建变得灵活高效 —— 无需复杂架构设计,就能实现 “推理与动作” 的闭环。

什么是 ReAct 模式?

ReAct(Reasoning + Acting,即推理 + 行动)是构建人工智能(AI)智能体的常用模式,这类智能体能够通过思考分析问题,并采取行动解决问题。该模式遵循一个简单的循环流程:

  • 推理(Reasoning):智能体思考下一步需要执行的操作。
  • 行动(Acting):智能体执行行动(例如搜索信息)。
  • 观察(Observing):智能体检查行动所产生的结果。

这一循环会不断重复,直到智能体收集到足够信息来回答用户的问题。

为什么选择 LangGraph?

LangGraph 是在 LangChain 基础上构建的框架,可让我们将智能体的工作流程定义为 “图(graph)”。在此语境下,“图” 是一种数据结构,由 “节点(nodes)”(流程中的步骤)和 “边(edges)”(步骤间的路径)组成。图中的每个节点代表智能体流程中的一个步骤,边则定义了信息在步骤间的流转方式。

这种结构支持循环、条件分支等复杂流程。例如,智能体可在 “推理” 节点与 “行动” 节点之间循环,直到收集到足够信息。这一特性让复杂的智能体行为更易于理解和维护。

内容结构

我们将构建两个版本的 ReAct 智能体:

  1. 第一部分:构建简单的硬编码智能体,理解其核心机制。
  2. 第二部分:构建由大语言模型(LLM)驱动的智能体,实现动态决策。

第一部分:通过简单示例理解 ReAct

首先,我们将创建一个带有硬编码逻辑的基础 ReAct 智能体。无需涉及 LLM 集成的复杂操作,即可通过该示例理解 ReAct 循环的工作原理。

1. 状态(State)设置

每个 LangGraph 智能体都需要一个 “状态对象”,该对象会在图的各个节点间流转。这个状态相当于 “共享内存”,用于累积存储信息。节点会读取当前状态,添加自身产生的信息后,再将状态传递到下一个节点。

from langgraph.graph import StateGraph, END from typing import TypedDict, Annotated import operator # 定义在图中流转的状态 class AgentState(TypedDict): messages: Annotated[list, operator.add] # 存储所有思考、行动和观察记录,用operator.add实现列表拼接 next_action: str # 指示图的下一个执行节点 iterations: int # 记录推理循环的完成次数
核心组件说明:
  • StateGraph:LangGraph 中的核心类,用于定义智能体的工作流程。
  • AgentState:基于 TypedDict 定义的字典类,明确智能体需要跟踪的信息:
  • messages:通过operator.add实现列表元素的累积,存储智能体的思考过程、行动记录和观察结果。
  • next_action:指定图的下一个执行节点,实现流程路由。
  • iterations:统计推理循环的次数,避免无限循环。

2. 创建模拟工具(Mock Tool)

在真实的 ReAct 智能体中,“工具” 是指能在现实场景中执行行动的函数,例如网页搜索、数据库查询或 API 调用。本示例中,我们将使用一个简单的模拟搜索工具。

# 简单的模拟搜索工具 def search_tool(query: str) -> str: # 模拟搜索过程——实际使用时,此处会调用真实API responses = { "weather beijing": "北京天气:22°C,局部多云", "population china": "中国人口:约14亿" } # 若查询词不在预设响应中,返回“未找到结果”提示 return responses.get(query.lower(), f"未找到关于{query}的结果")

该函数通过硬编码的响应模拟搜索引擎功能。在实际生产环境中,此处可替换为调用百度、必应等真实搜索 API,或自定义的知识库接口。

3. 推理节点(Reasoning Node)——ReAct 的 “大脑”

推理节点是智能体思考 “下一步该做什么” 的核心模块。本示例采用硬编码逻辑实现,在第二部分会介绍如何通过 LLM 实现动态推理。

# 推理节点——决定下一步操作 def reasoning_node(state: AgentState): messages = state["messages"] # 获取当前累积的信息 iterations = state.get("iterations", 0) # 获取当前循环次数,默认值为0 # 简单逻辑:先搜索天气,再搜索人口,最后结束流程 if iterations == 0: return { "messages": ["思考:我需要查询北京的天气"], "next_action": "action", # 下一步执行“行动”节点 "iterations": iterations + 1 # 循环次数加1 } elif iterations == 1: return { "messages": ["思考:现在需要查询中国的人口"], "next_action": "action", "iterations": iterations + 1 } else: return { "messages": ["思考:我已收集到足够信息,可以回答用户问题"], "next_action": "end", # 下一步结束流程 "iterations": iterations + 1 }
工作原理:

推理节点通过分析当前状态,做出以下决策:

  • 是否需要继续收集信息?(返回"action",进入行动节点)
  • 是否已收集足够信息可以回答问题?(返回"end",结束流程)

注意,每次返回结果都会更新状态:

  1. 添加一条 “思考” 信息,解释决策依据;
  2. 设置next_action,指定下一个执行节点;
  3. 递增循环计数器,避免流程无限重复。

这一逻辑模拟了人类处理研究类任务的思路:“首先需要天气信息,然后需要人口数据,收集完这些就能回答问题了。”

这份完整版的大模型 AI 学习和面试资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

4. 行动节点(Action Node)—— 执行操作

当推理节点决定 “执行行动” 后,行动节点会执行选定的操作,并观察操作结果。

# 行动节点——执行工具调用 def action_node(state: AgentState): iterations = state["iterations"] # 获取当前循环次数 # 根据循环次数选择查询词 query = "weather beijing" if iterations == 1 else "population china" result = search_tool(query) # 调用模拟搜索工具,获取结果 return { "messages": [ f"行动:搜索关键词 '{query}'", f"观察:{result}" # 记录工具返回的结果 ], "next_action": "reasoning" # 下一步返回“推理”节点,继续循环 } # 路由函数——决定下一步执行的节点 def route(state: AgentState): return state["next_action"] # 直接返回next_action的值,作为路由依据
ReAct 循环的实际运行流程:
  1. 行动(Action):使用查询词调用search_tool,执行搜索操作;
  2. 观察(Observing):记录工具返回的搜索结果;
  3. 路由(Routing):将next_action设为"reasoning",回到推理节点继续循环。

路由函数是一个简单的辅助模块,通过读取next_action的值,告知 LangGraph 下一步该执行哪个节点。

5. 构建并执行图(Graph)

现在,我们将所有组件整合为一个 LangGraph 工作流程 —— 这是整个智能体实现的核心步骤!

# 构建图 workflow = StateGraph(AgentState) # 基于AgentState创建图实例 workflow.add_node("reasoning", reasoning_node) # 添加“推理”节点 workflow.add_node("action", action_node) # 添加“行动”节点 # 定义边(节点间的路径) workflow.set_entry_point("reasoning") # 设置“推理”节点为流程入口 # 为“推理”节点添加条件边:根据路由结果决定下一个节点 workflow.add_conditional_edges( "reasoning", # 起点节点:推理节点 route, # 路由函数:根据state["next_action"]决定路径 { "action": "action", # 若next_action为"action",则跳至行动节点 "end": END # 若next_action为"end",则结束流程(END为LangGraph内置常量) } ) # 为“行动”节点添加固定边:行动完成后,固定返回推理节点 workflow.add_edge("action", "reasoning") # 编译图并运行 app = workflow.compile() # 编译图,生成可执行的应用实例 # 调用应用,启动流程 result = app.invoke({ "messages": ["用户:告诉我关于北京和中国的信息"], # 初始用户输入 "iterations": 0, # 初始循环次数 "next_action": "" # 初始无下一步操作 }) # 打印整个对话流程 print("\n=== ReAct循环输出结果 ===") for msg in result["messages"]: print(msg)
图结构解析:
  1. 添加节点:将reasoning_nodeaction_node两个函数注册为图的节点;
  2. 设置入口:流程始终从 “推理” 节点开始;
  3. 添加条件边:基于推理节点的决策结果路由:
  • next_action == "action",则进入 “行动” 节点;
  • next_action == "end",则终止流程;
  1. 添加固定边:“行动” 节点执行完成后,固定返回 “推理” 节点,继续循环。

通过app.invoke()调用,即可启动整个 ReAct 流程。

输出结果:

=== ReAct循环输出结果 === 用户:告诉我关于北京和中国的信息 思考:我需要查询北京的天气 行动:搜索关键词 'weather beijing' 观察:北京天气:22°C,局部多云 思考:现在需要查询中国的人口 行动:搜索关键词 'population china' 观察:中国人口:约14亿 思考:我已收集到足够信息,可以回答用户问题

第二部分:基于大语言模型(LLM)的 ReAct 智能体

了解了基本原理后,我们来构建一个真正的 ReAct 智能体 —— 它将借助大语言模型做出智能决策。

为何使用大语言模型(LLM)?

硬编码版本的智能体虽然能运行,但灵活性极差 —— 它只能处理我们预先编程好的特定场景。而基于大语言模型的智能体则具备以下能力:

  • 理解不同类型的问题
  • 动态决定需要收集哪些信息
  • 根据已获取的知识调整推理过程

核心差异

我们不再使用硬编码的 if/else 逻辑,而是通过提示词引导大语言模型决定下一步操作。此时,大语言模型成为了智能体的 “推理引擎”。

1.搭建大语言模型环境

我们将使用deepseek作为推理引擎,当然也可以替换为其他任何大语言模型。

from langgraph.graph import StateGraph, END from typing import TypedDict, Annotated import operator import os from openai import OpenAI # 初始化deepseek客户端(从环境变量中获取API密钥) client = OpenAI(api_key=os.environ.get("deepseek_API_KEY"), base_url=os.environ.get("deepseek_url")) # 定义智能体状态类 class AgentStateLLM(TypedDict): messages: Annotated[list, operator.add] # 存储对话历史,支持列表拼接 next_action: str # 记录下一步操作("action"执行动作/"end"结束) iteration_count: int # 记录迭代次数(防止无限循环)

新状态定义说明

AgentStateLLM与第一部分中的AgentState结构完全一致 —— 仍需跟踪对话消息、操作指令和迭代次数,仅重命名以区分两个示例。

2.大语言模型工具:信息收集

不同于第一部分的模拟搜索,我们将直接让大语言模型利用自身知识库回答查询。这能直观展示如何将大语言模型转化为实用工具!

def llm_tool(query: str) -> str: """让大语言模型直接利用自身知识回答查询""" response = client.chat.completions.create( model="deepseek-chat", # 指定使用的模型 max_tokens=150, # 限制生成内容的最大 tokens 数 messages=[{"role": "user", "content": f"简要回答以下查询:{query}"}] # 构造用户查询 ) # 返回模型生成的内容(去除首尾空格) return response.choices[0].message.content.strip()

该函数通过API调用deepseek处理查询,大语言模型会返回事实性信息,供智能体后续推理使用。

3.基于大语言模型的推理:核心创新点

这是 ReAct 框架真正发挥优势的地方。我们不再依赖硬编码逻辑,而是通过提示词引导大语言模型决定下一步需要收集哪些信息。

def reasoning_node_llm(state: AgentStateLLM): # 获取当前迭代次数(默认从0开始) iteration_count = state.get("iteration_count", 0) # 迭代次数达到3次时停止,避免无限循环 if iteration_count >= 3: return { "messages": ["思考:我已收集足够信息"], "next_action": "end", # 标记为结束 "iteration_count": iteration_count } # 将对话历史拼接为字符串,供大语言模型参考 history = "\n".join(state["messages"]) # 构造提示词:明确大语言模型的任务、上下文和输出格式 prompt = f"""你是一个负责回答"介绍北京和中国"的AI智能体。 当前对话历史: {history} 已完成查询次数:{iteration_count}/3 你必须执行恰好3次查询以收集信息。 仅需按照以下格式回复:查询:<你的具体问题> 不要使用对话式语气,无需向用户致谢。仅输出:查询:<问题>""" # 调用大语言模型生成决策 decision = client.chat.completions.create( model="deepseek-chat", max_tokens=100, messages=[{"role": "user", "content": prompt}] ).choices[0].message.content.strip() # 若大语言模型返回符合格式的查询,标记下一步为"执行动作" if decision.startswith("查询:"): return { "messages": [f"思考:{decision}"], "next_action": "action", # 标记为执行动作 "iteration_count": iteration_count } # 若返回格式不符合要求,直接结束流程 return { "messages": [f"思考:{decision}"], "next_action": "end", "iteration_count": iteration_count }

该推理节点的工作原理

  1. 上下文构建:将对话历史传入提示词,确保大语言模型了解已收集的信息,避免重复查询。
  2. 结构化提示:明确要求大语言模型以 “查询:< 问题>” 格式输出,确保后续能被正确解析。
  3. 迭代控制:限制最大查询次数为 3 次,防止智能体陷入无限循环。
  4. 决策解析:检查大语言模型的输出是否符合预期格式,以此决定下一步是执行动作还是结束流程。

提示词策略解析

提示词向大语言模型明确了以下关键信息:

  • 核心任务:回答 “介绍北京和中国”
  • 上下文:已有的对话历史和查询进度
  • 约束条件:必须执行 3 次查询
  • 输出格式:仅需 “查询:< 问题>” 的结构化内容
  • 语气要求:避免对话式表达,保持简洁

大语言模型的训练目标是 “乐于助人且善于对话”,但在智能体工作流中,我们需要的是简洁、结构化的输出。上述提示词能有效引导模型聚焦任务本身。

4.执行动作节点

动作节点的逻辑与硬编码版本类似,但此时它会处理大语言模型动态生成的查询。

def action_node_llm(state: AgentStateLLM): # 获取推理节点生成的最后一条思考记录 last_thought = state["messages"][-1] # 提取查询内容(去除"思考:查询:"前缀) query = last_thought.replace("思考:查询:", "").strip() # 调用大语言模型工具执行查询,获取结果 result = llm_tool(query) # 返回更新后的状态:记录动作、观察结果,迭代次数+1,下一步返回推理节点 return { "messages": [f"动作:查询('{query}')", f"观察:{result}"], "next_action": "reasoning", # 下一步回到推理节点 "iteration_count": state.get("iteration_count", 0) + 1 # 迭代次数+1 }

动作执行流程

  1. 提取查询:从推理节点的输出中移除 “思考:查询:” 前缀,得到纯查询内容。
  2. 执行查询:调用llm_tool工具,让大语言模型生成查询结果。
  3. 记录状态:将 “执行的动作” 和 “观察到的结果” 存入对话历史,便于后续推理参考。
  4. 路由控制:将流程重新导向推理节点,进行下一轮决策。

相较于硬编码版本,该设计的灵活性显著提升 —— 智能体可自主决定查询任何它认为相关的信息!

5.构建基于大语言模型的工作流图

工作流图的结构与第一部分完全一致,核心差异在于:推理节点不再依赖硬编码规则,而是由大语言模型驱动决策。

# 初始化状态图(指定状态类型为AgentStateLLM) workflow_llm = StateGraph(AgentStateLLM) # 添加节点:推理节点和动作节点 workflow_llm.add_node("reasoning", reasoning_node_llm) # 推理节点 workflow_llm.add_node("action", action_node_llm) # 动作节点 # 设置入口节点:从推理节点开始 workflow_llm.set_entry_point("reasoning") # 添加推理节点的条件边:根据next_action决定路由 workflow_llm.add_conditional_edges( "reasoning", # 起点节点 lambda s: s["next_action"], # 路由判断依据:next_action的值 {"action": "action", "end": END} # 路由规则:"action"→动作节点,"end"→结束 ) # 添加动作节点的边:执行完动作后,回到推理节点 workflow_llm.add_edge("action", "reasoning") # 编译工作流图,生成可调用的应用 app_llm = workflow_llm.compile() # 调用应用,初始化状态(用户问题、空动作、0次迭代) result_llm = app_llm.invoke({ "messages": ["用户:介绍北京和中国"], "next_action": "", "iteration_count": 0 }) # 打印最终结果 print("\n=== 基于大语言模型的ReAct智能体(无模拟数据)===") for msg in result_llm["messages"]: print(msg)

与硬编码版本的差异

  • 工作流拓扑相同:仍为 “推理节点↔动作节点” 的循环结构,通过条件路由控制结束。
  • 状态管理方式相同:均通过messagesnext_actioniteration_count跟踪状态。
  • 核心差异:推理逻辑从 “if/else 硬编码” 替换为 “大语言模型提示词驱动”。

这充分体现了 LangGraph 的优势:我们可以在保持工作流结构不变的前提下,灵活替换核心组件!

输出结果示例

运行代码后,我们将看到智能体自主决定需要收集的信息。每一轮迭代都会展示以下内容:

  • 思考:大语言模型决定查询的问题
  • 动作:正在执行的查询操作
  • 观察:通过大语言模型工具获取的信息

观察大语言模型如何通过策略性查询,逐步构建完整的回答!

=== 基于大语言模型的ReAct智能体(无模拟数据)=== 用户:介绍北京和中国 思考:查询:北京在中国的历史地位和重要性是什么? 动作:查询('北京在中国的历史地位和重要性是什么?') 观察:北京是中国数朝古都、国家首都,兼具深厚历史文化底蕴与政治、文化、国际交往核心功能,是维系国家发展与民族认同的关键枢纽。 思考:查询:北京在中国的文化和经济有哪些主要贡献? 动作:查询('北京在中国的文化和经济有哪些主要贡献?') 观察:北京作为文化枢纽传承弘扬中华优秀传统文化、集聚优质文化资源引领文化创新,同时以总部经济、高端产业和科技创新赋能国家经济,助力区域协调发展与高质量增长。 思考:查询:中国整体有哪些关键的历史与文化特征? 动作:查询('中国整体有哪些关键的历史与文化特征?') 观察:中国拥有数千年延续未断的文明脉络、大一统的政治传统与多元一体的文化格局,以儒家思想为核心融合多民族智慧,沉淀出天人合一的哲学理念、崇德尚礼的价值追求与务实创新的发展基因。 思考:我已收集足够信息

总结

至此,我们已使用 LangGraph 构建了两个 ReAct 智能体:

  1. 基于硬编码逻辑的智能体:帮助理解 ReAct 的基本原理
  2. 基于大语言模型的智能体:具备动态决策能力,更贴近实际应用场景

核心启示:LangGraph 实现了 “工作流结构” 与 “驱动智能” 的解耦。第一部分与第二部分的工作流拓扑完全相同,但将硬编码逻辑替换为大语言模型推理后,原本僵化的脚本变成了具备自适应能力的智能体。

如何学习AI大模型?

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

这份完整版的大模型 AI 学习和面试资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

第一阶段:从大模型系统设计入手,讲解大模型的主要方法;

第二阶段:在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段:大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段:大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段:大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段:以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段:以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

👉学会后的收获:👈

• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/9 12:51:13

《从零开始学java篇》包装类

包装类&#xff1a;基本数据类型对应的引用数据类型&#xff0c;就是把基本数据类型变成了一个对象&#xff0c;对象当中记录对应的数据值&#xff08;用一个对象&#xff0c;把基本数据类型包起来&#xff09; int 的包装类 IntegerJDK5之前利用构造方法获取Integer对象 利用静…

作者头像 李华
网站建设 2026/5/1 10:58:36

10、Linux系统进程管理全解析

Linux系统进程管理全解析 1. 进程的定义 进程是正在执行的程序实例。与程序或命令不同的是,一个程序可以同时启动多个进程。每个进程会使用多种资源,具体如下: - 内存中的地址空间 - 具有一些安全属性,如所有权、权限等 - 拥有一个状态 - 具备本地和全局环境变量 - …

作者头像 李华
网站建设 2026/5/1 9:33:55

16、CentOS系统软件包管理与日志管理全解析

CentOS系统软件包管理与日志管理全解析 1. 第三方仓库与自定义仓库创建 1.1 第三方仓库 存在许多第三方仓库,但部分仓库可能未得到维护,还有些仓库存在包冲突问题。若想了解哪些仓库应避免使用,哪些值得推荐,可访问 CentOS 的相关维基页面: https://wiki.centos.org/A…

作者头像 李华
网站建设 2026/5/2 19:12:32

TikTok推荐算法怎么快速涨粉

在TikTok这个充满创意和活力的平台上&#xff0c;想要快速增加粉丝&#xff0c;就需要深入了解并巧妙利用其推荐算法。以下是一些实用的策略&#xff0c;帮助你在TikTok上迅速提升粉丝数量&#xff0c;提高视频的曝光率。 1. 内容质量与原创性 内容为王&#xff0c;在TikTok上尤…

作者头像 李华