[控场AI]
· 10 分钟阅读· 5,047 字

LangGraph 与 LangChain 有什么区别?一文讲透

LangGraph 与 LangChain 有什么区别?一文讲透

LangChain 是高层 Agent 组件库,LangGraph 是底层有状态编排运行时,二者层级不同、配合使用。

文章厘清了 LangChain 与 LangGraph 的关系:前者是提供开箱即用 Agent 的高层组件库,控制流由模型在 Agent 循环中自行决定,适合助手、RAG 链与简单工具调用;后者是面向有状态工作流的底层编排运行时,节点、边、条件路由、循环全部由开发者显式定义,状态类型和持久化策略也完全可控。LangChain 的 Agent 实际运行在 LangGraph 之上,其持久化能力也来自后者。LangGraph 的核心价值在于 checkpointer 持久化与 interrupt() 暂停/恢复,使长周期、需人工审批的业务流程可靠运行。作者建议先学 LangChain 打基础,再进阶 LangGraph 掌握状态与控制,并按场景选择工具。

一句话结论: LangChain 提供高层组件和一个开箱即用的 Agent;LangGraph 则是面向有状态、可控工作流的底层编排运行时。LangChain 的 Agent 本质上就跑在 LangGraph 之上。

两者不是替代关系,而是抽象层级不同的两套工具。理解这一点,才能决定什么时候用哪个。

LangGraph 与 LangChain 对比

LangChain:几行代码搞定工具调用 Agent

LangChain 的定位是「高层组件库」。你定义工具、选好模型、写一段系统提示词,剩下的交给 Agent 循环——模型自己决定调用哪个工具、什么时候停止。

原文给出的示例非常直观:定义一个查询保单额度的工具,用 create_agent 组装 Agent,然后一次 invoke 就能拿到结果。

from langchain.agents import create_agent
from langchain.tools import tool

@tool
def get_policy_limit(policy_id: str) -> str:
    """Return the claim limit for a policy."""
    return "Limit for " + policy_id + " is ₹5,00,000"

agent = create_agent(
    model="openai:gpt-4.1-mini",
    tools=[get_policy_limit],
    system_prompt="You are a helpful insurance assistant.",
)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "What is the limit on policy P-1029?"}]}
)
print(result["messages"][-1].content)

这段代码的控制流完全由模型驱动。适合什么场景?助手类应用、RAG 链、简单的工具调用。你不需要关心状态怎么存、分支怎么走,LangChain 都替你封装好了。

LangGraph:每一步都由你掌控

当业务逻辑变复杂——需要条件分支、人工审批、断点续跑——LangChain 的 Agent 循环就不够用了。LangGraph 把控制权交还给你:节点、边、条件路由、循环,全部显式定义。

原文用了一个理赔工作流的例子:先评估理赔金额,根据金额大小路由到人工审核或自动批准,大额理赔通过 interrupt() 暂停等待人工确认。

from typing import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.types import interrupt, Command

class ClaimState(TypedDict):
    claim_text: str
    amount: float
    approved: bool

def assess(state: ClaimState):
    return {"amount": 75000.0}

def route(state: ClaimState) -> str:
    return "human_review" if state["amount"] > 50000 else "auto_approve"

def human_review(state: ClaimState):
    decision = interrupt({"question": "Approve this claim?", "amount": state["amount"]})
    return {"approved": decision == "yes"}

def auto_approve(state: ClaimState):
    return {"approved": True}

builder = StateGraph(ClaimState)
builder.add_node("assess", assess)
builder.add_node("human_review", human_review)
builder.add_node("auto_approve", auto_approve)
builder.add_edge(START, "assess")
builder.add_conditional_edges("assess", route, ["human_review", "auto_approve"])
builder.add_edge("human_review", END)
builder.add_edge("auto_approve", END)

graph = builder.compile(checkpointer=InMemorySaver())
config = {"configurable": {"thread_id": "claim-42"}}

graph.invoke({"claim_text": "Hospital bill..."}, config)   # 在 human_review 处暂停
graph.invoke(Command(resume="yes"), config)                 # 审批后恢复
graph.invoke(Command(resume="yes"), config)

注意最后两行:第一次 invoke 执行到 human_review 节点时暂停,第二次用 Command(resume="yes") 恢复执行。这种「暂停—恢复」的能力依赖 checkpoint 机制。原文特别指出,生产环境中要把 InMemorySaver 换成 Postgres checkpointer,这样工作流在服务重启后依然能恢复。

这是 LangGraph 的核心价值:持久化状态 + 可中断执行,让长周期、有人参与的业务流程能够可靠运行。

