【LangGraph】新篇章:LangGraph 流式处理入门 ------ 理解五种流模式与基本算法
- 前言
-
- 1、什么是流式处理?
- [2、LangGraph 的五种流模式](#2、LangGraph 的五种流模式)
- 3、环境准备:一个支持工具调用的天气助手
-
- [3.1 定义状态和上下文](#3.1 定义状态和上下文)
- [3.2 工具函数:使用 get_stream_writer() 发送自定义事件](#3.2 工具函数:使用 get_stream_writer() 发送自定义事件)
- [3.3 LLM 节点:同样发送自定义事件](#3.3 LLM 节点:同样发送自定义事件)
- [3.4 构建图并编译](#3.4 构建图并编译)
- [4、updates 模式:观察节点状态更新](#4、updates 模式:观察节点状态更新)
- [5、custom 模式:传输自定义事件](#5、custom 模式:传输自定义事件)
- [6、values 模式:完整状态快照](#6、values 模式:完整状态快照)
- 7、结合使用:处理混合输出
- 8、总结

前言
当你构建的 AI Agent 需要处理复杂任务时,用户最讨厌的就是"等待"
LangGraph提供的流式处理能力,让你能够将执行过程的中间状态、节点更新、甚至 LLM 生成的每一个 token 实时推送给前端
本文是流式处理系列的第一篇,我们将介绍 LangGraph 的五种流模式,并通过一个天气查询助手的实例,带你掌握custom 和 updates 等模式的基本用法
1、什么是流式处理?
在传统的一次性调用中,graph.invoke() 会等待整个工作流执行完毕,然后一次性返回最终结果
这对于耗时较长的任务(比如多步推理、调用多个工具)来说,用户体验很差
流式处理(Streaming)允许你在图执行的过程中,逐步输出中间结果
例如:
-
每执行完一个节点,就输出该节点对状态做了哪些更新
-
在 LLM 生成回复时,逐 token 输出文字(类似 ChatGPT 的打字机效果)
-
在长时间运行的工具内部,发送自定义的进度事件(比如"搜索中 30%")
LangGraph 对流的支持非常彻底:不仅支持图状态的变化流,还支持工具内部的自定义数据流,以及 LLM token 级别的流,理解这些模式,是构建高质量交互式 Agent 的基础
2、LangGraph 的五种流模式
LangGraph 的 stream() 方法(以及异步的 astream())接受一个 stream_mode 参数,可以传入单个模式名称,也可以传入一个列表同时启用多种模式
下表是五种模式的概览:
| 模式名 | 输出内容 | 典型使用场景 |
|---|---|---|
"values" |
每个超级步骤后的完整状态(full state) | 调试时查看状态的完整变化历史 |
"updates" |
每个节点返回的状态更新(仅变更的部分) | 实时显示哪个节点做了什么更新,节省带宽 |
"messages" |
逐 token 输出的 LLM 消息(message_chunk, metadata)元组 | 聊天应用,实现打字机效果 |
"custom" |
工具或节点内通过 get_stream_writer() 发送的自定义数据 |
进度条、中间日志、思考过程展示 |
"debug" |
所有调试信息(包括每个步骤的详细信息) | 开发阶段深度调试 |
注意:
你可以在一次调用中组合多种模式,例如 stream_mode=["custom", "updates"],LangGraph 会为每种模式分别输出一个元组 (mode_name, data)
3、环境准备:一个支持工具调用的天气助手
为了演示流模式,我们构建一个简单的 LangGraph 应用:
用户询问 "今天烟台莱山区的天气"
Agent 必须调用一个模拟的天气查询工具,然后返回结果
我们将在这个应用中同时启用 custom 和 updates 模式
3.1 定义状态和上下文
python
from dataclasses import dataclass
from langgraph.graph import MessagesState
class State(MessagesState):
user_name: str = "" # 扩展用户名字段
@dataclass
class Context:
user_id: str
MessagesState 是 LangGraph 预定义的状态
它包含一个 messages: list[AnyMessage],并配置了 operator.add 合并策略,非常适合对话系统
3.2 工具函数:使用 get_stream_writer() 发送自定义事件
python
from langgraph.config import get_stream_writer
from langgraph.prebuilt import ToolRuntime
def search(runtime: ToolRuntime[Context]) -> str:
writer = get_stream_writer()
writer({
"type": "search_node",
"status": "start",
})
user_id = runtime.context.user_id
user_name = runtime.state["user_name"]
writer({
"type": "search_node",
"status": "searching",
"user_id": user_id,
"user_name": user_name,
})
# 模拟查询数据...
writer({
"type": "search_node",
"status": "end",
"user_id": user_id,
"user_name": user_name,
})
return f"user_id:{user_id},user_name:{user_name} 查询天气,晴天:15-20°"
get_stream_writer() 返回一个可调用对象,你可以在任何节点或工具中调用它,并传入一个 JSON 可序列化的字典
这些数据只有在 stream_mode 包含 "custom" 时才会输出
3.3 LLM 节点:同样发送自定义事件
python
def llm_call(state: State):
writer = get_stream_writer()
writer({
"type": "llm_call",
"status": "start",
"messages": "开始调用大模型",
"content": state["messages"][-1].content,
})
messages = [SystemMessage(content="你是天气助手,必须调用工具查询天气")] + state["messages"]
result = model_with_tool.invoke(messages)
writer({
"type": "llm_call",
"status": "end",
"messages": "结束调用大模型",
})
return {"messages": [result]}
3.4 构建图并编译
python
from langgraph.constants import START, END
from langgraph.graph import StateGraph
from langgraph.prebuilt import ToolNode, tools_condition
builder = StateGraph(State, context_schema=Context)
builder.add_node(llm_call)
builder.add_node("tool_node", ToolNode([search]))
builder.add_edge(START, "llm_call")
builder.add_conditional_edges(
"llm_call",
tools_condition,
{
"tools": "tool_node",
"__end__": END
})
builder.add_edge("tool_node", "llm_call")
graph = builder.compile()
4、updates 模式:观察节点状态更新
当我们调用 stream() 并指定 stream_mode="updates" 时,每次节点执行后都会输出一个字典,格式为 {node_name: state_update}
python
for chunk in graph.stream(inputs, context=ctx, stream_mode="updates"):
print(chunk)
输出示例:
text
{'llm_call': {'messages': [AIMessage(content='', tool_calls=[...])]}}
{'tool_node': {'messages': [ToolMessage(content='...')]}}
{'llm_call': {'messages': [AIMessage(content='根据查询,天气晴朗...')]}}
每个 chunk 只包含该节点对状态的增量更新,而不是完整状态
这样可以减少传输的数据量,特别适合在 UI 上实时显示"当前正在执行哪个节点"以及该节点产生的新消息
实际应用:我们可以在前端实时显示"模型正在决定调用工具..."、"工具正在执行..."、"模型正在生成最终回复..."。
5、custom 模式:传输自定义事件
custom 模式与 updates 模式独立
当我们同时启用两者时,输出是一个元组 (mode_name, data)
bash
for chunk in graph.stream(inputs, context=ctx, stream_mode=["custom", "updates"]):
print(chunk)
输出示例:
text
('custom', {'type': 'llm_call', 'status': 'start', 'messages': '开始调用大模型', 'content': '今天烟台莱山区天气怎么样'})
('updates', {'llm_call': {'messages': [AIMessage(tool_calls=[...])]}})
('custom', {'type': 'search_node', 'status': 'start'})
('custom', {'type': 'search_node', 'status': 'searching', 'user_id': '123', 'user_name': '小猫'})
('custom', {'type': 'search_node', 'status': 'end', 'user_id': '123', 'user_name': '小猫'})
('updates', {'tool_node': {'messages': [ToolMessage(...)]}})
('custom', {'type': 'llm_call', 'status': 'end', 'messages': '结束调用大模型'})
('updates', {'llm_call': {'messages': [AIMessage(content='最终答案')]}})
注意:custom 事件可以出现在任何时刻,甚至可以出现在工具执行期间(比如多步骤进度)
这正是我们将要介绍的下一篇文章的重点!!!
6、values 模式:完整状态快照
与 updates 不同,values 模式输出每个超级步骤后的整个状态
例如:
bash
for chunk in graph.stream(inputs, context=ctx, stream_mode="values"):
print(chunk["messages"][-1].content)
输出(略去细节)可能会看到状态逐步丰富的过程
values 模式适合调试或需要完整上下文的前端同步,但数据量较大
两者区别 :

在 LangGraph 中:
- updates :类似 事件流(event stream)
- values :类似 状态快照(state snapshot)
假设 state:
state = {
"messages": [...]
}
updates 模式返回:
{"messages": [AIMessage("hello")]} # 新增的
values 模式返回:
{"messages": [HumanMessage(...), AIMessage("hello")]} # 全部
我们可以这样记:
- updates = git diff(改了啥)
- values = git snapshot(现在啥样)
7、结合使用:处理混合输出
在实际应用中,你通常会同时接收 custom 和 updates 事件,分别处理:
python
for chunk in graph.stream(inputs, context=ctx, stream_mode=["custom", "updates"]):
mode, data = chunk
if mode == "custom":
# 处理自定义事件,例如更新进度条
update_progress(data)
elif mode == "updates":
# 处理节点更新,例如显示最新消息
for node, update in data.items():
if "messages" in update:
last_msg = update["messages"][-1]
if hasattr(last_msg, "pretty_print"):
last_msg.pretty_print()
8、总结
本文介绍了 LangGraph 的五种流模式,重点解析了 updates 和 custom 模式,并通过一个天气查询代理的实例,展示了如何在实际中使用 get_stream_writer() 发送自定义事件,以及如何接收混合流数据
核心要点回顾:
-
values:完整状态快照(调试/同步)
-
updates:节点增量更新(实时显示进度)
-
custom:任意自定义事件(进度条、思考日志)
-
messages:LLM token 流(实时展⽰ LLM ⽣成内容)
-
debug:全量调试信息(开发用)
在下一篇文章中,我们将深入 custom 模式的高级用法:
如何在工具内部模拟多步骤任务,发送进度百分比,构建"思考过程"可视化面板
okok,本期分享先到这里了,再见再见~
