LangGraph 源码拆解,Graph 基类与 StateGraph
一、读源码的重要性
很多人觉得 “用框架不用看源码”,但 LangGraph 的核心逻辑都藏在两个类里:Graph
(图的基础)和StateGraph
(带状态的图)。看懂它们,你不仅能解决 90% 的 “调试难题”,还能自定义扩展功能(比如加个新的边类型)。
二、Graph 基类:所有图的祖先
Graph
类是 LangGraph 的 “基础骨架”,负责管理节点、边和分支逻辑。我们先看它的核心属性和方法(源码简化版):
1. 核心属性:图的 “基础配置”
from collections import defaultdict
from typing import Any, Callable, Dict, Set, Tupleclass Graph:def __init__(self):self.nodes: Dict[str, Any] = {} # 存所有节点:key是节点名,value是节点逻辑self.edges: Set[Tuple[str, str]] = set() # 存普通边:(起始节点名, 目标节点名)self.branches: defaultdict = defaultdict(dict) # 存条件边:按条件映射节点self.compiled = False # 标记图是否已编译(编译后才能执行)
这些属性的作用很直白:nodes
管 “有哪些节点”,edges
管 “节点怎么连”,branches
管 “条件分支”,compiled
确保图结构不被随意修改。
2. 核心方法:图的 “操作工具”
你日常开发会用到的方法,都在这里:
add_node(node_name, action)
:添加节点,比如把一个 Python 函数封装成 “工具调用节点”;add_edge(start_node, end_node)
:加普通边,比如add_edge("llm_node", "action_node")
;add_conditional_edges(source, path, path_map)
:加条件边,path
是判断函数,path_map
是 “条件→节点” 的映射;set_entry_point(node_name)
:设入口点(图从哪个节点开始);compile()
:编译图,会检查 “有没有孤立节点”“入口点是否存在”,通过后才能执行。
三、StateGraph:给图加 “记忆” 的关键
Graph
类只管 “结构”,不管 “数据”;StateGraph
继承自Graph
,核心是加了 “状态管理”,让节点间能传递数据。
1. 什么是 “状态(State)”?
状态就是一个 “全局字典”,但不是随便写的 —— 需要用TypedDict
定义结构(确保数据类型安全)。比如你要做一个 “问答系统”,状态可以这样定义:
from typing import TypedDict# 输入状态:用户的问题
class InputState(TypedDict):question: str# 输出状态:AI的回答
class OutputState(TypedDict):answer: str# 整体状态:合并输入和输出,节点间共享
class OverallState(InputState, OutputState):pass
这样定义后,每个节点的输入 / 输出都必须符合OverallState
的结构,不会出现 “节点 A 输出result
,节点 B 要读answer
” 的报错。
2. StateGraph 的核心用法
创建StateGraph
时,必须指定状态结构,示例代码:
from langgraph.graph import StateGraph# 1. 初始化:指定整体状态、输入和输出模式
builder = StateGraph(state_schema=OverallState, # 整体状态结构input_schema=InputState, # 输入数据结构output_schema=OutputState # 输出数据结构
)# 2. 加节点、加边(后续博客会详细讲)
builder.add_node("llm_node", llm_process_function) # 加LLM处理节点
builder.add_edge("llm_node", "output_node") # 加普通边# 3. 编译图
graph = builder.compile()
四、小结:从源码看 LangGraph 的设计思路
LangGraph 的源码逻辑很清晰:
- 用
Graph
类打 “结构框架”,负责节点和边的管理; - 用
StateGraph
加 “数据层”,通过TypedDict
确保状态安全; - 所有操作都围绕 “可复用、可扩展”,比如子图节点支持模块化,条件边支持动态决策。
下一篇博客,我们会动手写代码 —— 从节点和边的实现,到第一个完整的 LangGraph 应用。