LangGraph 执行流程解析

LangGraph 执行流程深度解析

StateGraph.compile() → CompiledStateGraph.stream() 完整执行链路


📋 概述

核心概念

LangGraph 是基于 LangChain 的状态图框架,用于构建有状态的多智能体应用。

  • StateGraph:构建器模式,负责定义图的结构
  • CompiledStateGraph:编译后的可执行图,支持 invoke、stream 等方法
graph TD A[StateGraph 定义] --> B[添加节点和边] B --> C[compile 编译] C --> D[CompiledStateGraph] D --> E[stream 流式执行] D --> F[invoke 同步执行] E --> G[迭代器输出] F --> H[一次性返回]

🔧 第一部分:StateGraph.compile() 执行流程

步骤解析

1. 初始化 StateGraph 构建器

创建 StateGraph 实例,定义状态类型(StateT)、上下文类型(ContextT)、输入类型(InputT)和输出类型(OutputT)

2. 添加节点(add_node)

注册图中的处理节点,每个节点是一个 Runnable 或函数。节点会被包装成 PregelNode,包含输入映射、输出映射、重试策略等

3. 添加边(add_edge / add_conditional_edges)

定义节点之间的连接关系。边会被转换为 Channel 和 PregelNode 的组合,实现状态传递和条件分支

4. 编译(compile)核心逻辑

调用 compile() 方法,将 StateGraph 转换为 CompiledStateGraph。这个过程包括:

  • 验证图的完整性(检查孤立节点、循环依赖等)
  • 构建 channels 字典,包含所有状态通道
  • 创建 Pregel 实例,配置 stream_mode、input_channels、output_channels
  • 注入 checkpointer(可选,用于状态持久化)
5. 返回 CompiledStateGraph 实例

编译完成后返回 CompiledStateGraph 对象,该对象继承自 Pregel,包含完整的执行逻辑

compile() 源码关键流程

python 复制代码
def compile(
    self,
    checkpointer: Checkpointer | None = None,
    *,
    cache: Cache | None = None,
    store: Store | None = None,
    interrupt_before: All | Sequence[str] | None = None,
    interrupt_after: All | Sequence[str] | None = None,
    debug: bool = False,
) -> CompiledStateGraph:
    # 1. 验证图结构
    self.validate()
    
    # 2. 构建 channels 字典
    channels = {
        **self.channels,
        **self.managed,
        START: EphemeralValue(self.input_schema),
    }
    
    # 3. 创建 CompiledStateGraph 实例
    compiled = CompiledStateGraph[StateT, ContextT, InputT, OutputT](
        builder=self,
        schema_to_mapper={},
        context_schema=self.context_schema,
        nodes={},  # 节点会在内部构建
        channels=channels,
        input_channels=START,
        stream_mode="updates",
        output_channels=output_channels,
        stream_channels=stream_channels,
        checkpointer=checkpointer,
        interrupt_before_nodes=interrupt_before,
        interrupt_after_nodes=interrupt_after,
        debug=debug,
    )
    
    return compiled

编译时序图

sequenceDiagram participant User as 用户代码 participant Builder as StateGraph participant Compile as compile() participant Graph as CompiledStateGraph User->>Builder: 创建 StateGraph(State) User->>Builder: add_node("agent", call_model) User->>Builder: add_edge(START, "agent") User->>Builder: add_edge("agent", END) User->>Compile: graph = builder.compile() Note over Compile: 1. 验证图结构 Note over Compile: 2. 构建 channels Note over Compile: 3. 创建 Pregel 实例 Note over Compile: 4. 配置 stream_mode Compile->>Graph: 返回 CompiledStateGraph Graph-->>User: 可执行的图实例

🌊 第二部分:CompiledStateGraph.stream() 执行流程

stream() vs invoke()

特性 stream() invoke()
返回类型 Iterator(迭代器) Any(一次性返回)
执行方式 逐步执行,实时输出 等待完成,批量返回
适用场景 需要实时反馈(如 LLM 流式输出) 简单调用,不需要中间状态
内存占用 低(逐步处理) 高(需要缓存所有状态)

步骤解析

1. 参数处理与默认值设置

处理 stream_mode、output_keys、interrupt_before/after 等参数。如果未指定 stream_mode,默认使用 "updates" 或 "values"

2. 创建同步队列(SyncQueue)

创建用于接收流式输出的队列,这是 stream() 方法的核心数据结构

3. 配置回调管理器

设置 LangChain 的回调系统,用于追踪执行过程、记录日志、发送遥测数据等

4. 启动 Pregel 执行循环

调用 PregelLoop,这是 LangGraph 的核心执行引擎,负责:

  • 从输入通道读取数据
  • 触发满足条件的节点执行
  • 将节点输出写入输出通道
  • 检查中断条件
  • 持久化检查点(如果启用)
5. 迭代输出

根据 stream_mode 的不同,逐步 yield 输出:

  • "values":输出每个步骤后的完整状态
  • "updates":只输出节点返回的更新
  • "messages":输出 LLM 的 token 流和元数据
  • "debug":输出详细的调试信息
6. 执行完成或中断

当图执行完成(到达 END 节点)或遇到中断条件时,停止迭代

stream() 源码关键流程

