所谓流式执行,就是任务还没有全部完成时,就把已经产生的状态变化、消息增量或运行事件持续返回给调用方,而不是一直等到最终结果生成。
1. stream、astream 和 invoke 是什么关系?
前面我们经常这样调用图:
python
result = graph.invoke(input)
这种方式最终只关心完整结果。
而流式执行使用:
python
for chunk in graph.stream(input):
print(chunk)
异步环境则使用:
python
async for chunk in graph.astream(input):
print(chunk)
两者的核心区别主要是调用方式:
text
stream()
同步迭代
适合普通 Python、CLI
astream()
异步迭代
适合 asyncio、FastAPI 等异步环境
它们支持相同的 stream_mode,输出语义也基本一致。
实际上,invoke() 内部也会消费流式执行结果,只不过最后帮我们汇总成一个最终返回值。
2. stream_mode:到底想流什么?
LangGraph 的流式执行并不只有逐字输出模型回答。
通过:
python
stream_mode
可以决定到底要观察什么数据。
常见模式:
| 模式 | 作用 |
|---|---|
values |
每个 SuperStep 后的完整 State |
updates |
节点产生的 State 增量 |
messages |
模型消息增量 |
checkpoints |
检查点事件 |
tasks |
任务开始、结束、异常等信息 |
debug |
更完整的调试事件 |
custom |
节点或工具主动写出的自定义数据 |
其中最常用的还是前三个。
values:看完整 State
例如:
python
for chunk in graph.stream(
{"initial_state": "初始状态"},
stream_mode=["values"]
):
print(chunk)
可以理解为:
text
values
=
每一步都告诉你"现在整个 State 是什么"
updates:只看节点改了什么
如果使用:
python
stream_mode=["updates"]
则不会每次返回完整 State,而是只返回节点产生的增量。
例如:
python
(
"updates",
{
"node_a": {
"node_a_output": "节点A的输出"
}
}
)
所以:
text
values
=
完整快照
updates
=
本次更新
如果 State 很大,一般 updates 会更轻量。
3. messages:实现真正的 LLM 流式回复
Agent 应用最常见的流式场景,就是模型回答逐步显示。
例如:
python
for chunk in graph.stream(
{
"messages": [
HumanMessage("你好")
]
},
stream_mode=["messages"]
):
print(chunk)
messages 模式返回的不是完整 AIMessage,而可能是一段一段的:
text
AIMessageChunk
实际 chunk 中通常还会附带一些运行元数据:
text
langgraph_step
langgraph_node
langgraph_triggers
checkpoint_ns
模型信息
所以前端聊天界面想实现:
text
模型一边生成
页面一边显示
通常重点关注:
python
stream_mode="messages"
多个流模式也可以一起使用:
python
stream_mode=[
"values",
"messages"
]
这样既可以观察模型消息增量,也可以观察 State 怎么变化。
4. checkpoints、tasks、debug 和 custom 有什么用?
除了业务数据,LangGraph 还可以流出运行时信息。
checkpoints
用于观察:
text
checkpoint_id
当前 values
next
tasks
step
很适合和之前学过的 Checkpoint、Interrupt、失败恢复结合起来调试。
tasks
关注的是单个任务。
一个任务通常会出现:
text
任务开始事件
↓
input / triggers
任务结束事件
↓
result / error / interrupts
如果并行节点比较多,想知道哪个节点开始、哪个节点失败,tasks 会比 updates 更适合。
debug
debug 可以理解为更完整的运行时调试流,把检查点、任务、step、时间戳等信息放到一起。
适合:
text
排查复杂控制流
观察 Interrupt
分析并行任务
custom
如果框架自带的模式不够,还可以由节点或工具自己输出数据。
例如:
text
正在读取文件...
正在调用模型...
处理进度 50%...
正在生成最终结果...
所以流式执行不只是"逐字输出",还可以用来做:
text
进度通知
运行监控
调试信息
状态可视化
5. astream_events 又是什么?
除了:
python
stream()
astream()
LangGraph 还有:
python
astream_events()
它关注的不是单纯的 State,而是整个 Runnable 执行过程产生的标准事件。
例如:
text
on_chain_start
on_chain_stream
on_chain_end
on_chat_model_start
on_chat_model_stream
on_chat_model_end
on_tool_start
on_tool_end
示例:
python
async for event in graph.astream_events(
input,
version="v2"
):
print(event)
事件中通常可以看到:
text
组件名称
run_id
输入输出
父子调用关系
metadata
当前 step
所以可以这样区分:
text
stream / astream
=
拿业务数据、State、消息或调试数据
astream_events
=
观察整个 Runnable 调用链发生了什么
对于普通 Agent 前端,通常 stream/astream 就够了;如果要做更细的运行追踪、监控和调试,再考虑 astream_events。