checkpoint / checkpointer 机制:LangGraph 的 checkpointer 会在每个节点执行后把当前状态快照持久化下来,附带一个 thread_id 作为会话标识。这一机制带来三件事:一是断点续跑,进程崩溃或服务重启后可从最后一个快照恢复;二是人工介入,interrupt() 本质上就是保存快照后抛出暂停信号,恢复时用 Command(resume=...) 把人工输入作为节点返回值注入;三是可回溯与时间旅行,理论上可以读取历史某个时刻的状态重新执行。InMemorySaver 只把快照存在进程内存里,重启即丢失,仅适合本地调试;生产环境应换成 PostgresSaver 等持久化后端,并注意状态对象需可序列化。

TypedDict 与类型化状态:LangGraph 用 Python 的 TypedDict 声明图的共享状态结构,每个节点函数接收完整状态、返回一个「增量字典」,LangGraph 按字段做合并更新。这意味着状态的字段完全由业务定义(如 claim_text、amount、approved),而不是像 LangChain 那样固定为消息列表。对于需要累加而非覆盖的字段(例如消息历史、日志列表),可以用 Annotated 配合 operator.add 等 reducer 指定合并策略,这是构建多轮、多 Agent 状态时的关键细节。

核心差异对照

原文用一张表格清晰地对比了两者:

维度LangChainLangGraph
层级高层组件与 Agent底层编排运行时
控制流模型决定(Agent 循环)你定义节点、边、分支、循环
状态消息列表任意自定义类型化状态
持久化底层依赖 LangGraph内置 checkpointer
人工介入通过中间件图中任意位置 interrupt()
适用场景助手、RAG 链、简单工具调用业务工作流、多 Agent 系统、长任务

几个关键点值得展开:

状态设计自由度的差异。 LangChain 的状态基本就是消息历史,结构固定;LangGraph 允许你定义任意 TypedDict 作为状态,字段完全由业务决定。

人工介入的实现方式。 LangChain 需要通过中间件来插入人工审核环节,而 LangGraph 可以在图的任何位置调用 interrupt(),粒度更细、更自然。

持久化的归属。 LangChain 的持久化能力实际上来自底层的 LangGraph,而 LangGraph 原生就带 checkpointer。这也再次印证了两者的层级关系。

「中间件」式人工介入:表格中提到 LangChain 通过中间件(middleware)实现人工介入,指的是在 Agent 循环的工具调用前后挂载钩子函数,拦截特定工具的执行并请求人工确认。这种方式粒度较粗,只能在工具调用边界处拦截,且难以表达「暂停数小时后由另一个人恢复」这类跨请求的长周期等待。LangGraph 的 interrupt() 则把暂停点作为图的一部分显式建模,配合 checkpointer 天然支持跨进程、跨时间的恢复,因此更适合审批流、表单补全等真实业务场景。

Agent 循环(Agent Loop):LangChain 中 create_agent 生成的 Agent 本质上是一个「推理—调用工具—观察结果—再推理」的循环,直到模型认为无需再调用工具时终止。循环的每一步在哪停、调用哪个工具,全由模型输出决定,开发者无法在不修改提示词或工具集的前提下插入确定性逻辑。这正是它在复杂分支、需人工把关场景下受限的根本原因,也是理解两套工具分界线的关键。

应该先学哪个?

原文的建议很明确:先学 LangChain,再学 LangGraph。

原因在于 LangChain 覆盖了最基础的概念——模型调用、提示词、结构化输出、工具定义。这些是任何 Agent 系统的地基。跳过这一步直接上手 LangGraph,容易陷入状态机和图结构的细节里,反而看不清 Agent 的整体逻辑。

等基础打牢之后,再学 LangGraph 就有意义了。原文的判断是:任何严肃的 Agent 系统最终都需要状态和控制,所以 LangGraph 是进阶路上绕不开的一环。

这个学习路径也被实践验证过——原文提到 TechSimPlus 与 Prateek Mishra 的 Gen-AI 开发者课程 Vector 2.0 就是按这个顺序设计的:Sprint 1 讲 LangChain,Sprint 3 用 ClaimSense 项目讲 LangGraph,Sprint 4 再引入 MCP 和 A2A 的多 Agent 系统。

对于开发者来说,选择哪个工具不取决于哪个「更好」,而取决于你的场景需要多少控制力。简单助手用 LangChain 快速交付,复杂业务流程用 LangGraph 精细编排,两者配合使用才是完整方案。

#LangGraph#LangChain#LangGraph vs LangChain#AI Agent 框架#LLM 工作流编排#有状态工作流#human-in-the-loop
分享:

相关推荐