LangChain 与 LangGraph 完全指南:核心组件、架构原理、编排机制与 LlamaIndex 集成 -- pd的后端笔记
文章目录
-
- [LangChain 与 LangGraph 完全指南:核心组件、架构原理、编排机制与 LlamaIndex 集成 -- pd的后端笔记](#LangChain 与 LangGraph 完全指南:核心组件、架构原理、编排机制与 LlamaIndex 集成 -- pd的后端笔记)
- [🎯 先别急着背概念:为什么很多人一学 Agent 就开始乱?](#🎯 先别急着背概念:为什么很多人一学 Agent 就开始乱?)
- [🧠 一、先建立一个正确视角:LLM 应用不是"调个模型"这么简单](#🧠 一、先建立一个正确视角:LLM 应用不是“调个模型”这么简单)
-
- [📌 先记一个总判断](#📌 先记一个总判断)
- [📊 二、从系统分层看这三个框架,各自到底在管什么](#📊 二、从系统分层看这三个框架,各自到底在管什么)
-
- [💡 这一层最容易形成的误区](#💡 这一层最容易形成的误区)
- [🚀 三、LangChain 到底是什么?不要再把它只理解成"链式调用库"了](#🚀 三、LangChain 到底是什么?不要再把它只理解成“链式调用库”了)
-
- [1. 它不只关心"怎么调模型"](#1. 它不只关心“怎么调模型”)
- [2. 它不只服务"问答 Demo"](#2. 它不只服务“问答 Demo”)
- [🔍 一个更贴近工程的类比](#🔍 一个更贴近工程的类比)
- [✅ 小结](#✅ 小结)
- [🔧 四、LangChain 的核心组件,应该放在一套系统里去理解](#🔧 四、LangChain 的核心组件,应该放在一套系统里去理解)
-
- [🧩 1. Models:模型抽象层](#🧩 1. Models:模型抽象层)
-
- [一个最小的 LangChain Agent 例子](#一个最小的 LangChain Agent 例子)
- [🗂️ 2. Messages / Context:消息与上下文层](#🗂️ 2. Messages / Context:消息与上下文层)
- [🛠️ 3. Tools:工具层](#🛠️ 3. Tools:工具层)
-
- [再看一个带 `@tool` 的例子](#再看一个带
@tool的例子)
- [再看一个带 `@tool` 的例子](#再看一个带
- [📦 4. Structured Output:结构化输出层](#📦 4. Structured Output:结构化输出层)
- [🧱 5. Middleware:中间件层](#🧱 5. Middleware:中间件层)
- [🤖 6. Agents:Agent 封装层](#🤖 6. Agents:Agent 封装层)
- [🏗️ 五、LangChain 的核心架构,为什么说它本质上是"应用层框架"](#🏗️ 五、LangChain 的核心架构,为什么说它本质上是“应用层框架”)
-
- [1. 能力接入层](#1. 能力接入层)
- [2. 上下文组织层](#2. 上下文组织层)
- [3. 决策与输出层](#3. 决策与输出层)
- [4. 运行时承接层](#4. 运行时承接层)
- [📌 一个最容易忽略的架构事实](#📌 一个最容易忽略的架构事实)
- [⚠️ 六、为什么 LangGraph 会出现?因为复杂 Agent 根本不是一条直线](#⚠️ 六、为什么 LangGraph 会出现?因为复杂 Agent 根本不是一条直线)
-
- [💥 为什么说"复杂 Agent 不是直线"很重要?](#💥 为什么说“复杂 Agent 不是直线”很重要?)
- [🚦 七、LangGraph 到底是什么?它本质上是在把 Agent 运行时状态机化](#🚦 七、LangGraph 到底是什么?它本质上是在把 Agent 运行时状态机化)
-
- [它和普通 DAG / 工作流工具有什么不一样?](#它和普通 DAG / 工作流工具有什么不一样?)
- [✅ 一个更准确的一句话定义](#✅ 一个更准确的一句话定义)
- [🧠 八、LangGraph 的编排原理,到底在编排什么](#🧠 八、LangGraph 的编排原理,到底在编排什么)
-
- [📌 1. State:整个图的共享状态中心](#📌 1. State:整个图的共享状态中心)
- [🧩 2. Node:处理状态的逻辑节点](#🧩 2. Node:处理状态的逻辑节点)
- [🔀 3. Edge:决定接下来去哪](#🔀 3. Edge:决定接下来去哪)
- [🪢 4. Reducer:解决状态合并问题](#🪢 4. Reducer:解决状态合并问题)
- [💾 5. Checkpoint / Persistence:让流程可以中断和恢复](#💾 5. Checkpoint / Persistence:让流程可以中断和恢复)
- [👤 6. Human-in-the-loop:让人工介入成为流程一部分](#👤 6. Human-in-the-loop:让人工介入成为流程一部分)
- [📌 一个官方概念里很实用的点:MessagesState](#📌 一个官方概念里很实用的点:MessagesState)
- [📈 九、用一张图彻底看懂 LangGraph 的执行机制](#📈 九、用一张图彻底看懂 LangGraph 的执行机制)
- [⚖️ 十、LangChain 和 LangGraph 的区别,到底该怎么讲才不混乱](#⚖️ 十、LangChain 和 LangGraph 的区别,到底该怎么讲才不混乱)
-
- [1. 抽象层级不同](#1. 抽象层级不同)
- [2. 设计目标不同](#2. 设计目标不同)
- [3. 适用场景不同](#3. 适用场景不同)
- [4. 两者关系不是替代,而是上下层协作](#4. 两者关系不是替代,而是上下层协作)
- [📌 一个非常实用的选型建议](#📌 一个非常实用的选型建议)
- [📚 十一、那 LlamaIndex 应该放在哪?它更像 RAG 系统里的"数据层专家"](#📚 十一、那 LlamaIndex 应该放在哪?它更像 RAG 系统里的“数据层专家”)
- [🔗 十二、LlamaIndex 如何和 LangChain 结合?最常见的是这三种方式](#🔗 十二、LlamaIndex 如何和 LangChain 结合?最常见的是这三种方式)
-
- [1. LangChain 做应用与 Agent,LlamaIndex 做检索与查询](#1. LangChain 做应用与 Agent,LlamaIndex 做检索与查询)
- [2. 在 LlamaIndex 里复用 LangChain 的 LLM 适配](#2. 在 LlamaIndex 里复用 LangChain 的 LLM 适配)
- [3. 在 LlamaIndex 里复用 LangChain 的 Embeddings](#3. 在 LlamaIndex 里复用 LangChain 的 Embeddings)
- [4. 一个更贴近项目落地的组合姿势](#4. 一个更贴近项目落地的组合姿势)
- [🏢 十三、如果把三者放进一套企业系统里,最合理的架构通常长什么样](#🏢 十三、如果把三者放进一套企业系统里,最合理的架构通常长什么样)
-
- [🔍 这套架构为什么更稳?](#🔍 这套架构为什么更稳?)
- [⚠️ 十四、真正落地时最容易踩的坑,不在框架本身,而在边界设计](#⚠️ 十四、真正落地时最容易踩的坑,不在框架本身,而在边界设计)
-
- 再把这些坑翻译成人话
- [✅ 一个很实用的自检清单](#✅ 一个很实用的自检清单)
- [✅ 十五、最后再把你最关心的几个问题,压缩成一张速答表](#✅ 十五、最后再把你最关心的几个问题,压缩成一张速答表)
- [💡 十六、总结](#💡 十六、总结)
-
- [📌 最后给一个落地建议](#📌 最后给一个落地建议)
- [🔗 参考资料](#🔗 参考资料)
🎯 先别急着背概念:为什么很多人一学 Agent 就开始乱?
如果你最近在做 LLM 应用,大概率会经历一个很典型的过程:
- 一开始,只想先把模型调通
- 接着,开始加 Prompt、加 Tools、加聊天记忆
- 再往后,又想接知识库、做多步骤推理、加人工审核、支持失败恢复
- 最后你会发现:系统能跑,但结构越来越乱
这时候,很多人脑子里会同时冒出几个名词:
- LangChain
- LangGraph
- LlamaIndex
然后新的困惑就来了:
- LangChain 到底是什么?
- 它的核心组件有哪些?
- LangGraph 又是干什么的?
- 它和 LangChain 到底是什么关系?
- 如果我要做 RAG,LlamaIndex 又该放在哪一层?
很多文章的问题,不是讲得不多,而是讲得太像"问答串烧":
- 先解释一个名词
- 再解释一个名词
- 再做一个生硬对比
- 最后给你一张表结束
结果就是:
每个问题好像都答了,但你仍然没形成一张完整的系统地图。
所以这篇文章,我们不按你提问的顺序机械作答,而是按一条更符合工程理解的主线来讲:
先看 LLM 应用为什么会复杂,再看 LangChain 解决了什么,再看 LangGraph 为什么会出现,最后再看 LlamaIndex 怎么接进整套系统。
你只要沿着这条主线读下去,前面那些问题自然都会被串起来。
🧠 一、先建立一个正确视角:LLM 应用不是"调个模型"这么简单
很多人第一次做 AI 应用,会把系统想成这样:
text
用户问题 -> Prompt -> LLM -> 返回答案
这个模型本身没错,但它只适合最小 Demo。
一旦你做的是稍微真实一点的业务系统,链路马上就会膨胀:
用户请求
应用层封装
模型调用
上下文管理
工具调用
知识库检索
状态持久化
人工审核 / 中断恢复
文档索引 / 向量库
也就是说,真正的 LLM 系统,至少会同时碰到 4 类问题:
| 问题类型 | 你会碰到什么事 | 本质挑战 |
|---|---|---|
| 模型调用 | 不同 provider、不同模型切换 | 抽象统一接口 |
| 应用编排 | Prompt、Tools、输出结构化、消息上下文 | 如何高效开发 |
| 流程控制 | 分支、循环、重试、恢复、人审 | 如何把复杂流程跑稳 |
| 数据检索 | 私有知识、索引构建、检索召回 | 如何把外部知识接进来 |
看到这里,你就会明白一个关键点:
LangChain、LangGraph、LlamaIndex 之所以经常一起出现,不是因为它们"长得像",而是因为它们通常落在同一套系统的不同层。
很多人一上来就问"我到底该学哪个",其实这个问题本身就有点偏。
更准确的问法应该是:
- 我现在缺的是应用开发抽象吗?
- 我现在缺的是复杂流程运行时吗?
- 我现在缺的是私有知识的数据层能力吗?
当你从这个角度切入,三者的关系会清晰很多。
📌 先记一个总判断
如果你现在还没有完整地图,可以先记住这三句话:
- LangChain 更像应用层框架
- LangGraph 更像流程运行时框架
- LlamaIndex 更像 RAG 数据层框架
后面我们就沿着这个分层逐步拆开。
📊 二、从系统分层看这三个框架,各自到底在管什么
如果你让我用最工程化的方式来描述这三个框架,我会这样拆:
| 层级 | 主要问题 | 更常见的框架 |
|---|---|---|
| 应用开发层 | 怎么把模型、Prompt、Tools、消息、输出组织起来 | LangChain |
| 流程编排层 | 怎么把多步骤 Agent 作为有状态流程稳定运行 | LangGraph |
| 数据检索层 | 怎么把企业文档、知识库、索引、查询引擎接进系统 | LlamaIndex |
很多人最容易混淆的地方,在于把"应用开发"和"流程编排"当成一回事。
但这两个层其实完全不同:
- 应用开发层 更关心开发体验:怎么快速搭起来、怎么复用组件、怎么让接口友好
- 流程编排层 更关心运行稳定性:怎么处理中断、怎么持久化状态、怎么做条件分支、怎么让人工介入
而数据检索层又是第三套问题域,它关注的是:
- 文档怎么接入
- 数据怎么清洗
- 索引怎么构建
- 查询怎么组织
- 检索结果怎么返回给上层 Agent
所以很多时候,它们并不是替代关系,而是组合关系。
用户 / 外部系统
LangChain 应用层
LangGraph 编排层
LlamaIndex 数据层
向量库 / 文档源 / 检索系统
💡 这一层最容易形成的误区
很多文章会把三者写成"横向竞品对比表",但真实项目里,它们更像纵向分层:
- LangChain 不一定替代 LangGraph
- LangGraph 也不一定替代 LlamaIndex
- LlamaIndex 通常也不是在替代 LangChain
真正成熟的理解不是"谁比谁强",而是:
谁更适合放在这一层。
下面我们先看 LangChain,因为它往往是大多数人最先接触的一层。
🚀 三、LangChain 到底是什么?不要再把它只理解成"链式调用库"了
LangChain 早期给很多人的印象,是"把几个步骤串起来"的 chain 框架。
这个印象不是完全错,但今天如果你还停在这一步,就会明显低估它。
从当前官方文档来看,LangChain 的定位已经更清晰了:
LangChain 是一个用于构建 LLM 应用和 Agent 的开发框架。
这个定义看起来普通,但它背后至少包含了两层意思。
1. 它不只关心"怎么调模型"
它还关心:
- 怎么组织消息
- 怎么管理上下文
- 怎么做工具调用
- 怎么做结构化输出
- 怎么把这些能力封装成 Agent
也就是说,它不是只解决 API 调用问题,而是想把 LLM 应用开发过程中的一组高频能力统一抽象出来。
2. 它不只服务"问答 Demo"
它真正想解决的是:
如何把大模型能力,封装成一套可复用、可组合、可进工程系统的开发能力。
这也是为什么现在你再只用"LangChain 就是链式框架"去理解它,已经不够了。
它更像一个围绕 LLM 应用开发展开的"应用层工具箱"。
🔍 一个更贴近工程的类比
如果用 Web 开发做类比:
- 模型 provider SDK 像数据库驱动或第三方 SDK
- LangChain 更像"把这些能力统一到一套应用开发方式里"的框架
- 它让你不用每次都手搓一套 Prompt + Tool + Memory + Output 管线
所以 LangChain 的价值,从来不只是"少写几行代码",而是:
- 降低心智负担
- 提高组合效率
- 让模型能力更容易进入业务系统
✅ 小结
如果你要一句话回答"什么是 LangChain",更推荐这样说:
LangChain 是一个面向 LLM 应用和 Agent 开发的高层框架,它把模型、消息、工具、结构化输出和 Agent 能力统一到一套开发抽象里。
🔧 四、LangChain 的核心组件,应该放在一套系统里去理解
如果只把 LangChain 的核心组件当名词背下来,很容易记完就忘。
更推荐的做法是:把它们放进一条应用链路里理解。
用户输入
Messages / Context
Prompt / Agent Logic
Model
Tools
Structured Output
Middleware
业务系统消费结果
这张图里,几乎就包含了 LangChain 的核心组件。
🧩 1. Models:模型抽象层
这一层负责统一不同模型提供商的调用方式。
它的价值不只是"写起来方便",更重要的是:
- 业务代码不需要深度耦合某一个厂商 SDK
- 更容易切换 provider
- 更容易做路由、降级、兜底和成本控制
如果没有这一层,系统很容易走向一个结局:
- 前期接 OpenAI 很快
- 中期想接 Anthropic 或本地模型时发现全链路都要改
- 最后模型切换成本高得离谱
这就是"抽象统一接口"的工程价值。
一个最小的 LangChain Agent 例子
下面这个例子来自 LangChain 官方文档的思路,重点不是天气查询本身,而是看它如何把 模型 + 工具 + system prompt 收敛到一个 agent 创建入口里:
python
from langchain.agents import create_agent
def get_weather(city: str) -> str:
"""Get weather for a given city."""
return f"It's always sunny in {city}!"
agent = create_agent(
model="anthropic:claude-sonnet-4-6",
tools=[get_weather],
system_prompt="You are a helpful assistant",
)
result = agent.invoke(
{
"messages": [
{"role": "user", "content": "what is the weather in sf"}
]
}
)
这个例子虽然简单,但已经体现出 LangChain 的第一层价值:
- 模型不是直接裸调 SDK
- 工具不是散落在业务代码里
- 对话入口不是你自己手拼一个 while 循环
也就是说,它帮你把"最常见的 Agent 开发骨架"先搭出来了。
🗂️ 2. Messages / Context:消息与上下文层
这部分非常关键。
因为 LLM 应用不是发一个字符串就结束了,真实系统往往要维护:
- system message
- user message
- assistant message
- 会话历史
- 运行时上下文
- 短期记忆
这层真正解决的问题是:
模型这次回答之前,到底应该看到哪些上下文。
这不是小问题,因为上下文管理几乎直接决定:
- 回答是否准确
- token 成本是否可控
- 多轮对话是否会跑偏
- 工具调用是否还保留前置信息
很多 Agent"看起来像是笨",其实不是模型笨,而是上下文喂错了。
比如:
- 该保留的业务上下文没保留
- 不该保留的历史垃圾全部塞进去
- 检索结果和会话消息重复拼接
- 用户权限和会话状态没有进入上下文
所以这层真正考验的是"上下文工程",而不只是"消息列表怎么拼"。
🛠️ 3. Tools:工具层
Tool 是 LangChain 非常核心的能力。
它让模型不只是"会说",而是能"调用外部能力"。
典型工具包括:
- 数据库查询
- 搜索引擎
- 内部 HTTP API
- 工单系统
- 日历、邮件、审批接口
- 知识库检索器
所以 Tool 的本质不是"插件",而是:
让模型从语言生成器,升级成带决策能力的任务执行器。
官方文档里还特别强调了几个现实能力:
- 多次工具调用
- 动态工具选择
- 工具错误处理
- 状态持久化下的工具调用
这就意味着 Tool 不是一个孤立能力,而是 Agent 运行逻辑的一部分。
再看一个带 @tool 的例子
python
from langchain.agents import create_agent
from langchain.tools import tool
@tool
def search(query: str) -> str:
"""Search for information."""
return f"Results for: {query}"
@tool
def get_weather(location: str) -> str:
"""Get weather information for a location."""
return f"Weather in {location}: Sunny, 72F"
agent = create_agent(
model="openai:gpt-5",
tools=[search, get_weather],
)
这里的重点不是语法,而是它体现出的能力边界:
- Tool 有明确输入输出
- Tool 有明确语义描述
- Agent 运行时可以决定调哪个工具
这正是现代 Agent 和早期"纯 Prompt 调用"的分水岭。
📦 4. Structured Output:结构化输出层
这一层是很多工程项目里最容易被低估,但最不能少的一层。
因为业务系统要的往往不是一段"差不多能懂"的话,而是:
- JSON
- Schema 对象
- 分类标签
- 路由结果
- 参数提取结果
如果输出不结构化,就会出现一个很典型的问题:
- 人看着像对的
- 系统接起来全是错的
所以结构化输出,本质上是在解决:
如何让 LLM 的结果可被程序稳定消费。
这在下面这些场景里尤其明显:
- 让模型给流程选下一步节点
- 让模型返回 API 调用参数
- 让模型给工单打标签
- 让模型提取时间、地点、实体、优先级
一旦进入这些场景,"自由文本"往往就不是朋友,而是风险点。
🧱 5. Middleware:中间件层
这一层的意义,在生产环境特别明显。
因为真实系统里,几乎一定会碰到这些横切需求:
- 日志埋点
- 权限控制
- Prompt 注入
- 成本统计
- 审计追踪
- 限流与熔断
- 动态选择模型
- 动态过滤工具
如果这些逻辑都散落在业务代码里,系统会越来越难维护。
所以 Middleware 的价值,就是把这类通用治理能力抽出来。
一个很有代表性的官方模式:动态选模型
官方 Agents 文档给过一个很典型的例子:根据消息长度切换不同模型。
python
from langchain.agents import create_agent
from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
from langchain_openai import ChatOpenAI
basic_model = ChatOpenAI(model="gpt-4.1-mini")
advanced_model = ChatOpenAI(model="gpt-4.1")
@wrap_model_call
def dynamic_model_selection(request: ModelRequest, handler) -> ModelResponse:
message_count = len(request.state["messages"])
if message_count > 10:
model = advanced_model
else:
model = basic_model
return handler(request.override(model=model))
agent = create_agent(
model=basic_model,
tools=[],
middleware=[dynamic_model_selection],
)
这个例子特别能说明 LangChain 的工程思路:
- 不是把所有逻辑写死在 Agent 本体里
- 而是通过 middleware 把"横切控制"抽出去
这也是为什么 LangChain 不只是"提示词工具箱",而越来越像一个完整应用框架。
🤖 6. Agents:Agent 封装层
Agent 是很多人使用 LangChain 的入口。
但你要注意,Agent 不只是"让模型自己想一想"。
一个更工程化的理解是:
- 读取用户输入
- 理解当前上下文
- 判断要不要调工具
- 决定调哪个工具
- 根据工具结果继续推理
- 满足条件后结束
- 最后输出结果
这其实已经不是单次模型调用,而是一种"带决策能力的运行逻辑"。
也正因为如此,官方现在明确指出:
LangChain 的 agents 构建在 LangGraph 之上。
这句话非常关键,因为它说明了:
- LangChain 负责开发体验
- LangGraph 负责底层运行时编排
到这里,其实"LangChain 的核心组件有哪些"这个问题,已经自然回答完了。
如果你要压缩成一句话,就是:
Models、Messages/Context、Tools、Structured Output、Middleware、Agents,构成了 LangChain 的核心能力骨架。
🏗️ 五、LangChain 的核心架构,为什么说它本质上是"应用层框架"
理解完组件之后,我们再往上提一层,看它的架构。
LangChain 的核心架构,不应该只看成一条调用链,而应该看成一个应用层分层系统。
用户请求 / 外部事件
LangChain 应用层
消息与上下文管理
Prompt / Agent 决策
Tools 调用
结构化输出
Middleware 治理
LangGraph 运行时
Model Abstraction
数据库 / 搜索 / 业务 API
State / Checkpoint / Human-in-the-loop
这张图里,可以把 LangChain 架构理解成 4 层。
1. 能力接入层
负责接模型、接工具、接外部系统。
重点不是业务逻辑,而是统一接口和抽象边界。
这一层最像"能力适配器层"。
2. 上下文组织层
负责把消息历史、运行时上下文、记忆、系统提示词组织起来。
这一层直接决定模型"看到了什么"。
很多人调 Prompt 调了半天,实际上问题不在 Prompt,而在上下文边界乱了。
3. 决策与输出层
负责推理、工具选择、输出控制、结果结构化。
这是应用真正"智能"的地方。
但你要注意,所谓"智能"在工程上并不神秘,它通常只是:
- 让模型做判断
- 让模型给出结构化结果
- 让结果进入后续系统节点
所以智能和工程并不是两回事,它们在这一层恰好会合。
4. 运行时承接层
负责把 Agent 作为流程稳定跑起来。
注意:
这一层在今天已经越来越依赖 LangGraph。
也就是说,LangChain 的高层架构里,已经天然包含了一个事实:
它虽然是应用开发框架,但复杂 Agent 的运行时能力,正在更多地交给 LangGraph。
这也解释了为什么很多人一开始只学 LangChain,后来还是得回头补 LangGraph。
📌 一个最容易忽略的架构事实
LangChain 的强项,从来不是"最底层最可控",而是"高层抽象足够顺手"。
所以:
- 当你想快速搭起来,LangChain 很舒服
- 当你要强控制复杂流程,单靠 LangChain 的高层抽象就会不够
这就是 LangGraph 出场的原因。
⚠️ 六、为什么 LangGraph 会出现?因为复杂 Agent 根本不是一条直线
如果你的应用只是:
- 单轮问答
- 简单分类
- 一次工具调用
那么 LangChain 基本就够用了。
但一旦你开始做下面这些场景,问题马上就来了:
- 先规划,再执行
- 根据结果决定分支
- 调工具失败后重试
- 多轮反思与修正
- 长时间运行后恢复
- 某一步需要人工确认
这时候,如果你还把流程写成简单函数链,系统很快就会变得非常难维护。
因为复杂 Agent 的真实形态更像这样:
是
否
输入任务
规划节点
是否需要工具?
工具节点
结果写回状态
重新规划
总结输出
结束
这已经不是"调用顺序"问题了,而是"流程编排"问题。
很多团队在这里会经历一个很典型的演化过程:
- 先用一层函数调用串起来
- 发现需要 if / else 分支
- 再加 while 循环
- 再加异常重试
- 再加数据库状态记录
- 再加人工审核节点
- 最后代码像一团湿毛线
也正是在这个背景下,LangGraph 的价值才真正凸显出来。
💥 为什么说"复杂 Agent 不是直线"很重要?
因为很多问题本质上不是"模型更聪明一点"就能解决,而是流程本身具有下面这些特征:
- 非确定性
- 多轮反馈
- 外部依赖
- 中断恢复
- 审批介入
- 状态演进
而这类问题,天然适合用图和状态机来建模,而不是单纯用"链"来堆。
🚦 七、LangGraph 到底是什么?它本质上是在把 Agent 运行时状态机化
LangGraph 可以理解成一个专门面向 stateful agents 的编排框架。
它不是单纯帮你"画流程图",而是在解决下面这个核心问题:
如何把复杂、多步骤、可分支、可循环、可恢复的 Agent,作为一个有状态系统稳定跑起来。
所以你可以把 LangGraph 理解成:
- 不是高层"应用开发糖衣"
- 而是更底层的"流程运行时骨架"
如果用一句最直白的话概括:
LangGraph 就是把 AI Workflow 从函数链升级成状态图。
它和普通 DAG / 工作流工具有什么不一样?
很多人会问:
- 这不就是个流程图引擎吗?
表面上有点像,但关键差异在于:
- 它不是只编排静态步骤
- 它还编排状态更新
- 它天然面向消息与 Agent 推理循环
- 它强调持久化、人工介入和恢复执行
也就是说,它不是只关心"下一步是谁",还关心:
- 当前状态是什么
- 这一步对状态做了什么更新
- 如果中断了,下一次从哪恢复
- 如果人工改了状态,后续怎么继续
这就是它比"把几个函数连起来"更工程化的地方。
✅ 一个更准确的一句话定义
如果你被问"什么是 LangGraph",最推荐的回答不是"画图的框架",而是:
LangGraph 是一个面向有状态 Agent 的低层编排框架,它通过 state、node、edge、reducer 和 checkpoint 来驱动复杂流程执行。
🧠 八、LangGraph 的编排原理,到底在编排什么
说 LangGraph 是"图编排",很多人第一反应是:
- 有节点
- 有边
- 能跳转
这当然没错,但还不够。
LangGraph 真正编排的,不只是节点顺序,而是:
状态如何流动,节点如何读取状态、更新状态,以及流程如何基于状态继续演进。
这就是它和普通工作流工具的关键区别。
📌 1. State:整个图的共享状态中心
State 是 LangGraph 里最核心的对象之一。
它通常承载:
- 当前输入
- 消息历史
- 中间推理结果
- 工具调用结果
- 审核状态
- 最终输出
也就是说,流程不是靠函数一个个传参数,而是围绕一份共享状态逐步推进。
这件事看起来抽象,但工程价值巨大:
- 状态统一,参数不会满天飞
- 节点之间解耦更清晰
- 中断恢复时有明确落点
- 人工介入时也知道该改哪一块状态
🧩 2. Node:处理状态的逻辑节点
每个节点做一件相对清晰的事,例如:
- 规划
- 检索
- 调工具
- 校验
- 人工审批
- 最终整理结果
节点通常读取 state,并返回对 state 的更新。
这个设计的好处是:
- 节点职责单一
- 节点更容易测试
- 节点更容易替换或重组
如果一个节点里又做规划、又调接口、又格式化输出、又写数据库,那后面几乎一定会很难维护。
🔀 3. Edge:决定接下来去哪
边的作用不是"连接起来这么简单",而是决定:
- 固定往下走
- 走条件分支
- 回到前面循环
- 动态路由到别的节点
所以边的本质,是流程调度规则。
很多复杂 Agent 的真正复杂度,并不在单个节点里,而在"下一步到底怎么走"。
🪢 4. Reducer:解决状态合并问题
这是 LangGraph 一个非常值得注意的点。
当多个节点都可能更新同一份 state 时,就必须明确:
- 覆盖谁
- 合并谁
- 追加谁
- 哪些字段怎么拼
Reducer 就是在干这件事。
官方 Graph API 文档里也强调了:每个 state key 都有自己的 reducer;如果你不显式指定,默认就是覆盖。
这意味着:
- 简单字段默认覆盖没问题
- 列表、消息历史、多轮结果这些字段往往要更谨慎
尤其是消息列表,如果你只是简单覆盖,很容易把上下文冲掉。
💾 5. Checkpoint / Persistence:让流程可以中断和恢复
这是 LangGraph 非常核心的工程能力。
因为真实 Agent 流程经常不是几百毫秒就结束,有时候会:
- 跑很久
- 中途失败
- 等待人类输入
- 需要下次再继续
如果没有 checkpoint,这种流程一旦中断就只能重来。
所以 LangGraph 的持久化,不是锦上添花,而是很多业务落地的前提。
👤 6. Human-in-the-loop:让人工介入成为流程一部分
很多高风险场景根本不能全自动。
例如:
- 金融审批
- 合同修改确认
- 代码变更审核
- 生产环境操作放行
LangGraph 很强调:流程可以暂停、等待人类输入、然后继续执行。
这意味着它服务的不是"纯自动机器人",而是更真实的企业级智能流程。
📌 一个官方概念里很实用的点:MessagesState
LangGraph 官方 Graph API 里还提供了一个很常见的预置状态:MessagesState。
它的意义在于:
- 很多图都会维护
messages - 而消息列表的更新不能只是简单覆盖
- 需要用合适的 reducer 来追加、更新和反序列化消息
所以官方提供了 MessagesState,本质上是在帮你把"消息作为图状态"这件高频需求标准化。
📈 九、用一张图彻底看懂 LangGraph 的执行机制
Human Review Tool Node Planner Node Shared State LangGraph Runtime 用户/事件源 Human Review Tool Node Planner Node Shared State LangGraph Runtime 用户/事件源 alt [需要人工审核] 提交任务 初始化状态 执行规划节点 写入计划 根据状态判断下一条边 调用工具节点 写入工具结果 判断是否继续循环 暂停并等待输入 提交审核结果 更新审核状态 从 checkpoint 继续执行 返回最终结果
这张图背后,其实就是 LangGraph 编排原理的核心步骤:
- 初始化 state
- 执行 node
- node 更新 state
- runtime 根据 edge 和当前状态决定下一步
- 在关键节点保存 checkpoint
- 必要时暂停、恢复、人工介入
- 最后流转到结束节点
所以,LangGraph 编排的原理,最本质的一句话就是:
用 State + Nodes + Edges + Reducers + Checkpoint 驱动一个可分支、可循环、可恢复的 Agent 工作流。
一个更贴近代码的最小示意
下面这段代码不是为了炫 API,而是让你看到:LangGraph 的核心不是"节点函数本身",而是 节点只返回状态更新,图来负责状态演进。
python
from operator import add
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
user_input: str
plan: str
tool_results: Annotated[list[str], add]
final_answer: str
def planner_node(state: State):
return {"plan": f"Need to answer: {state['user_input']}"}
def tool_node(state: State):
# 这里用伪结果代替真实工具调用,重点是观察状态更新方式
return {"tool_results": ["retrieved context from external tool"]}
def final_node(state: State):
answer = f"Plan: {state['plan']}\nEvidence: {state['tool_results']}"
return {"final_answer": answer}
builder = StateGraph(State)
builder.add_node("planner", planner_node)
builder.add_node("tool", tool_node)
builder.add_node("final", final_node)
builder.add_edge(START, "planner")
builder.add_edge("planner", "tool")
builder.add_edge("tool", "final")
builder.add_edge("final", END)
graph = builder.compile()
result = graph.invoke({"user_input": "What is LangGraph?", "tool_results": []})
这段代码有两个非常重要的观察点:
- 节点不需要返回整个状态,只返回更新部分
tool_results用Annotated[list[str], add]指定了合并方式,不是默认覆盖
这正是 reducer 的价值所在。
再看一个官方概念味更浓的状态写法
如果你的流程就是围绕消息展开,那么 MessagesState 会更自然:
python
from langgraph.graph import MessagesState
class State(MessagesState):
documents: list[str]
这个例子虽然很短,但它非常有代表性:
- 消息历史作为状态一等公民
- 你可以在此基础上继续加自己的业务字段
这也是为什么说 LangGraph 不是"画图工具",而是"有状态运行时"。
⚖️ 十、LangChain 和 LangGraph 的区别,到底该怎么讲才不混乱
这是一个非常高频、但也最容易答虚的问题。
最常见的错误回答是:
- LangChain 做链
- LangGraph 做图
这不算错,但太浅了。
更推荐的讲法,是从"抽象层级"和"设计目标"两个角度说。
1. 抽象层级不同
- LangChain 更高层:关注开发体验、组件组合、Agent 封装
- LangGraph 更底层:关注状态流转、执行控制、流程持久化
2. 设计目标不同
- LangChain 重点是"怎么更快开发 AI 应用"
- LangGraph 重点是"怎么把复杂 Agent 稳定跑起来"
3. 适用场景不同
| 场景 | 更适合谁 |
|---|---|
| 简单问答、摘要、分类、轻量工具调用 | LangChain |
| 多步骤规划、复杂分支、长任务恢复、人机协同 | LangGraph |
4. 两者关系不是替代,而是上下层协作
这是最重要的一点。
官方文档已经很明确:
LangChain 的 agents 是建立在 LangGraph 之上的。
所以更准确的理解应该是:
- LangChain 提供上层开发抽象
- LangGraph 提供底层流程运行时
也就是说,它们不是二选一,而更像:
一个偏"写起来方便",一个偏"跑起来可靠"。
📌 一个非常实用的选型建议
如果你现在的需求是:
- 先把应用搭出来
- 工具不多
- 分支不复杂
- 暂时不做人审和恢复
那 LangChain 往往就够了。
但如果你已经出现下面这些信号:
- 工具调用要循环很多轮
- 会话任务可能跨很长时间
- 需要节点级状态控制
- 需要失败后从中间恢复
- 需要人工接管某一步
那你就该认真进入 LangGraph 了。
📚 十一、那 LlamaIndex 应该放在哪?它更像 RAG 系统里的"数据层专家"
讲到这里,就该轮到 LlamaIndex 了。
如果说 LangChain 和 LangGraph 解决的是"应用与流程"问题,那么 LlamaIndex 更擅长解决的是:
如何把外部知识、企业文档、检索索引、查询引擎接进 LLM 系统。
所以它最适合放在 RAG 的数据层。
它通常更强的地方在于:
- 数据接入(ingestion)
- 文档解析
- 索引构建
- Retriever / Query Engine 抽象
- RAG 查询链路组织
很多团队在做企业知识库时会有一个典型痛点:
- 模型能力和 Agent 流程都已经接好了
- 但数据入口很乱
- 索引构建和查询逻辑也没有统一抽象
这时候,LlamaIndex 往往正好补上的是"数据层能力缺口"。
为什么说它是"数据层专家"?
因为它更聚焦这些事情:
- 文档从哪里来
- 文档怎么切块
- 元数据怎么组织
- 索引怎么建立
- 查询时怎么拿到适合上层应用消费的结果
而这些问题,本来就不应该全塞进 LangChain Agent 节点里。
所以 LlamaIndex 的合理位置,不是"替代整个 Agent 框架",而是:
作为上层 Agent / Workflow 的知识检索后端。
🔗 十二、LlamaIndex 如何和 LangChain 结合?最常见的是这三种方式
1. LangChain 做应用与 Agent,LlamaIndex 做检索与查询
这是最常见、也最自然的一种组合。
用户问题
LangChain Agent / App
LlamaIndex Retriever / Query Engine
索引 / 向量库 / 文档源
答案输出
在这个模式里:
- LangChain 负责 Agent、提示词、工具路由、结构化输出
- LlamaIndex 负责文档摄取、索引构建、检索、查询引擎
这就是最典型的"应用层 + 数据层"分工。
2. 在 LlamaIndex 里复用 LangChain 的 LLM 适配
LlamaIndex 官方提供了 LangChain LLM 适配器,所以你可以在 LlamaIndex 中复用 LangChain 已经统一好的模型接入。
python
from langchain_openai import ChatOpenAI
from llama_index.llms.langchain import LangChainLLM
lc_llm = ChatOpenAI(model="gpt-4.1-mini", temperature=0)
llm = LangChainLLM(llm=lc_llm)
这种方式适合:
- 你已经用 LangChain 统一了模型层
- 但检索和查询逻辑希望交给 LlamaIndex
这样做的好处是:
- 模型配置只维护一份
- 数据层不会自己再维护另一套 LLM 接入逻辑
- 上下游边界更清晰
3. 在 LlamaIndex 里复用 LangChain 的 Embeddings
LlamaIndex 也提供了 LangChain Embeddings 适配器。
python
from llama_index.core import Settings
from llama_index.embeddings.langchain import LangchainEmbedding
# lc_embedding 按你的 LangChain provider 创建
Settings.embed_model = LangchainEmbedding(lc_embedding)
这个模式适合:
- 公司已经统一了 embedding 服务
- 但索引构建、检索层仍然想使用 LlamaIndex
本质上,它是在做一件很工程化的事:
模型层和数据层各用所长,但底层能力不要重复配置。
4. 一个更贴近项目落地的组合姿势
除了上面两个 adapter,真正项目里更常见的写法是:
- 用 LlamaIndex 构建查询引擎
- 再把这个查询引擎包装成 LangChain 可调用工具
- 最后交给 LangChain Agent 或 LangGraph 流程使用
下面这个示例偏工程示意,重点看职责分层,不强调逐行可运行:
python
from langchain.tools import tool
# 假设你已经在 LlamaIndex 里构建好了 query_engine
# query_engine = index.as_query_engine()
@tool
def kb_search(question: str) -> str:
"""Search enterprise knowledge base."""
response = query_engine.query(question)
return str(response)
agent = create_agent(
model="openai:gpt-5",
tools=[kb_search],
)
这个组合非常典型,因为它体现了清晰边界:
- LlamaIndex 负责查知识
- LangChain 负责决定"什么时候去查"
- LangGraph 负责把整条复杂流程稳定跑完
这三层一旦边界清楚,系统维护成本会低很多。
🏢 十三、如果把三者放进一套企业系统里,最合理的架构通常长什么样
如果你要做的是企业知识库助手、文档问答系统、流程型 Agent,比较推荐的分层通常是这样:
| 层级 | 负责内容 | 更常见的选择 |
|---|---|---|
| 接口层 | Web / API / Chat UI | 前端、FastAPI、网关 |
| 应用层 | Prompt、工具、结构化输出、Agent 入口 | LangChain |
| 编排层 | 分支、循环、状态持久化、人机协同 | LangGraph |
| 数据层 | 文档接入、索引、检索、查询引擎 | LlamaIndex |
| 基础设施层 | 向量库、对象存储、日志监控 | Milvus、pgvector、S3、可观测系统 |
用图看会更直观:
是
否
用户请求
LangChain 应用层
LangGraph 编排层
是否需要外部知识?
LlamaIndex 数据层
文档索引 / 向量库
直接调用工具 / 模型
状态持久化 / 人工审核
最终结果
这套架构的好处是:
- 组件职责清晰
- Agent 逻辑不会和检索实现缠在一起
- 检索系统能单独优化
- 流程系统能单独治理
- 更适合后期扩展与多人协作
🔍 这套架构为什么更稳?
因为它遵守了一个常被忽略的原则:
把变化频率不同的东西拆开。
举个例子:
- 模型选择可能经常变
- 检索策略可能也经常变
- 但审批流程和业务状态机不一定天天变
如果这些东西全写在同一层,系统一改就会牵一大片。
而分层之后:
- 想换 embedding,不一定动 Agent 流程
- 想改审批分支,不一定重写知识库检索
- 想换模型,不一定推翻整个数据层
这就是架构边界的真正价值。
⚠️ 十四、真正落地时最容易踩的坑,不在框架本身,而在边界设计
很多团队不是不会用框架,而是不会做边界设计。
最容易踩坑的地方,通常有下面这些:
| 坑点 | 典型表现 | 更推荐的做法 |
|---|---|---|
| 把 LangChain 当成全栈解决方案 | 检索、状态、流程全塞在一起 | 明确应用层与流程层边界 |
| 把 LangGraph 当成"画图工具" | 图很漂亮,但没有真正利用持久化与恢复 | 按运行时系统思维设计 |
| 把 LlamaIndex 逻辑写死在 Agent 节点里 | 一改检索策略就全链路受影响 | 用 Retriever / Query Engine 抽象隔离数据层 |
| State 设计过大 | 什么都往状态里塞 | 只保留流程必需数据 |
| 上下文重复拼接 | 消息历史和检索结果不断叠加 | 统一上下文组装策略 |
| 没有退出条件 | Agent 一直循环调用工具 | 明确最大轮次、失败策略与人工兜底 |
再把这些坑翻译成人话
很多系统最后出问题,不是因为选错框架,而是因为:
- 本来该是数据层的逻辑,被写进 Agent 提示词里了
- 本来该由状态机控制的流程,被塞进一堆 if/else 里了
- 本来该结构化输出的节点,还在回自由文本
- 本来该中断恢复的长流程,只能失败重来
所以你会发现,真正难的从来不是"会不会调框架 API",而是:
你能不能把系统拆成应用层、流程层、数据层这几个清晰边界。
✅ 一个很实用的自检清单
如果你想判断自己的设计是不是已经有点混了,可以快速问自己 5 个问题:
- 这个逻辑到底属于应用层、编排层,还是数据层?
- 这个状态应该存在图状态里,还是只存在单次调用上下文里?
- 这个返回结果是给人看的,还是给程序消费的?
- 如果这里中断了,我能从中间恢复吗?
- 如果我要替换检索实现,需要改多少上层代码?
如果这 5 个问题里有 3 个回答不清楚,说明你的边界大概率已经开始混了。
✅ 十五、最后再把你最关心的几个问题,压缩成一张速答表
到这里,前面的问题其实都已经融在正文里讲完了。
如果你想最后快速复习,可以直接看这张表。
| 问题 | 简洁回答 |
|---|---|
| 什么是 LangChain? | 一个面向 LLM 应用和 Agent 开发的高层框架,不只是"链式调用库" |
| LangChain 的核心组件有哪些? | Models、Messages/Context、Tools、Structured Output、Middleware、Agents |
| LangChain 核心架构是什么样的? | 本质上是"应用开发层"架构:统一模型与工具接入、组织上下文、控制输出,并把复杂运行时交给 LangGraph |
| 什么是 LangGraph? | 一个面向有状态、多步骤、可恢复 Agent 的图编排框架 |
| LangGraph 编排的原理是什么? | 用 State、Nodes、Edges、Reducers、Checkpoint 驱动流程演进 |
| LangChain 和 LangGraph 有什么区别? | LangChain 偏应用开发抽象,LangGraph 偏流程运行时编排;两者更像上下层关系 |
| LlamaIndex 如何与 LangChain 结合? | 通常由 LangChain/LangGraph 负责应用和流程,LlamaIndex 负责 RAG 数据接入、索引与检索 |
如果只允许你记一句话,那我建议你记这个版本:
LangChain 解决"怎么开发 AI 应用",LangGraph 解决"怎么让复杂 Agent 稳定运行",LlamaIndex 解决"怎么把私有知识高质量接进系统"。
💡 十六、总结
最后我们把整篇文章收一下。
很多人一开始学这几个框架,会觉得它们名字都很像,能力边界也很容易混。
但如果你站在系统分层的角度看,逻辑其实非常清晰:
- LangChain 主要解决应用开发问题
- LangGraph 主要解决流程编排与运行时问题
- LlamaIndex 主要解决 RAG 数据接入与检索问题
所以真正成熟的选型思路,不是问"我到底该选谁",而是问:
- 我现在缺的是应用开发抽象?
- 还是复杂流程运行时?
- 还是私有知识的数据层能力?
想清楚这个问题,你对这三个框架的理解,就已经超过很多只会背定义的人了。
📌 最后给一个落地建议
如果你现在正准备做项目,我会给你一个很实用的起步顺序:
- 先用 LangChain 把最小应用跑起来
- 当流程复杂度上来后,再把关键链路迁到 LangGraph 思维里
- 一旦涉及企业知识库或 RAG,再引入 LlamaIndex 做数据层抽象
这个顺序的好处是:
- 不会一开始就学得太重
- 也不会在复杂度上来之后被迫重写全部系统
换句话说:
先搭应用,再稳流程,最后把数据层做扎实。
这往往比一开始追求"最全框架组合拳"更现实。
🔗 参考资料
以下为本文整理时参考的官方资料:
- LangChain Overview: https://docs.langchain.com/oss/python/langchain/overview
- LangChain Agents: https://docs.langchain.com/oss/python/langchain/agents
- LangGraph Graph API / Low-level concepts: https://docs.langchain.com/oss/python/langgraph/graph-api
- LlamaIndex LangChain LLM Adapter: https://developers.llamaindex.ai/python/framework-api-reference/llms/langchain/
- LlamaIndex LangChain Embeddings Adapter: https://developers.llamaindex.ai/python/framework-api-reference/embeddings/langchain/