三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

LangChain与LangGraph:大模型应用开发中的链与图架构解析

LangChain与LangGraph:大模型应用开发中的链与图架构解析

如果你刚开始接触大语言模型应用开发,大概率会同时遇到 LangChain 和 LangGraph 这两个名字。它们都带着“Lang”前缀,都出现在各种教程和项目里,甚至很多文章会把它们混在一起讲。这很容易让人困惑:它们到底是一个东西的两个部分,还是两个完全不同的工具?我应该先学哪个?我的项目到底该用哪个?

这种困惑非常普遍,但背后的原因其实很简单:LangChain 和 LangGraph 解决的是大模型应用开发中两个不同层级、但又紧密相关的问题。一个帮你“组装”静态的、线性的任务链,另一个帮你“编排”动态的、有状态的、可能循环的工作流。理解这个核心区别,远比记住一堆 API 调用更重要。

今天,我们就用最直白的方式,帮你理清 LangChain 和 LangGraph 的从属关系、核心区别以及各自的适用场景。无论你是零基础的新手,还是已经用过 LangChain 但对 LangGraph 感到好奇的开发者,这篇文章都会给你一个清晰的路线图。

1. 先搞明白它们各自的“本职工作”:组装零件 vs. 设计流水线

要理解关系,首先要抛开名字,看看它们各自被设计出来是干什么的。

LangChain 的核心是“链”(Chain)。你可以把它想象成一个高级的“胶水”或者“组装工具箱”。大模型本身就像一个功能强大但有点“傻”的万能工人,它很能干,但不知道先干什么后干什么,也不知道怎么跟数据库、搜索引擎、计算器这些专业工具配合。

LangChain 的作用,就是帮你定义好一套固定的工作流程(也就是“链”),告诉这个工人:“你先去数据库查资料(Retrieval),然后把查到的资料和用户问题一起给我(Combining),我再根据这些信息生成最终答案(Generation)。” 这个过程通常是线性的、一步接一步的,像一个预设好的剧本。它的重点是把不同的模块(模型、工具、记忆、数据源)连接成一个可执行的、端到端的应用程序

LangGraph 的核心是“图”(Graph)。它解决的是一个更复杂的问题:当你的工作流程不是一条直线,而是一个需要根据中间结果动态决定下一步怎么走的网络时,该怎么办?比如,一个客服机器人需要根据用户情绪决定是安抚还是转接;一个数据分析任务需要循环执行“查询-判断-再查询”直到满足条件;一个游戏NPC需要根据对话历史和当前状态选择不同的行为分支。

LangGraph 允许你定义多个“节点”(Node),每个节点执行特定任务(比如调用模型、运行工具、更新状态),然后用“边”(Edge)来定义节点之间的流转规则。最关键的是,流转规则可以基于上一个节点的执行结果来动态决定,这就形成了“有状态”的、可能包含循环或条件分支的工作流。它更像是在设计一个智能流水线或一个决策流程图。

所以,最形象的比喻是:LangChain 帮你把螺丝刀、扳手、电钻(各种工具)组装成一个好用的“多功能螺丝刀”(一个链);而 LangGraph 则帮你设计一整条汽车装配流水线,这条线上有多个工位(节点),并且能根据上一道工序的结果,动态决定下一辆车是送去喷漆还是直接检测(有条件的工作流)。

2. 理清从属关系:LangGraph 是 LangChain 生态中的“高级模块”

从项目归属上看,关系非常明确:LangGraph 是 LangChain 项目旗下的一个库。你可以认为 LangChain 是一个“全家桶”,里面包含了很多子工具:

  • langchain-core: 基础抽象和接口。
  • langchain: 主库,包含了大量的链(Chains)、代理(Agents)、检索器(Retrievers)等核心组件。
  • langgraph: 专门用于构建有状态、多参与者的工作流图。
  • 还有其他如langchain-community(社区贡献集成)、langchain-text-splitters(文本处理)等。

因此,在安装时,你通常会:

pip install langchain langgraph

