第 1 章:LangGraph 框架概览

本笔记面向 AI 开发工程师、架构师及对 AI 智能体感兴趣的技术爱好者阅读。

    在构建复杂的智能体应用时,我们经常面临多轮对话、状态管理、工作流程控制等挑战。传统的线性处理方式往往难以胜任这些复杂场景。

    LangGraph 是基于 LangChain 生态的智能体框架,采用图架构设计,将智能体的工作流程抽象为由节点和边构成的有向循环图。这种架构为构建状态化、可循环的智能体系统提供了强大的支持。

    本章将通过手工构建 ReAct 智能体的完整示例,帮助您理解 LangGraph 的核心概念和实际应用。

LangGraph 简介

    LangGraph 的核心创新在于其采用了图架构来设计智能体的工作流程。这种架构与传统的线性流程或树状结构截然不同,LangGraph 将智能体执行任务的过程,抽象为一个由节点(Node)和边(Edge)构成的有向循环图(Directed Cyclic Graph)

🔧 核心组件

节点(Node)类型
  • • LLM 调用节点: 负责与大型语言模型进行交互,执行推理任务

  • • 工具调用节点: 允许智能体调用外部工具或 API,扩展能力边界

  • • 自定义函数节点: 封装业务逻辑或数据处理逻辑

  • • 子图节点: 提高代码模块化和可维护性

边(Edge)类型
  • • 普通边: 定义节点间的直接顺序执行关系

  • • 条件边: 根据状态动态决定工作流程走向

  • • 入口点: 定义工作流程的起始位置

  • • 条件入口点: 根据初始状态动态选择起始节点

状态(State)

状态是 LangGraph 的核心概念,扮演着多重角色:

  • • 上下文信息存储: 记录对话历史、任务进度等

  • • 节点间数据传递: 作为共享的数据容器

  • • 状态持久化: 支持记忆能力和容错恢复

  • • 多智能体共享: 实现智能体间协作

现在让我们通过实际代码来理解这些概念的应用。

🚀 环境准备

首先加载必要的环境变量配置:

from dotenv import load_dotenv

load_dotenv()

LangGraph 与 LangChain 的关系

在深入实践之前,让我们理解 LangGraph 与 LangChain 的关系。

核心架构差异

特性

LangChain (LCEL)

LangGraph

核心架构

链式,有向无环图 (DAG)

图架构,有向循环图 (DCG)

设计理念

简化 LLM 应用开发,线性流程

构建复杂、状态化的智能体系统

状态管理

相对简单,短期记忆

强大的状态管理和持久化机制

工作流程

线性或分支流程,相对固定

循环流程,支持迭代和动态分支

适用场景

简单应用,快速原型开发

复杂智能体,多智能体系统

协同使用策略

最佳实践是将 LangChain 作为 LangGraph 的“组件库”:

  • • 利用 LangChain 的模型、提示、工具等组件

  • • 在 LangGraph 中组织和编排这些组件

  • • 构建更复杂的工作流程和智能体系统

现在让我们实际构建一个展示这些概念的 ReAct 智能体。

基于 LangGraph 实现 ReAct 模式

    

Graph view in LangGraph studio UI

    为了帮助大家深入理解 LangGraph 框架的图构建过程,并掌握如何从零开始搭建智能体工作流程,我们将通过手工构建图的方式来实现一个工具调用型的 ReAct 模式智能体。

    我们将使用 OpenAI 兼容的模型作为示例,构建一个能够使用搜索工具查询天气信息的智能体。与预制 API 不同,这次我们从最基础的 LangGraph 组件开始,一步步构建 ReAct 智能体的工作流程图。

示例 1:定义工具和工具节点

    首先导入必要的 LangGraph 和 LangChain 组件,并定义智能体可以使用的工具。

from langchain_openai import ChatOpenAI  # 导入 ChatOpenAI,用于使用 OpenAI 的模型
from langchain_core.tools import tool  # 导入 tool 装饰器,用于定义工具
from langgraph.graph import END, StateGraph, MessagesState  # 导入 LangGraph 图构建核心组件:END, StateGraph, MessagesState
from langgraph.prebuilt import ToolNode  # 导入 ToolNode,用于封装工具节点

