LangChain vs LangGraph:如何选择合适的 AI 框架!
Source: Dev.to
LangChain vs LangGraph:如何选择合适的 AI 框架
在过去的几年里,LangChain 已经成为构建 LLM(大语言模型)驱动应用的事实标准。然而,随着需求的演进,LangGraph 作为一个更专注于图结构和工作流的框架出现,提供了不同的抽象层次和功能。本文将帮助你了解两者的核心区别、适用场景以及如何在项目中做出明智的选择。
目录
核心概念对比
| 概念 | LangChain | LangGraph |
|---|---|---|
| 抽象层次 | 以 链(Chain) 为中心,强调一步步的 顺序执行。 | 以 图(Graph) 为中心,支持 分支、合并和循环 的工作流。 |
| 主要目标 | 快速搭建 单一任务(如问答、文本生成)的流水线。 | 构建 复杂、多步骤 的业务流程,尤其是需要 状态管理 的场景。 |
| 状态管理 | 通过 Memory 对象在链之间共享上下文,适用于短期记忆。 | 内置 节点状态 与 全局状态,天然支持长期记忆和跨节点数据流。 |
| 调度方式 | 线性调用,通常在 Python 中直接调用 chain.run()。 | 使用 调度器(Scheduler),可以并行或异步执行节点。 |
| 可视化 | 主要依赖 代码结构,缺少官方可视化工具。 | 提供 图形化编辑器 与 可视化 DAG(有时通过 langgraph.visualize())。 |
主要特性对比表
| 特性 | LangChain | LangGraph |
|---|---|---|
| 链式调用 | ✅ 完整的 Chain、SequentialChain、RouterChain 等实现。 | ❌ 通过 节点(Node)组合实现相同功能,但不是链式 API。 |
| 工具集成 | 丰富的 工具(Tool) 接口:搜索、数据库、API 调用等。 | 同样支持工具,但更倾向于 节点 级别的封装。 |
| 记忆(Memory) | 多种内置记忆实现:ConversationBufferMemory、ConversationSummaryMemory 等。 | 通过 状态对象 实现记忆,支持 持久化(如向量数据库)。 |
| 并行执行 | 需要自行使用 asyncio 或多线程实现。 | 原生支持 并行节点 与 异步调度。 |
| 错误处理 | 通过 try/except 包装链或使用 ConditionalRouter。 | 节点级别的 错误回退 与 重试策略。 |
| 可扩展性 | 通过自定义 Chain、Tool、PromptTemplate 扩展。 | 通过自定义 节点、边 与 调度器 扩展。 |
| 社区与生态 | 大型社区,丰富的插件与示例。 | 较新,但增长迅速,官方文档提供 图编辑器 示例。 |
| 部署 | 适合 单体服务 或 函数即服务(FaaS)。 | 更适合 微服务、容器编排(如 Kubernetes)以及 工作流引擎。 |
何时使用 LangChain
- 单一步骤或线性任务:如问答、摘要、文本生成等。
- 快速原型:想在几行代码内完成一个 LLM 应用。
- 已有丰富工具链:需要集成搜索、数据库或自定义 API,且不需要复杂的状态管理。
- 资源受限:项目规模小,部署在单个容器或函数即服务平台上。
示例代码(保持原样,不翻译):
from langchain import OpenAI, LLMChain, PromptTemplate
prompt = PromptTemplate(
input_variables=["question"],
template="Answer the following question succinctly: {question}"
)
llm = OpenAI(model="gpt-4")
chain = LLMChain(llm=llm, prompt=prompt)
response = chain.run({"question": "What is the capital of France?"})
print(response)
何时使用 LangGraph
- 复杂业务流程:需要 分支、循环、并行 的工作流(如多轮对话、审批流、数据管道)。
- 长期记忆:跨会话、跨用户的状态需要持久化。
- 可视化需求:希望通过图形化界面查看和编辑工作流。
- 团队协作:多个开发者负责不同节点,图结构更易于分工。
- 高并发或分布式部署:需要调度器管理节点的并行执行。
示例代码(保持原样,不翻译):
from langgraph import Graph, Node, Scheduler
def fetch_data(state):
# ... fetch from DB ...
return {"data": result}
def process_data(state, data):
# ... process ...
return {"processed": processed_result}
graph = Graph()
graph.add_node("fetch", Node(fetch_data))
graph.add_node("process", Node(process_data))
graph.add_edge("fetch", "process")
scheduler = Scheduler(graph)
output = scheduler.run(initial_state={})
print(output)
迁移与互操作性
-
从 LangChain 迁移到 LangGraph
- 将
Chain中的每一步抽象为 节点(Node)。 - 使用 状态对象 替代
Memory,将上下文信息放入全局状态。 - 利用
Graph.add_edge定义执行顺序或条件分支。
- 将
-
在同一项目中混用
- 可以在 LangGraph 的节点内部调用 LangChain 的
Chain,实现 复用。 - 例如,在一个复杂工作流的“文本生成”节点里直接使用
LLMChain.run()。
- 可以在 LangGraph 的节点内部调用 LangChain 的
-
工具与插件
- 大多数 LangChain 的工具(如
SerpAPIWrapper、SQLDatabaseToolkit)可以直接在 LangGraph 节点中使用,只需包装为函数即可。
- 大多数 LangChain 的工具(如
结论
- LangChain 仍是 快速构建单一步骤 LLM 应用 的首选,尤其适合原型和小型服务。
- LangGraph 则在 复杂、可视化、可扩展的工作流 场景中表现更佳,尤其当你需要 状态管理、并行执行 或 团队协作 时。
选择建议:
| 场景 | 推荐框架 |
|---|---|
| 简单问答 / 文本生成 | LangChain |
| 多轮对话 + 长期记忆 | LangGraph |
| 数据管道 + 并行处理 | LangGraph |
| 快速 PoC / 单函数 | LangChain |
| 需要图形化编辑器 | LangGraph |
随着两者生态的不断成熟,未来可能出现更深层次的融合。保持关注官方更新,结合项目实际需求灵活选型,才能最大化发挥 LLM 的价值。
为什么此比较重要 – LangChain 与 LangGraph
我构建实用的 LLM 驱动软件,已经看到两种模式逐渐显现:直接的线性流水线以及有状态的、代理式工作流。 “LangChain vs LangGraph” 这个问题并非学术讨论;它决定了架构、维护方式以及系统随时间的推理方式。
当我说 “LangChain vs LangGraph” 时,我指的是比较两种不同的设计哲学:
- LangChain – 为线性序列优化:接受输入,按顺序执行一次或多次 LLM 调用,存储或返回结果。
- LangGraph – 为图结构优化:节点、边、循环,以及跨多个步骤的持久状态。
LangChain
核心概念
- Prompt templates – 可复用的模板,接受变量并生成一致的 LLM 输入。
- LLM‑agnostic connectors – 在 OpenAI、Anthropic、Mistral、Hugging Face 等模型之间轻松切换。
- Chains – 核心抽象:将多个步骤组合,使每个输出作为下一个步骤的输入。
- Memory – 短期或长期对话上下文,适用于有状态聊天,但相较于完整状态机仍有限。
- Agents and tools – 让模型以结构化方式调用 API、计算器或外部服务。
何时使用 LangChain
- 原型设计提示、构建简单的 RAG 系统,或创建从向量库读取并返回单一响应的问答流水线。
- 文本转换流水线(摘要、翻译、信息抽取)。
- 单轮用户交互,如客服响应。
- 基本的 RAG 系统,执行向量库检索并返回单一合成答案。
LangChain 能让开发者快速提升生产力。它提供即插即用的组件——提示模板、检索器和链组合器——让你无需自行构建编排原语即可快速交付。
Source: …
LangGraph
核心概念
- Nodes – 离散任务:调用 LLM、从数据库获取数据、执行网页搜索或调用摘要器。
- Edges – 定义条件转移、并行分支或回环路径。
- State – 在节点之间演进的动态上下文:消息、情景记忆和检查点。
- Decision nodes – 原生支持条件逻辑和路由到专门的代理。
LangGraph 将应用视为状态机。节点可以循环、重新访问早期步骤,并执行多轮工具调用。这使得反思、迭代检索或逐步细化答案等代理行为成为可能。
何时使用 LangGraph
- 需要多步骤决策且可以循环直至满足退出条件的场景。
- 根据上下文将查询路由到专门的代理。
- 在多个 LLM 调用和用户交互之间保持持久状态。
- 复杂的工具使用,包括多轮网页搜索、摘要以及外部来源的聚合。
示例: 一个电子邮件草稿代理,能够检索用户偏好、查询日历、起草邮件、请求澄清,并迭代细化草稿,这自然映射到 LangGraph。
实用比较检查清单
| 方面 | LangChain | LangGraph |
|---|---|---|
| 工作流风格 | 线性且顺序的 | 循环的、基于图的并带有循环 |
| 内存 | 有限的对话记忆 | 丰富且持久的状态,跨节点和会话保持 |
| 分支 | 简单分支,一次性工具调用 | 内置条件边、循环、检查点 |
| 理想使用场景 | 简单聊天机器人、检索增强生成(RAG)、类似 ETL 的 LLM 流程 | 多代理系统、自治代理行为、长期运行的工作流 |
| 人机交互 | 可实现但非原生 | 一流的检查点和人机交互模式 |
在权衡 “LangChain 与 LangGraph” 时,除了考虑当前需求,还要考虑预期的未来复杂度。如果应用可能会发展为多代理编排,或需要持久状态和重试机制,直接使用 LangGraph 可以避免后期重构。
示例:使用 LangChain 的 RAG(线性)
- 安装所需的包并配置 API 密钥。
- 创建接受变量(如
objective和topic)的提示模板。 - 通过 Hugging Face、OpenAI 或其他提供商初始化 LLM 或本地模型连接器。
- 将文档存储在向量数据库中并创建检索器。
- 构建检索增强生成链,以检索上下文并合成答案。
这种模式保持线性:检索相关文档 → 生成答案。它适用于许多 FAQ 机器人、文档助理以及单次流水线。代码简洁,易于迭代。
# Example LangChain RAG pipeline
from langchain import PromptTemplate, LLMChain
from langchain.vectorstores import FAISS
from langchain.llms import OpenAI
# 1. Prompt template
prompt = PromptTemplate(
input_variables=["question", "context"],
template="Answer the question based on the context:\n\nContext: {context}\n\nQuestion: {question}"
)
# 2. LLM
llm = OpenAI(model_name="gpt-4")
# 3. Chain
chain = LLMChain(llm=llm, prompt=prompt)
# 4. Retrieval
vector_store = FAISS.load_local("my_index")
retriever = vector_store.as_retriever()
def answer_question(question: str):
docs = retriever.get_relevant_documents(question)
context = "\n".join([doc.page_content for doc in docs])
return chain.run({"question": question, "context": context})
示例:使用 LangGraph 的 RAG(基于图)
- 将静态内容从 URL 或文档加载到向量库中。
- 创建图节点:
retrieve、web_search、decision和generate。 - 定义状态:跟踪检索结果是否已回答用户问题,存储中间摘要,并记录工具输出。
- 使用条件边连接节点:
- 如果本地检索失败 → 路由到网页搜索。
- 如果网页搜索产生噪声结果 → 提出澄清性问题。
- 根据需要循环返回。
- 运行图,直至满足停止条件,然后返回最终合成结果。
该模式支持多轮工具使用和代理式推理。在测试中,询问 LangGraph 代理“本月最新的 AI 发展”时,如果本地知识已过时,会触发网页搜索节点,获取、摘要并在呈现答案前检查充分性。
# Example LangGraph workflow (pseudo‑code)
from langgraph import Graph, Node, Edge, State
# Nodes
def retrieve(state: State):
docs = vector_store.as_retriever().get_relevant_documents(state["question"])
state["retrieved"] = docs
return state
def web_search(state: State):
results = search_api(state["question"])
state["web_results"] = results
return state
def decide(state: State):
if not state["retrieved"]:
return "web_search"
if not is_sufficient(state["retrieved"]):
return "web_search"
return "generate"
def generate(state: State):
context = combine(state.get("retrieved", []), state.get("web_results", []))
answer = llm.generate(prompt=prompt, context=context)
state["answer"] = answer
return state
# Graph definition
graph = Graph()
graph.add_node("retrieve", retrieve)
graph.add_node("web_search", web_search)
graph.add_node("decision", decide)
graph.add_node("generate", generate)
graph.add_edge("retrieve", "decision")
graph.add_edge("web_search", "decision")
graph.add_edge("decision", "generate", condition=lambda s: s == "generate")
graph.add_edge("decision", "web_search", condition=lambda s: s == "web_search")
graph.set_entry_point("retrieve")
Decision Heuristics
- Pattern: Start simple – 如果问题是单次传递的,使用 LangChain 快速验证提示。
- Pattern: Evolve to graph – 如果你的单次传递流水线累积了条件和有状态的检查点,请逐步重构为 LangGraph 图。
- Anti‑pattern: Premature complexity – 当不需要循环或持久状态时,避免实现完整的图。过度设计会降低清晰度并增加维护成本。
- Anti‑pattern: One‑off tool calls – 如果需要重复或多阶段的工具编排,线性链会变得脆弱。LangGraph 的原生边和状态更适合。
可复用模板
| 模板 | 描述 |
|---|---|
User query → Retriever → LLM prompt → Result → Store conversation (optional) | 适用于文档问答、帮助中心和每个请求基本独立的聊天机器人。 |
User query → Retrieve → Decision node (sufficient?) → If no, Web search node → Summarize → Reflect/loop → Final generate → Persist episodic memory | 适用于动态信息请求、研究助理以及需要迭代推理的多代理工作流。 |
Migrating from LangChain to LangGraph
- 确定 LangChain 中出现决策逻辑的分支点。
- 将提示模板和检索组件提取为可重用的节点。
- 定义一个状态模式(schema),用于捕获中间结果、工具输出和记忆。
- 用通过条件边连接节点的图结构取代线性链执行。
- 根据需要添加检查点或人工介入(human‑in‑the‑loop)节点。
结论
- 选择 LangChain 当您需要快速开发、工作流是线性的且状态管理最小化时。
- 选择 LangGraph 当您的应用需要循环、丰富的持久状态、条件路由或多代理编排时。
评估您 AI 系统的当前和未来复杂性将帮助您选择合适的框架,避免以后昂贵的重构。