前言

在过去的一年里,LangChain 几乎成为了 LLM(大语言模型)应用开发的代名词。它通过“链(Chain)”的概念,成功地将 Prompt、模型和输出解析器串联起来,极大地降低了开发 RAG(检索增强生成)和基础应用的门槛。

然而,随着应用场景的深入,开发者们发现了一个问题:真实的业务逻辑往往不是线性的。我们需要循环、需要重试、需要根据上一步的结果动态决定下一步的操作——简而言之,我们需要构建Agent(智能体)

这时候,LangGraph 应运而生。本文将深入浅出地讲解 LangChain 与 LangGraph 的核心区别,并通过实战代码展示如何利用 LangGraph 构建一个具备状态管理的智能 Agent。


一、 LangChain:线性的流水线大师

1.1 什么是 LangChain?

LangChain 本质上是一个编排工具。它的核心理念是将 LLM 开发中的各个组件(Component)模块化,然后通过“链”将它们连接起来。

最经典的模式是 LCEL(LangChain Expression Language):



chain = prompt | model | output_parser

这种架构非常适合 DAG(有向无环图) 的场景。例如:

  1. 用户输入问题。
  2. 检索向量数据库。
  3. 将检索结果和问题填入 Prompt。
  4. LLM 生成答案。

1.2 LangChain 的局限性

虽然 LangChain 也有 AgentExecutor,但在处理复杂逻辑时显得力不从心:

  • 缺乏循环能力:标准的 Chain 是单向流动的,很难实现“思考 -> 行动 -> 观察 -> 再思考”的循环,除非使用非常复杂的递归。
  • 状态管理黑盒AgentExecutor 封装太深,开发者很难精细控制中间的状态(State)。
  • 定制难:如果你想让 Agent 在某个特定步骤强制人工介入(Human-in-the-loop),或者根据特定条件回滚,传统的 LangChain 实现起来非常痛苦。

二、 LangGraph:为 Agent 而生的状态机

2.1 什么是 LangGraph?

LangGraph 是 LangChain 团队推出的一个扩展库。它的核心观点是:Agent 的本质是一个图(Graph),而不是一条链。

更具体地说,LangGraph 允许我们在图中定义循环(Cycles)。这对于 Agent 来说至关重要,因为 Agent 需要不断地循环执行“调用工具 -> 获取结果 -> 再次决策”的过程,直到任务完成。

2.2 LangGraph 的核心概念

理解 LangGraph 只需要掌握三个要素:

  1. State(状态)
    • 这是图的“共享内存”。
    • 所有节点(Nodes)都可以读取和写入这个状态。
    • 它的结构通常是一个 TypedDict 或 Pydantic 模型。
  1. Nodes(节点)
    • 图中的执行单元。
    • 比如:一个节点负责调用 LLM,另一个节点负责执行 Python 代码。
    • 每个节点接收当前的 State,执行逻辑,然后返回更新后的 State。
  1. Edges(边)
    • 定义控制流。
    • 普通边:从 A 节点直接流向 B 节点。
    • 条件边(Conditional Edges):根据上一个节点的输出,动态决定去往哪个节点(这是实现 If-Else 逻辑的关键)。

三、 实战对比:LangChain vs LangGraph

如果我们要解释两者的区别,用图表最直观:

特性

LangChain (LCEL)

LangGraph

架构模型

DAG (有向无环图)

Cyclic Graph (有环图)

核心隐喻

流水线 (Pipeline)

状态机 (State Machine)

控制流

线性、预定义

动态、可循环

适用场景

简单的 RAG、聊天机器人、单次调用

复杂 Agent、多步推理、Human-in-the-loop

状态管理

通过参数隐式传递

显式定义的全局 Schema


四、 代码实战:构建一个简单的 ReAct Agent

下面我们用 LangGraph 构建一个具备搜索能力的 Agent。注意看它是如何通过图来管理循环的。

4.1 环境准备

pip install langchain langchain-openai langgraph

4.2 定义状态 (State)

首先,我们需要定义在这个图中流转的数据结构。通常我们需要保留消息历史。

from typing import TypedDict, Annotated, Sequence
import operator
from langchain_core.messages import BaseMessage

class AgentState(TypedDict):
    # Annotated[list, operator.add] 意思是:
    # 当新消息产生时,不要覆盖旧消息,而是追加(add)到列表中
    messages: Annotated[Sequence[BaseMessage], operator.add]

4.3 定义节点 (Nodes)

我们需要两个节点:一个是“大脑”(LLM),一个是“手”(工具执行)。

from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
from langgraph.prebuilt import ToolNode

# 1. 准备工具
tools = [TavilySearchResults(max_results=1)]
tool_node = ToolNode(tools)

# 2. 准备模型并绑定工具
model = ChatOpenAI(model="gpt-4o")
model_with_tools = model.bind_tools(tools)

# 3. 定义调用模型的节点函数
def call_model(state):
    messages = state['messages']
    response = model_with_tools.invoke(messages)
    # 返回的内容会通过 operator.add 更新到 State 中
    return {"messages": [response]}

4.4 定义边与图的构建 (The Graph)

这是 LangGraph 最精彩的部分。

from langgraph.graph import StateGraph, END

# 初始化图
workflow = StateGraph(AgentState)

# 添加节点
workflow.add_node("agent", call_model)
workflow.add_node("tools", tool_node)

# 设置入口点
workflow.set_entry_point("agent")

# 定义条件边:决定是继续调用工具,还是结束
def should_continue(state):
    messages = state['messages']
    last_message = messages[-1]
    
    # 如果 LLM 返回了 tool_calls,说明它想用工具 -> 转到 tools 节点
    if last_message.tool_calls:
        return "tools"
    # 否则 -> 结束
    return END

# 添加条件边
workflow.add_conditional_edges(
    "agent",
    should_continue,
    {
        "tools": "tools",
        END: END
    }
)

# 添加普通边:工具执行完后,必须把结果扔回给 Agent 重新思考
workflow.add_edge("tools", "agent")

# 编译图
app = workflow.compile()

4.5 运行与可视化

from langchain_core.messages import HumanMessage

inputs = {"messages": [HumanMessage(content="现在旧金山的天气怎么样?")]}

for output in app.stream(inputs):
    # 实时打印每个节点的输出
    for key, value in output.items():
        print(f"Node '{key}':")
        print(value)
        print("----")

运行逻辑解析:

  1. 进入 agent 节点,LLM 判断需要查询天气。
  2. should_continue 检测到工具调用,路由到 tools 节点。
  3. tools 节点执行搜索,获取天气数据。
  4. 普通边强制流回 agent 节点(这就是循环!)。
  5. agent 节点接收到工具结果,生成最终自然语言回复。
  6. should_continue 检测到没有新工具调用,路由到 END

五、 总结

LangChain 并没有过时,它依然是构建 LLM 应用最基础的积木(Prompt 模板、模型接口、向量库接口依然沿用 LangChain 的生态)。

但是,当你需要构建复杂的、自主决策的系统时,请务必拥抱 LangGraph

  • LangChain 负责“连接”。
  • LangGraph 负责“循环”和“控制”。

掌握 LangGraph,你就掌握了构建下一代 Agent 的钥匙。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