Appearance
6. 什么是 LangGraph?它与 LangChain 有什么区别?
难度 P0 必背 · 岗位 应用 · 频率 ★★★ · 预计阅读 14 min
本题阅读地图
- 💡 简要回答
- 📝 详细解析
- 🎯 面试总结
👔面试官:听说过 LangGraph 吗?它是做什么的,跟 LangChain 什么关系?
🙋♂️我:LangGraph 是 LangChain 的扩展吧,可以做更复杂的 Agent 工作流。
👔面试官:具体扩展了什么?LangChain 的 Chain 有什么局限?
🙋♂️我:Chain 是线性的……只能一步一步执行?LangGraph 可以支持循环?
👔面试官:对。那为什么需要循环?ReAct Agent 不就是循环吗?
🙋♂️我:ReAct 是循环,但在 LangChain 里实现比较麻烦?LangGraph 让循环更自然?
👔面试官:接近了。LangGraph 把 Agent 的执行过程建模为「有状态图」,节点是函数,边是流转关系,可以显式表达循环、条件分支、状态共享。还有个关键特性是「Human-in-the-loop」,知道是什么吗?
🙋♂️我:人工介入?在关键节点暂停,等人工确认再继续?
👔面试官:对。这在生产环境非常重要,比如执行危险操作前需要人工审批。下面详细说一下。
TL;DR 速记
- 是什么:LangGraph 是基于 LangChain 的有状态图框架,把 Agent 执行过程建模成节点和边。
- 解决什么:补上 Chain 不擅长的循环、条件分支、显式状态、人机协同和中断恢复。
- 怎么答:简单线性流程用 LangChain/LCEL,复杂 Agent 工作流用 LangGraph;核心差异是“线性链”变成“可恢复的状态图”。
图解
💡 简要回答
LangGraph 是基于 LangChain 的有状态图(Stateful Graph)工作流框架,把 Agent 的执行过程建模为节点(Node)和边(Edge)的有向图。
相比 LangChain 的线性 Chain,LangGraph 的核心优势:
- 支持循环:节点可以跳回前面的节点(ReAct 的推理循环)
- 条件分支:边可以有条件,根据不同状态走不同路径
- 显式状态:所有状态保存在 TypedDict 中,节点间共享
- Human-in-the-loop:支持在任意节点暂停,等待人工介入
- 状态持久化:可以中断恢复,适合长任务
📝 详细解析
为什么需要 LangGraph
LangChain 的 Chain 是线性的:A → B → C,适合简单流程。但复杂 Agent 需要:
规划 → 执行 → 检查 →(未完成)→ 回到规划
↓
(完成)→ 结束这种循环、条件分支在 Chain 里很难优雅实现。
LangGraph 的解决思路:把执行流程建模为有向图。
核心概念:State、Node、Edge
python
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator
# 1. 定义状态(所有节点共享的「内存」)
class AgentState(TypedDict):
messages: Annotated[list, operator.add] # 消息历史,累加模式
current_step: str # 当前步骤标识
execution_count: int # 执行次数(防死循环)
# 2. 定义节点(每个节点是一个函数)
def plan_node(state: AgentState):
"""规划节点:决定下一步做什么"""
plan = llm.invoke(f"基于历史:{state['messages']}\n制定计划")
return {
"messages": [("assistant", plan)],
"current_step": "execute",
"execution_count": state.get("execution_count", 0) + 1
}
def execute_node(state: AgentState):
"""执行节点:调用工具"""
tool_result = tools.execute(state["messages"][-1].content)
return {
"messages": [("tool", tool_result)],
"current_step": "check"
}
def check_node(state: AgentState):
"""检查节点:判断是否完成"""
# 这个节点返回的不是状态更新,而是下一步去哪个节点
if is_task_complete(state["messages"]):
return "done" # 去结束节点
elif state["execution_count"] > 10:
return "max_iterations" # 去错误处理
else:
return "continue" # 继续规划
# 3. 构建图
graph = StateGraph(AgentState)
graph.add_node("plan", plan_node)
graph.add_node("execute", execute_node)
graph.add_node("check", check_node)
# 4. 添加边
graph.add_edge("plan", "execute")
graph.add_edge("execute", "check")
# 条件边:根据 check_node 的返回值决定下一步
def route_check(state):
return state["next_step"]
graph.add_conditional_edges(
"check",
route_check,
{
"continue": "plan", # 未完成,循环回规划
"done": END, # 完成,结束
"max_iterations": "error_handler"
}
)
graph.set_entry_point("plan")
app = graph.compile()
# 5. 运行
result = app.invoke({
"messages": [("user", "帮我查竞品信息并整理报告")],
"current_step": "plan"
})LangChain vs LangGraph 对比
| 维度 | LangChain Chain | LangGraph |
|---|---|---|
| 执行模型 | 线性(A→B→C) | 有向图(支持任意拓扑) |
| 循环支持 | ❌ 不支持 | ✅ 天然支持 |
| 条件分支 | ❌ 需要额外逻辑 | ✅ 条件边 |
| 状态管理 | 隐式(Memory) | 显式(TypedDict) |
| 可视化 | ❌ 无 | ✅ Mermaid 图 |
| 人工介入 | ❌ 不支持 | ✅ Human-in-the-loop |
| 中断恢复 | ❌ 不支持 | ✅ 检查点持久化 |
| 适用场景 | 简单线性流程 | 复杂多步骤 Agent |
Human-in-the-loop 人工介入
生产环境很多场景需要人工审批:
python
from langgraph.checkpoint.sqlite import SqliteSaver
# 创建检查点存储
checkpointer = SqliteSaver.from_conn_string("agent_state.db")
# 编译图,在 execute 节点前设置中断点
app = graph.compile(
checkpointer=checkpointer,
interrupt_before=["execute"] # 执行前暂停
)
# 第一次调用,执行到 execute 前暂停
thread_id = "task_001"
result = app.invoke(
initial_state,
config={"configurable": {"thread_id": thread_id}}
)
# → 暂停,等待人工确认
# 人工确认后,继续执行
app.invoke(None, config={"configurable": {"thread_id": thread_id}})适用场景:
- 执行危险操作前(删除数据、转账)
- 调用敏感 API 前
- 生成内容发布前审核
- 预算超限时的确认
状态持久化:长任务的保障
python
# 任务执行过程中,状态自动保存到检查点
# 即使程序崩溃,也可以从检查点恢复
# 查询当前状态
snapshot = app.get_state(config)
print(snapshot.values) # 当前所有状态
print(snapshot.next) # 下一个要执行的节点
# 从任意检查点恢复
app.invoke(None, config) # 继续执行常见踩坑与反例
踩坑 1:只说“LangGraph 支持循环”
错误描述:「LangGraph 就是能把节点连回去。」
正确做法:循环只是表象。面试要讲到有状态图、条件边、共享状态、检查点、人机协同,这些才是生产价值。
踩坑 2:把 State 当普通全局变量
错误描述:「节点之间用变量传一下就行。」
正确做法:State 是图执行的契约。字段、更新方式、累加策略都要显式定义,否则调试、恢复和并发执行都会混乱。
踩坑 3:迁移时全量重写 Chain
错误描述:「上 LangGraph 就要把原来的 LangChain 全拆掉。」
正确做法:简单链路继续保留,复杂分支和循环才迁到 Graph。LCEL 链也可以包装成节点逐步迁移。
踩坑 4:忽略检查点和人工介入
错误描述:「Graph 跑起来就行,暂停恢复以后再说。」
正确做法:长任务、危险操作、审核发布都要提前设计 checkpointer 和 interrupt,否则无法恢复,也无法在关键节点审批。
面试官可能继续追问
追问 1:LangGraph 的 State 应该怎么设计? 答题要点:先定义任务必需字段,如 messages、step、tool_result、status;区分覆盖字段和累加字段;避免把无关大对象都塞进状态。
追问 2:Human-in-the-loop 怎么落地? 答题要点:编译图时设置 interrupt 节点,配合 checkpointer 保存 thread 状态;人工确认后用同一个 thread_id 继续执行。
追问 3:什么时候不该用 LangGraph? 答题要点:线性、短链路、无循环、无状态恢复需求的任务没必要上 Graph,LCEL 或普通 Workflow 更简单。
追问 4:循环失控怎么防? 答题要点:在 State 中记录步数、失败次数和状态终态;路由函数同时判断任务完成、最大步数、超时和转人工条件。
🎯 面试总结
LangGraph 解决的是 LangChain Chain 「只能线性执行」的局限。
面试回答抓住四个核心:
- 图模型:节点(函数)+ 边(流转),支持循环和条件分支
- 显式状态:TypedDict 共享内存,所有节点可操作
- Human-in-the-loop:任意节点可暂停,等待人工确认
- 状态持久化:检查点机制,支持中断恢复
选型建议:简单流程用 LangChain,复杂 Agent 用 LangGraph。现在很多项目直接用 LangGraph 构建 Agent,跳过 Chain 那层抽象。
第五分类「五、AI Agent」全部完成,共覆盖题目 158-200(Agent 基础/CoT/ReAct/工具调用/MCP/多 Agent/记忆/LangChain/LangGraph)
第五分类「五、AI Agent」全部完成,共覆盖题目 158-200(Agent 基础/CoT/ReAct/工具调用/MCP/多 Agent/记忆/LangChain/LangGraph)