python 复制代码
def stream(
    self,
    input: InputT | Command | None,
    config: RunnableConfig | None = None,
    *,
    stream_mode: StreamMode | Sequence[StreamMode] | None = None,
    output_keys: str | Sequence[str] | None = None,
    interrupt_before: All | Sequence[str] | None = None,
    interrupt_after: All | Sequence[str] | None = None,
    durability: Durability | None = None,
    **kwargs,
) -> Iterator[dict[str, Any] | Any]:
    # 1. 参数处理
    if stream_mode is None:
        stream_mode = "updates"  # 默认模式
    
    # 2. 创建同步队列
    stream = SyncQueue()
    
    # 3. 配置回调管理器
    callback_manager = get_callback_manager_for_config(config)
    run_manager = callback_manager.on_chain_start(None, input, ...)
    
    # 4. 启动 Pregel 执行循环(在后台线程中)
    with get_executor_for_config(config) as executor:
        future = executor.submit(
            _run_stream,  # 核心执行函数
            input,
            config,
            stream,
            stream_mode,
            output_keys,
            interrupt_before,
            interrupt_after,
            durability,
        )
        
        # 5. 从队列中读取输出
        while True:
            try:
                chunk = stream.get(block=True, timeout=0.1)
                if chunk is None:  # 结束标志
                    break
                yield chunk  # 逐步输出
            except queue.Empty:
                if future.done():
                    break
                continue

📊 关键概念对比

StateGraph vs CompiledStateGraph

特性 StateGraph CompiledStateGraph
角色 构建器(Builder) 可执行实例
用途 定义图结构(节点、边) 执行图(invoke/stream)
生命周期 编译前 编译后
核心方法 add_node, add_edge, compile invoke, stream, get_state
是否可执行
继承关系 独立类 继承自 Pregel

stream() vs invoke()

特性 stream() invoke()
返回类型 Iterator(迭代器) Any(一次性返回)
执行方式 逐步执行,实时输出 等待完成,批量返回
适用场景 需要实时反馈(如 LLM 流式输出) 简单调用,不需要中间状态
内存占用 低(逐步处理) 高(需要缓存所有状态)
stream_mode 支持多种模式 不支持

💡 关键要点总结

compile() 的关键作用

  • 将声明式的 StateGraph 转换为可执行的 Pregel 实例
  • 构建 channels 字典,管理状态传递
  • 配置 stream_mode、checkpointer 等运行时参数
  • 验证图的完整性(无孤立节点、无死循环)

stream() 的执行机制

  • 使用 SyncQueue 在生产者(执行线程)和消费者(主线程)之间传递数据
  • ThreadPoolExecutor 中运行 PregelLoop,避免阻塞主线程
  • 通过 yield 逐步输出结果,支持实时反馈
  • 支持多种 stream_mode,满足不同场景需求

PregelLoop 的核心职责

  • 从输入通道读取数据
  • 触发满足条件的节点执行(基于边的连接关系)
  • 将节点输出写入输出通道
  • 检查中断条件(interrupt_before/after)
  • 持久化检查点(如果启用 checkpointer)
  • 判断是否到达终止条件(END 节点或无更多可执行节点)

stream_mode 详解

  • "values":输出每个步骤后的完整状态,适合调试
  • "updates":只输出节点返回的更新,最常用
  • "messages":输出 LLM 的 token 流和元数据,适合实时显示 AI 回复
  • "debug":输出详细的调试信息,包括任务调度、通道状态等
  • "checkpoints":输出检查点事件,用于状态恢复

🎯 实战示例

示例 1:基本编译与执行

python 复制代码
from langgraph.graph import StateGraph, START, END
from langgraph.graph.state import CompiledStateGraph
from typing_extensions import TypedDict

# 1. 定义状态
class State(TypedDict):
    messages: list
    summary: str | None

# 2. 构建图
builder = StateGraph(State)
builder.add_node("agent", call_model)
builder.add_edge(START, "agent")
builder.add_edge("agent", END)

# 3. 编译
graph: CompiledStateGraph = builder.compile()

# 4. 执行
result = graph.invoke({"messages": ["你好"]})
print(result)

# 5. 流式执行
for chunk in graph.stream({"messages": ["你好"]}, stream_mode="messages"):
    message_chunk, metadata = chunk
    print(message_chunk.content, end="", flush=True)

示例 2:带检查点的流式执行

python 复制代码
from langgraph.checkpoint.memory import MemorySaver

# 1. 创建检查点保存器
memory = MemorySaver()

# 2. 编译时注入 checkpointer
graph = builder.compile(checkpointer=memory)

# 3. 流式执行,使用 config 指定 thread_id
config = {"configurable": {"thread_id": "conversation_1"}}

for event in graph.stream(
    {"messages": ["你好,请介绍一下自己"]},
    config,
    stream_mode="messages"
):
    message_chunk, _metadata = event
    if hasattr(message_chunk, 'content') and message_chunk.content:
        print(message_chunk.content, end="", flush=True)
相关推荐
jixunwulian1 小时前
AI+边缘计算,工业智能网关智慧交通IoT解决方案
人工智能·物联网·边缘计算
清辞8531 小时前
Coze从入门到实战---第一、二章
大数据·人工智能·学习·语言模型
质造者1 小时前
LangChain + Ollama + Tavily 实现旅游问答系统
linux·人工智能·python·langchain·rag
追梦人电立电子1 小时前
X、Y电容的分类与选择
人工智能·分类·数据挖掘·追梦人电力电子
美狐美颜SDK开放平台1 小时前
直播APP开发实战:第三方美颜sdk接入步骤与注意事项
人工智能·音视频·美颜sdk·第三方美颜sdk·短视频美颜sdk
yychen_java1 小时前
当算法成为武器:AI泛滥时代的多维危机透视与治理路径
网络·人工智能·ai
TomatoStudy1 小时前
IT职业教育AI落地与实训体系建设复盘——以职坐标模式为例
大数据·人工智能
大模型最新论文速读1 小时前
小红书提出 RedKnot:分头处理 kv 缓存,延时降低 60%效果还提升
论文阅读·人工智能·深度学习·机器学习·缓存·自然语言处理
阿瑞IT1 小时前
AI Agent 工具调用可靠性的工程实践
人工智能