【LangGraph01】—— “从零认识 LangGraph:一个 Hello World 搞懂图编排“
从零认识 LangGraph:一个 Hello World 搞懂图编排
搞 AI 应用开发的人,迟早会碰到一个问题:怎么让 LLM 不只是"问答一轮就完事",而是能多步协作、记住上下文、有条件分支地完成复杂任务?
LangGraph 就是为这个场景而生的。它不关心你怎么调模型、怎么写 prompt,只管一件事——编排:把多个处理步骤串成一张图,数据沿着图流动,最终输出结果。
这篇博客从一个最简单的 Hello World 出发,把 LangGraph 的核心概念拆开讲清楚。读完你能回答三个问题:LangGraph 是什么?它解决什么问题?那十几行代码到底在干嘛?
一、LangGraph 是什么
一句话:LangGraph 是 LangChain 生态里的图编排框架,用来构建有状态、多步骤的 AI Agent 工作流。
它的定位很"底层"。不抽象 prompt,不预设模型调用方式,只提供图(Graph)的构建和执行能力。你可以把它想象成一个"流程图引擎"——你定义好节点和连线,它负责按顺序执行、管理中间状态。
和 LangChain 的关系:
| 产品 | 定位 | 一句话说清 |
|---|---|---|
| LangChain | Agent 框架 | 提供模型调用、工具集成、Agent 循环等上层抽象 |
| LangGraph | 编排运行时 | 提供图结构、状态管理、持久化、人机协作等底层能力 |
| LangSmith | 可观测平台 | 链路追踪、评估、部署,贯穿开发到生产 |
三者可以搭配用,也可以各用各的。LangGraph 不强制依赖 LangChain,你可以用任何模型 SDK 作为节点实现。
为什么需要"图编排"
直接调 LLM 是线性的:发一条消息,收一条回复。但真实场景远比这复杂:
- 客服 Agent 需要先判断意图,再走不同分支(退款 / 查询 / 转人工)
- 数据分析 Agent 需要先生成 SQL,执行后发现结果为空,得重试
- 审批流需要中间插入人工审核节点
这些场景用简单的顺序调用很难优雅处理。LangGraph 用图来描述这种流程——节点是处理步骤,边是流转条件,状态在节点之间传递和累积。
二、核心概念拆解
下面结合代码逐个讲。先贴完整代码,12 行,一个完整的 LangGraph 应用:
from langgraph.graph import StateGraph, MessagesState, START, END
def mock_llm(state: MessagesState):
return {"messages": [{"role": "ai", "content": "hello world"}]}
graph = StateGraph(MessagesState)
graph.add_node(mock_llm)
graph.add_edge(START, "mock_llm")
graph.add_edge("mock_llm", END)
graph = graph.compile()
graph.invoke({"messages": [{"role": "user", "content": "hi!"}]})
2.1 StateGraph — 状态图
graph = StateGraph(MessagesState)
StateGraph 是 LangGraph 最核心的类。创建图的时候,需要告诉它"状态长什么样"——这里传入的 MessagesState 就是状态的定义。
说白了,StateGraph 就是一张空白画布,MessagesState 规定了画布上流转的数据格式。
2.2 MessagesState — 消息状态
from langgraph.graph import MessagesState
MessagesState 是 LangGraph 内置的状态类型,结构极简:
class MessagesState(TypedDict):
messages: list # 消息列表
列表里每个元素是一条消息,包含两个字段:
| 字段 | 含义 | 常见值 |
|---|---|---|
role |
谁说的 | "user" / "ai" / "system" |
content |
说了什么 | 文本内容 |
这跟 OpenAI Chat API 的消息格式是一脉相承的。如果你用过 OpenAI 的 messages 参数,这里毫无障碍。
当然,你也可以自定义状态结构,不止是消息列表。比如加一个 step_count 计数器、一个 current_intent 分类结果等。MessagesState 只是最简单的起点。
2.3 节点(Node)— 执行单元
def mock_llm(state: MessagesState):
return {"messages": [{"role": "ai", "content": "hello world"}]}
节点就是一个普通 Python 函数。 没有基类、没有装饰器、没有魔法。
规矩很简单:
- 入参:接收当前完整状态(字典)
- 返回值:返回一个字典,LangGraph 会自动把它合并到当前状态中
这里的 mock_llm 做的事:读取当前状态(虽然没用到),返回一条新的 AI 消息。LangGraph 会把这条消息追加到 messages 列表末尾。
🔴 重点: 节点函数名叫什么,这个节点就叫什么。def mock_llm(...) 注册后,节点名就是 "mock_llm"。后面 add_edge 里引用的也是这个名字。
为什么叫 mock_llm?因为它没有真的调任何模型,只是固定返回 "hello world"。这是故意的——先跑通流程,再接真实模型。
2.4 边(Edge)— 连接节点
graph.add_edge(START, "mock_llm")
graph.add_edge("mock_llm", END)
边定义了数据往哪流。START 和 END 是 LangGraph 内置的特殊节点,分别代表图的入口和出口。
画出来就是:
START → mock_llm → END
最朴素的线性结构。实际项目中可以有分支(条件边)、循环(回到某个节点)、并行(多个节点同时执行),但 Hello World 阶段先不展开。
2.5 compile() — 编译
graph = graph.compile()
定义好节点和边之后,调 compile() 把图编译成可执行对象。这一步会做结构校验——节点有没有注册、边有没有断开、循环有没有死锁风险。
类比一下:写完代码要编译才能跑,compile() 就是这个"编译"动作。
2.6 invoke() — 执行
graph.invoke({"messages": [{"role": "user", "content": "hi!"}]})
传入初始状态,触发整个图的执行。完整流程:
- 初始状态:
messages = [{"role": "user", "content": "hi!"}] - 流入
mock_llm节点 - 节点返回:
{"messages": [{"role": "ai", "content": "hello world"}]} - LangGraph 自动合并,最终
messages里有两条消息 - 到达
END,执行结束
最终状态长这样:
{
"messages": [
{"role": "user", "content": "hi!"},
{"role": "ai", "content": "hello world"}
]
}
就这么简单。一条用户消息进去,一条 AI 消息出来,中间经历了一次图编排。
三、图的执行模型:数据怎么流动的
理解了单个概念,再串起来看数据流。
初始状态 {"messages": [{"role": "user", "content": "hi!"}]}
│
▼
START(入口,不做任何处理)
│
▼
┌─────────────┐
│ mock_llm │ ← 读取状态,返回新消息
└─────────────┘
│
▼
END(出口,结束执行)
│
▼
最终状态 {"messages": [用户消息, AI消息]}
核心机制是状态累积。每个节点不是"替换"状态,而是往状态里追加数据。messages 列表从 1 条变成 2 条,这个列表就是整个图的"记忆"。
如果后面接上真正的 LLM 节点,它就能读到完整的对话历史,实现多轮对话。这就是"有状态"的意义。
四、LangGraph 能做什么(超越 Hello World)
Hello World 只展示了最基础的线性流程。LangGraph 真正的威力在于:
持久化执行 — 图执行到一半挂了,可以从断点恢复,不用从头跑。对长周期任务(比如需要几小时的数据处理流水线)很有用。
人机协作(Human-in-the-loop) — 图执行到某个节点时可以暂停,等人工审核、修改状态后再继续。审批流、敏感操作拦截都靠这个。
短期 + 长期记忆 — 短期记忆就是当前图的状态(messages 列表);长期记忆可以跨会话持久化,让 Agent 记住"上次用户说过什么"。
条件分支 — 根据状态决定走哪条边。比如"如果用户想退款,走退款节点;如果想查询,走查询节点"。
可视化调试 — 配合 LangSmith,可以看到每次执行的完整链路、状态变化、耗时分布。
这些能力在 Hello World 里一个都看不到,但它们是 LangGraph 存在的理由。
五、安装与环境
pip install -U langgraph
本文以 Python 3.10+ 为例。LangGraph 支持 Python 3.9 及以上,但 3.10 以上体验更好。
如果你想用 LangSmith 做链路追踪,还需要设置环境变量:
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=你的API密钥
LangSmith 有免费额度,注册即可用。开发阶段强烈建议开着——调试 Agent 行为时,可视化链路比 print 大法好用太多。
六、避坑与常见问题
节点函数返回值格式不对
节点必须返回字典,且 key 要跟状态结构匹配。返回列表、字符串、或者 key 写错(比如 message 而不是 messages),都会报错或静默丢数据。
验证方式:在节点函数末尾加 print(result) 看返回值。
add_node 和 add_edge 搞混
add_node 注册节点,add_edge 定义连接。两者都要调,少一个都会出问题。顺序无所谓——可以先注册节点再连边,也可以反过来。
忘记调 compile()
定义好图之后不 compile(),直接调 invoke() 会报 Graph 对象没有 invoke 方法。这是新手最常踩的坑。
节点名引用错误
add_edge(START, "mock_llm") 里的字符串必须跟函数名完全一致。写成 "MockLLM" 或 "mock_llm_node" 都会报找不到节点。
七、总结:你真正需要记住的事
- LangGraph 是图编排框架,专注 Agent 工作流的编排,不碰模型调用本身。
- 状态是核心 — 所有节点共享一份状态,节点通过读取和追加状态来协作。
- 节点就是普通函数 — 入参是状态,返回值是状态的增量,没有魔法。
- 边定义流转 —
START和END是内置的起止点,中间是你自己定义的节点。 - 先跑通再迭代 — Hello World 不需要真实 LLM,用 mock 数据把流程跑通,再逐步替换。
验证清单
- 能独立写出
helloworld.py并成功运行 - 能解释
StateGraph、MessagesState、节点、边各自的作用 - 知道
compile()和invoke()分别做什么 - 理解状态是如何在节点之间流动和累积的
- 能画出这个 Hello World 的图结构
参考资源
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)