在 LLM 应用开发领域,LangChain 和 LangGraph 是两个经常被提及的名字。很多开发者入门时会选择 LangChain,但随着项目复杂度提升,往往会遇到瓶颈——循环逻辑怎么都写不对,状态管理越来越混乱。实际上,两者并不是竞争关系,而是互补关系:前者是通用的 LLM 应用开发框架,后者是针对复杂工作流设计的编排引擎。本文将系统性地对比两者的区别,帮助开发者做出更合适的技术选型。
从一个痛点说起
假设一个需求:构建一个客服机器人,用户可以随时追问、修正之前的问题,系统需要记住对话上下文,并且在特定条件下能够"回到上一步"重新回答。
如果用 LangChain 来做,你会发现它更像是一条单行道。定义好 Prompt,调用模型,返回结果,流程结束。虽然 LangChain 也有 Memory 模块,但那种线性流程在处理真正的多轮交互、状态回溯时,总感觉哪里不对劲。
这就是 LangGraph 出现的背景。LangGraph 是 LangChain 生态中的核心组件,专门用于构建有状态、多步骤的复杂工作流。值得注意的是,LangChain 的 Agent 正是构建在 LangGraph 之上的——换句话说,LangGraph 是更底层的基础设施,而非简单的"扩展库"。
什么是 LangChain
LangChain 是一个用于构建 LLM 应用的开发框架,提供了从模型调用到向量检索的一系列工具。它的核心价值在于封装了大量重复性代码,让开发者能够快速上手。
核心模块包括:模型调用层(统一接口)、Prompt 模板(动态拼接)、Chains(链式组合)、Memory(记忆存储)、Tools(工具调用)、Agents(自主决策)。
简单来说,LangChain 解决的是"如何方便地调用大模型"这个问题。
在 Go 语言中,对应的实现是 langchaingo(github.com/tmc/langchaingo):
package main
import (
"context"
"fmt"
"log"
"github.com/tmc/langchaingo/llms"
"github.com/tmc/langchaingo/llms/openai"
)
func main() {
llm, err := openai.New()
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
completion, err := llms.GenerateFromSinglePrompt(ctx, llm, "用一句话介绍 Go 语言")
if err != nil {
log.Fatal(err)
}
fmt.Println(completion)
}
对于简单场景,LangChain 的链式调用完全够用。
什么是 LangGraph
LangGraph 的核心设计是将工作流抽象为一张图,图的节点是操作单元,边是操作之间的流向。需要澄清的是,LangGraph 并非依赖 LangChain 才能运行——它可以独立使用,但在 LangChain 生态中,它是 Agent 实现持久化、流式输出、人机交互等能力的基础。
这个设计带来了几个关键能力:
节点:每个节点可以是模型调用、工具执行,或者任意自定义逻辑。
边:定义了节点之间的连接关系,分为普通边和条件边。
循环:支持从某个节点回到之前的节点,这是 LangChain 难以优雅处理的特性。
状态:每个步骤都可以读写共享状态,多个节点协同操作同一份上下文。
用 langchaingo 构建的链式调用是线性流程,每一步都依赖上一步的结果。但当我们需要"模型反复思考直到满意"这种循环逻辑时,LangChain 的链式模型就显得力不从心了。
核心区别在哪里
编程模型不同:LangChain 用链式调用,适合线性流程。LangGraph 用图结构,适合网状流程。
状态管理不同:LangChain 的状态传递主要依赖函数参数和返回值。LangGraph 提供共享状态对象,多个节点读写同一份数据。
循环处理不同:这是最核心的区别。LangChain 的 LCEL 管道是单向的,循环需要额外封装。LangGraph 原生支持循环,可以轻松实现"模型自我反思直到满足条件"这类场景。
适用场景不同:LangChain 适合单轮问答、简单工具调用、RAG 检索等场景。如果你想快速上手构建 Agent,LangChain 提供了预构建架构。对于复杂 Agent 工作流、需要回退机制的交互系统,或者对状态持久化、流式输出有要求的生产级应用,LangGraph 是更合适的选择。
什么时候选谁
如果你的应用是"一问一答"式,比如翻译、总结、生成文案,直接用 LangChain,简洁高效。
如果你的应用需要多轮对话、记忆上下文、动态选择下一步,优先考虑 LangGraph。
如果你的应用需要模型反复执行某个步骤直到结果符合预期,比如"让模型生成代码,不满意就重新生成",这是 LangGraph 的主场。
如果不确定,先用 LangChain 快速验证思路,等发现线性流程不够用了再迁移到 LangGraph。
实战场景对比
来看一个实际场景:实现一个"论文评审 Agent"。需求是:给 AI 一篇论文,检查格式、逻辑、创新点,如果发现问题就反馈给用户修改,形成一个"检查—反馈—修改"的循环,直到论文符合标准。
用 LangChain 实现的话,很难优雅地表达"检查不通过就回到反馈环节"这个循环逻辑。你可能需要用 while 循环配合 LangChain 的输出,代码会变得支离破碎。
用 LangGraph 呢?整个流程可以很自然地画成一张图:
// LangGraph 工作流伪代码
workflow := NewStateGraph(ReviewState{})
workflow.AddNode("review", reviewNode)
workflow.AddNode("feedback", feedbackNode)
workflow.SetEntryPoint("review")
workflow.AddConditionalEdges("review",
func(state ReviewState) string {
if state.IsApproved {
return END
}
return "feedback"
},
)
workflow.AddEdge("feedback", "review")
app := workflow.Compile()
这就是图结构的威力:流程看得见,状态管得住,循环写得优雅。
写在最后
LangChain 降低了 LLM 应用的开发门槛,LangGraph 则在门槛之上打开了更复杂的可能性。理解两者的定位很重要——回归到业务本质,选择真正适合的工具,才能写出既优雅又实用的代码。
不妨先问自己:这个流程有没有循环?有没有多步骤的状态需要保持?如果答案都是否,LangChain 足够。如果答案是有,LangGraph 可能是更好的选择。