LangChain vs LangGraph:从困惑到清晰的认知之路(扫盲篇)
文章目录
- LangChain:基础设施和组件库
- LangGraph:复杂应用的构建框架
- 形象的比喻
- 实际应用中的区别
- 什么时候用哪个?
- 我的学习路线
在学习 AI 的过程中,我发现一个很普遍的现象:很多开发者(包括我自己)对 LangChain 和 LangGraph 的关系都是一知半解的。
有些人可能知道 LangChain 可以调用 OpenAI API,LangGraph 可以构建 agent,但具体它们是什么关系、为什么需要两个框架、什么时候用哪个,基本上是靠感觉在用。我之前也是这样,能跑通代码就行了,反正功能实现了嘛。
但慢慢我发现,这种"差不多就行"的态度其实是有问题的:
- 开发效率低下:不清楚工具边界,经常用错工具做事情,绕了很多弯路
- 代码质量堪忧:不理解底层逻辑,写出来的代码维护性很差
- 问题排查困难:出了 bug 不知道从哪里入手,只能瞎试
- 技能天花板:永远停留在"能用"的层次,无法设计出真正高效实用的 AI 系统
更重要的是,当你想要构建更复杂的 AI 应用时——比如需要长期记忆的智能助手、可以自主决策的业务流程、或者需要人机协作的复杂系统——如果不理解这些工具的本质区别,基本上就是在盲人摸象。
所以我觉得有必要花时间理清楚这两者的关系,这不仅是为了写出更好的代码,更是为了能够设计出真正解决实际问题的 AI 系统。
LangChain:基础设施和组件库
LangChain 更像是一个工具箱,提供各种基础组件:
from langchain_openai import ChatOpenAI
from langchain.tools import tool# LangChain 提供统一的接口来使用不同的 LLM,更常见的做法是直接实例化具体的模型类
llm = ChatOpenAI(model="gpt-4", temperature=0)# LangChain 提供工具定义的标准方式
@tool
def write_email(to: str, subject: str, content: str) -> str:"""Write and send an email."""return f"Email sent to {to}"
LangChain 的强项:
- 模型抽象:统一接口访问不同的 LLM(OpenAI、Anthropic、本地模型等)
- 工具定义:标准化的工具创建和调用方式
- 提示模板:管理和组织 prompts
- 数据处理:文档加载、向量存储、检索等
LangGraph:复杂应用的构建框架
LangGraph 是建立在 LangChain 之上的架构框架,专门用来构建复杂的 AI 应用:
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import InMemorySaver# LangGraph 提供状态管理和流程控制
class State(TypedDict):messages: listuser_info: dictworkflow = StateGraph(State)
# workflow.add_node("process", process_node) # "process_node" 在此未定义,仅为示例
app = workflow.compile(checkpointer=InMemorySaver())
LangGraph 的强项:
- 状态管理:跟踪整个对话或工作流的状态
- 流程控制:定义复杂的执行路径和条件分支
- 持久化:保存和恢复执行状态,支持长时间运行的任务
- 人机交互:内置 interrupt 机制,支持人工干预
- 可视化:可以画出执行流程图
形象的比喻
LangChain = 乐高积木
- 提供各种标准化的"积木"(LLM、工具、提示模板等)
- 每个积木都有标准接口,可以相互连接
- 适合构建简单的组合
LangGraph = 乐高建筑设计图 + 施工管理
- 告诉你如何用这些积木构建复杂的"建筑"(workflow/agent)
- 提供"施工管理"(状态管理、流程控制、错误处理)
- 可以处理"建筑过程中的变化"(动态路径、人工干预)
实际应用中的区别
用 LangChain 构建简单应用:
# 简单的 LLM 调用链
# 这里使用了 LangChain 表达式语言(LCEL),通过管道符 | 可以方便地将组件连接起来。
prompt = "翻译这段文字:{text}"
# chain = llm | output_parser # "output_parser" 在此未定义,仅为示例
# result = chain.invoke({"text": "Hello world"})
等价于以下步骤:
prompt_text = "翻译这段文字:Hello world"# 第一步:调用 LLM
llm_response = llm.invoke(prompt_text)
# llm_response 类型通常是 AIMessage,包含很多元数据# 第二步:使用输出解析器处理 LLM 的原始输出
final_result = output_parser.invoke(llm_response)
# final_result 现在是纯字符串,比如:"你好,世界"
用 LangGraph 构建复杂应用:
# 有状态的、可中断的、多步骤的工作流
app = workflow.compile(checkpointer=InMemorySaver())
config = {"configurable": {"thread_id": "123"}}# 可以暂停、恢复、查看中间状态
# result = app.invoke(input_data, config) # "input_data" 在此未定义,仅为示例
state = app.get_state(config) # 查看当前状态
# ... 稍后继续执行
什么时候用哪个?
只需要 LangChain 的情况:
- 简单的 LLM 调用
- 基础的 RAG(检索增强生成)
- 单步骤的工具调用
- 原型验证
需要 LangGraph 的情况:
- 多步骤的复杂流程
- 需要状态管理的对话系统
- 长时间运行的任务
- 需要人工干预的 workflow
- 复杂的 agent 系统
我的学习路线
- 先学 LangChain 基础:理解 LLM、工具、提示模板等概念
- 再学 LangGraph:当你需要构建复杂应用时
- 它们是互补的:LangGraph 依赖 LangChain 的组件,但提供了更高级的组织方式
- 从简单到复杂:不要一开始就用 LangGraph,除非真的需要其复杂性