技术上的从属与互补

  1. 基础依赖:LangGraph 构建在 LangChain 的核心抽象之上。一个 LangGraph 的节点(Node),其内部完全可以执行一个 LangChain 的链(Chain)或者调用一个 LangChain 的工具(Tool)。也就是说,LangGraph 用 LangChain 的“零件”来构建更复杂的“机器”。
  2. 功能演进:在 LangGraph 出现之前,LangChain 用“代理”(Agent)来模拟一些简单的动态决策。但代理的复杂逻辑隐藏在内部,难以定制和可视化。LangGraph 可以看作是对“代理”模式的一种显式化、模块化和增强化的实现。它把代理内部隐式的决策逻辑,变成了外部可清晰定义和调试的图结构。
  3. 使用场景:对于简单的、线性的任务,直接用 LangChain 的链就足够了。只有当你需要处理复杂的、有状态的、带循环或分支的逻辑时,才需要请出 LangGraph。

简单来说:LangChain 提供了构建智能应用的基础积木和简单组合方式(链);而 LangGraph 提供了用这些积木搭建复杂、动态系统的蓝图和引擎(图)。

3. 核心区别对比:一张表看清何时该用谁

光说概念可能还是有点模糊,我们通过一个具体的对比表格,从多个维度来看它们的区别:

特性维度LangChain (链)LangGraph (图)
核心抽象链 (Chain):将多个组件按固定顺序连接。图 (Graph):由节点(Node)和边(Edge)组成,支持条件流转。
工作流状态无状态 (Stateless):每次调用独立,不自动保留中间状态(需额外配置记忆)。有状态 (Stateful):内置状态管理,在整个图执行过程中传递和更新上下文。
执行流程线性/定向:A -> B -> C,像执行一个函数。动态/条件性:根据节点结果,决定下一步走X、Y还是Z,甚至循环回到A。
复杂度相对简单:适合定义明确、步骤固定的任务。相对复杂:适合需要决策、循环、多分支的复杂场景。
可视化较难直观展示链的内部步骤。原生支持可视化,可以将整个工作流图渲染出来,便于理解和调试。
典型应用- 问答链(检索后生成)
- 文档总结链
- 简单数据提取链
- 复杂对话机器人(带状态和分支)
- 多步骤决策系统
- 循环执行直到满足条件的数据处理
- 模拟仿真(如游戏NPC)
学习曲线较低:概念直观,易于上手构建简单应用。较高:需要理解图、节点、边、状态管理等概念。
与代理关系包含“代理”作为实现动态性的一种(但较黑盒)。可视为“代理”的显式、可定制化实现。甚至可以用 LangGraph 来构建更强大的自定义代理。

一个更具体的例子:客服对话系统

  • 用 LangChain:你可以构建一个“检索增强生成(RAG)链”。用户提问 -> 检索知识库 -> 生成回答。这个流程每次都是固定的。
  • 用 LangGraph:你可以构建一个完整的对话流程。用户提问 -> 节点A(意图识别)-> 根据意图,边决定路由:如果是“查询”,走到节点B(RAG链);如果是“投诉”,走到节点C(安抚并记录工单);如果是“闲聊”,走到节点D(闲聊模式)。节点C执行后,可能还会根据用户情绪,边决定是否循环回节点A(继续安抚)或走到结束节点。整个对话的历史和状态(比如用户是否已生气)都在图中被维护和传递。

4. 零基础上手路径:从链到图,一步步来

如果你是完全的新手,按照以下路径学习,可以避免很多困惑:

第一步:先用 LangChain 搞定“单次任务”不要一开始就想着复杂的工作流。你的第一个目标应该是:

  1. 环境搭建:安装langchain和你的大模型API包(如openai)。
  2. Hello World:学会用ChatModel发起一次最简单的对话。
  3. 构建第一个链:尝试一个经典的LCEL(LangChain Expression Language)链,比如:prompt | model | output_parser。感受一下如何把提示词、模型调用和输出解析串起来。
  4. 引入工具:尝试让链调用一个简单的工具,比如计算器或者网络搜索(需要配置API)。
  5. 尝试代理:用 LangChain 内置的create_react_agent体验一下代理如何自动选择工具。这时你会初步感受到“动态性”。

关键体会:在这一步,你要理解PromptTemplateLLMToolChain这些核心组件是如何通过 LCEL 的管道符 (|) 组合在一起的。这是所有后续工作的基础。

第二步:当链不够用时,认识 LangGraph当你发现你的需求开始出现以下信号时,就该考虑 LangGraph 了:

  • “如果……那么……”:需要根据模型或工具的输出来决定下一步做什么。
  • “重复直到……”:需要循环执行某些步骤,直到满足某个条件(比如解析结果合格)。
  • “记住之前……”:需要在整个多轮交互中维护一个不断更新的状态(比如对话历史、已执行步骤列表、临时变量)。
  • “多角色协作”:需要模拟多个“参与者”(可以是不同的模型实例,也可以是工具)按照一定规则进行交互。