# 定义工具:search,用于模拟网页搜索,查询天气信息 (与之前的示例相同)
@tool
def search(query: str):
    """Call to surf the web."""
    # 这是一个占位符工具,实际应用中需要替换为真正的搜索功能
    if "sf" in query.lower() or "san francisco" in query.lower():
        return "It's 60 degrees and foggy."
    return "It's 90 degrees and sunny."

tools = [search] # 将 search 工具放入工具列表
tool_node = ToolNode(tools) # 创建 ToolNode 实例,将工具列表封装成 LangGraph 节点

💡 核心概念解析

    在这段代码中,我们定义了 search 工具,并使用 ToolNode 将工具列表封装成一个 LangGraph 节点。

  • • @tool 装饰器:将普通 Python 函数转换为 LangChain 工具

  • • ToolNode:LangGraph 预置的节点类型,专门用于执行工具调用

  • • 工具的 docstring 作为工具描述提供给 LLM,帮助模型理解何时使用工具

示例 2:初始化模型并绑定工具

初始化语言模型,并将其配置为能够调用工具。

# 初始化语言模型,使用 Qwen/Qwen3-8B 模型,并绑定工具
model = ChatOpenAI(model="Qwen/Qwen3-8B", temperature=0).bind_tools(tools)

💡 关键概念

bind_tools(tools) 方法至关重要。它将我们定义的工具列表绑定到 ChatOpenAI 模型上,使得模型知道它有哪些工具可以使用,以及如何调用这些工具。只有绑定了工具的模型,才能在后续的推理过程中生成工具调用指令。

示例 3:创建状态结构体

创建 StateGraph 实例,指定状态类型。

# 定义状态类型为 MessageState,用于处理消息列表
workflow = StateGraph(MessagesState)

💡 StateGraph 核心概念

  • • StateGraph:LangGraph 中用于构建和管理图的核心类

  • • MessagesState:LangGraph 预置的状态类型,专门用于处理消息列表,非常适合构建对话型智能体

  • • 状态作为"记忆库",用于存储和传递信息,在不同节点间共享数据

示例 4 & 5:添加节点

向图中添加两个核心节点:

  1. 1. "agent" 节点:负责调用语言模型进行推理

  2. 2. "tools" 节点:负责执行工具调用

# 定义 agent 节点的执行函数:call_model
def call_model(state):
    messages = state['messages'] # 从状态中获取消息列表
    response = model.invoke(messages) # 调用语言模型 model 进行推理,输入为消息列表
    return {"messages": [response]} # 将模型响应消息封装成字典返回,键为 "messages",值为包含响应消息的列表

# 将 call_model 函数添加到图中,并命名为 "agent" 节点
workflow.add_node("agent", call_model)

# 将之前创建的 tool_node 实例添加到图中,并命名为 "tools" 节点
workflow.add_node("tools", tool_node)

💡 节点设计原理

  • • call_model 函数:节点的执行函数,接收状态作为输入,返回状态更新

  • • 返回格式:必须是字典形式 {"messages": [response]},用于更新 LangGraph 状态

  • • 双节点架构:Agent 负责推理决策,Tools 负责行动执行,形成 ReAct 循环的基础

示例 6:设置图的入口点

定义工作流程的起始节点。

# 设置图的入口点为 "agent" 节点,表示工作流程从 agent 节点开始执行
workflow.set_entry_point("agent")
示例 7:定义条件判断函数

定义条件判断逻辑,这是 ReAct 模式的核心:根据模型输出决定下一步行动。

# 定义条件判断函数:should_continue,决定下一步执行哪个节点
def should_continue(state):
    messages = state['messages'] # 从状态中获取消息列表
    last_message = messages[-1] # 获取最后一条消息,即 agent 节点的输出消息
    # 如果 agent 节点的输出消息中包含工具调用指令,则流向 "tools" 节点
    if last_message.tool_calls:
        return "tools"
    # 否则,工作流程结束,流向 END
    return END

💡 条件路由机制

should_continue 函数实现了 ReAct 的核心决策逻辑:

  • • 检查最后一条消息是否包含 tool_calls

  • • 如果有工具调用,返回 "tools"(继续行动)

  • • 否则返回 END(推理完成,结束流程)

  • • END 是 LangGraph 预定义的特殊值,表示工作流程终点