第三步:从 LangGraph 的核心概念学起学习 LangGraph,不要直接复制复杂例子。从最核心的三个概念入手:

  1. 状态 (State):定义一个字典类型,明确你的工作流需要跟踪哪些信息。比如{"messages": list, "step_count": int, "data": dict}
  2. 节点 (Node):一个普通的函数,它接收当前状态,执行一些操作(比如调用一个 LangChain 链),然后返回一个对状态的更新。这是你放置业务逻辑的地方。
    def call_model(state: State): # 从state中获取消息 messages = state[“messages”] # 调用模型(这里可能封装了一个LangChain链) response = chat_model.invoke(messages) # 返回更新后的状态部分 return {“messages”: messages + [response]}
  3. 边 (Edge):定义规则,决定一个节点执行完后,下一个该执行哪个节点。可以是固定的("always_go_to_node_b"),也可以是条件的(lambda state: "node_b" if some_condition else "node_c")。

一个极简的 LangGraph 工作流构建流程如下

from langgraph.graph import StateGraph, END # 1. 定义状态类型 class State(TypedDict): messages: list # 2. 创建图构建器 builder = StateGraph(State) # 3. 添加节点(上面定义的call_model函数) builder.add_node(“model”, call_model) # 4. 设置入口点 builder.set_entry_point(“model”) # 5. 添加边(这里简单设置为:执行完model后,就结束) builder.add_edge(“model”, END) # 6. 编译图,得到可执行对象 graph = builder.compile()

现在,你可以像调用函数一样运行这个图:final_state = graph.invoke({“messages”: [“Hello”]})

第四步:实现循环和分支在上面极简图的基础上,实现复杂逻辑:

  • 循环:添加一个边,从某个节点指回它自己或之前的节点。通常需要配合一个“条件节点”来判断是否继续循环。
  • 分支:添加多个不同的节点,并使用add_conditional_edges方法,根据某个节点的输出结果,决定下一步走哪条边。

5. 项目选型决策指南:我到底该用哪个?

最后,我们来回答最实际的问题。面对一个新项目,如何选择?

毫不犹豫选择 LangChain 的情况:

  • 你的任务流程是线性、确定、无状态的。例如:输入文档 -> 分割 -> 向量化 -> 存储(这是一条预处理流水线,用链清晰明了)。
  • 你需要快速构建一个RAG 问答系统,流程就是“检索 -> 生成”。
  • 你正在学习大模型应用开发,想先理解基础组件(模型、提示词、检索器、输出解析器)如何协同工作。
  • 项目原型期,追求最快速度验证核心功能

需要考虑引入 LangGraph 的情况:

  • 你的应用本质是一个有状态的对话系统,需要根据完整对话历史做决策。
  • 你需要构建一个复杂的多步骤代理,这个代理需要规划、执行工具、检查结果、并可能重新规划。
  • 业务流程中天然存在**“是/否”判断、循环审批、条件分支**。例如:“生成报告 -> 审核是否通过? -> (是)发送邮件 / (否)返回修改”。
  • 你需要清晰的可视化来向团队或客户解释整个工作流的逻辑。
  • 你对工作流的可控性、可调试性要求极高,希望每一步的流转都明确定义和可见。

一个实用的建议从 LangChain 链开始。当你在用链开发的过程中,发现代码里开始出现大量的if...else...来控制流程,或者发现需要手动维护一个全局变量来传递状态时,这就是一个强烈的信号——你的项目可能更适合用 LangGraph 来重构。此时引入 LangGraph,不仅能简化代码,还能使你的业务逻辑变得更加清晰和健壮。

总结一下: LangChain 是你的基础工具箱和粘合剂,用于组装静态功能单元。而 LangGraph 是高级的流程设计器和执行引擎,用于编排动态的、智能的业务工作流。它们不是二选一的关系,而是相辅相成。在复杂的生产级应用中,你很可能同时使用两者:用 LangChain 构建链和工具,再将它们作为节点,组装进 LangGraph 的蓝图中。理解这种层次关系,你就能在技术选型和架构设计上做出更明智的决策。

← 返回列表