示例 8:添加条件边

添加从 agent 节点出发的条件边,根据条件函数的返回值决定流向。

# 添加条件边:从 "agent" 节点出发,根据 should_continue 函数的返回值,决定流向 "tools" 节点或 END
workflow.add_conditional_edges(
    "agent", # 起始节点为 "agent" 节点
    should_continue # 条件判断函数为 should_continue
)
示例 9:添加普通边

添加固定的返回路径,从 tools 节点总是返回到 agent 节点。

# 添加普通边:从 "tools" 节点到 "agent" 节点,表示工具调用完成后,总是返回 agent 节点继续推理
workflow.add_edge("tools", 'agent')

💡 边的类型和 ReAct 循环

  • • 条件边add_conditional_edges() 实现动态路由,根据运行时状态选择路径

  • • 普通边add_edge() 创建固定连接,工具执行后总是返回 agent

  • • ReAct 循环:这种设计形成了"推理 → 行动 → 推理 → ..."的循环模式

  • • 有向循环图:与传统 DAG 不同,支持循环结构,实现迭代推理

示例 10:编译 LangGraph 图

将构建好的图编译为可执行的 Runnable 对象。

# 编译 LangGraph 图,得到可执行的 app 对象
app = workflow.compile()
示例 11:运行 ReAct 智能体并处理用户查询

测试我们构建的 ReAct 智能体,向其发送用户查询。

# 运行智能体应用 app,处理用户查询 "What is the weather in sf" (旧金山天气)
final_state = app.invoke({"messages": [{"role": "user", "content": "what is the weather in sf"}]})
# 打印智能体的最后一条回复消息的内容
print(final_state["messages"][-1].content)

🔄 LangGraph 执行流程深度解析

让我们深入分析当运行 app.invoke() 方法时,LangGraph 内部的执行机制:

完整执行步骤

  1. 初始化阶段

    • • LangGraph 将输入消息添加到内部状态

    • • 状态传递给入口点节点 "agent"

  2. Agent 节点执行

    • • call_model 函数被调用,接收当前状态

    • • 从状态中提取消息列表,传递给语言模型

    • • 模型分析问题,识别需要获取天气信息

    • • 生成包含工具调用指令的 AIMessage

  3. 条件判断阶段

    • • should_continue 函数检查最后一条消息

    • • 发现 tool_calls 存在,返回 "tools"

    • • 工作流程路由到 Tools 节点

  4. Tools 节点执行

    • • ToolNode 解析工具调用指令

    • • 执行 search("weather in sf") 函数

    • • 返回结果:"It's 60 degrees and foggy."

    • • 工具结果被添加到状态中

  5. 循环返回 Agent

    • • 根据普通边,流程返回 Agent 节点

    • • Agent 接收包含工具结果的完整对话历史

    • • 模型基于工具结果生成最终回答

  6. 流程结束

    • • 最终回答不包含工具调用

    • • should_continue 返回 END

    • • 工作流程完成,返回最终状态

ReAct 模式的核心优势

这种设计体现了 LangGraph 相比传统线性流程的关键优势:

  • • 动态决策:根据运行时状态动态选择执行路径

  • • 状态持久化:完整的对话历史在整个流程中保持可用

  • • 循环支持:支持多轮推理-行动循环,直到问题解决

  • • 灵活扩展:易于添加新的工具、节点或修改流程逻辑

📚 本章总结

    通过本章的学习,我们深入了解了 LangGraph 框架的核心理念和实际应用。LangGraph 采用有向循环图架构,通过节点、边和状态三个核心组件构建智能体工作流程,相比传统线性流程具有更强的灵活性和表达能力。我们通过手工构建 ReAct 智能体的完整示例,掌握了状态管理、条件路由、循环结构等关键技术,为构建复杂的对话系统、决策型智能体和多智能体协作系统奠定了基础。
    在下一章中,我们将深入探讨 LangGraph 的图驱动智能体系统,学习更高级的状态管理和复杂流程控制技巧。

参考文献和资料
  • • LangGraph文档:https://docs.langchain.com/oss/python/langgraph/overview

  • • 《LangGraph实战》

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