LangGraph 的 graph.stream() 不只是逐字输出模型回答,还可以流式返回图状态、节点更新以及业务自定义事件。目录中的示例主要涉及四类模式:
流模式 返回内容 典型用途
updates 每个节点产生的状态增量 展示节点执行结果、调试状态变化
values 每一步执行后的完整状态 获取当前状态快照、判断最终结果
messages LLM Token 与元数据 实现聊天逐字输出
custom 开发者主动发送的事件 展示工具进度、业务状态和中间结果
1. updates:只返回状态变化
updates 演示:
for chunk in graph.stream(
{"topic": "冰激凌"},
stream_mode="updates",
):
print(chunk)
每个节点只返回本次修改的字段。例如:
{"refine_topic": {"topic": "冰激凌和猫"}}
{"generate_joke": {"joke": "..."}}
这种模式数据量较小,适合观察哪个节点修改了哪些状态。
2. values:返回完整状态
同一示例还使用了:
stream_mode="values"
它会在图初始化以及每个节点执行后返回完整状态。相比 updates,它更适合:
获取当前工作流的完整快照
在界面上刷新整体任务状态
从消息列表中判断最终 AI 回答
代价是状态较大时会产生更多传输数据。
3. custom:输出自定义业务事件
使用 get_stream_writer(),从节点或工具内部主动发送事件:
writer = get_stream_writer()
writer({
"type": "search_tool",
"status": "searching",
"cur_step": i,
"all_step": len(search_steps),
})
调用时可以同时订阅多种模式:
stream_mode=["values", "custom"]
返回值变成:
chunk_type, data = chunk
其中:
chunk_type == “custom”:处理搜索开始、搜索进度、搜索完成等事件
chunk_type == “values”:读取图的完整状态和最终 AI 消息
这是最适合真实产品的一种组合:custom 驱动进度条或状态提示,values 负责最终结果。
4. messages:流式输出 LLM Token
messages 演示了 Token 流:
for token_chunk, metadata in graph.stream(
{"input": "请解释什么是机器学习?"},
stream_mode="messages",
):
if token_chunk.content:
print(token_chunk.content, end="", flush=True)
返回的每一项包含:
token_chunk:当前消息片段
metadata:节点、标签等调用信息
即使节点内部使用的是 model.invoke(),LangGraph 仍可以捕获模型执行过程中产生的 Token 事件。
5. 按节点过滤 Token
当多个节点并行调用模型时,所有 Token 都可能进入同一个 messages 流。 按节点过滤 Token 通过元数据区分来源:
node_name = metadata.get("langgraph_node", "")
if token_chunk.content and node_name == "summarize":
print(token_chunk.content, end="", flush=True)
这种方式适合摘要、翻译等多个节点并行执行,但前端只展示某个指定节点输出的场景。
6. 按模型标签过滤 Token
按模型标签过滤 Token 为不同模型调用添加 joke、poem 标签,然后根据:
tags = metadata.get("tags", [])
过滤不同类型的内容。与节点过滤相比:
节点过滤关注 Token 来自哪个 LangGraph 节点
标签过滤关注 Token 属于哪类模型调用
一个节点包含多个模型调用时,标签过滤更精确
选择建议
只想观察状态改变时使用 updates;需要每一步完整状态时使用 values;构建聊天逐字输出时使用 messages;需要工具进度、业务通知等结构化事件时使用 custom。
真实的 RAG 或 Agent 产品通常组合使用:
stream_mode=["messages", "custom", "values"]
前端再根据流类型分别更新回答区、工具执行状态和最终会话状态。
总结
LangGraph 常用流模式可以概括为:
流模式 输出内容 适用场景
updates 每个节点产生的状态增量 观察节点更新、调试工作流
values 每一步执行后的完整状态 获取状态快照、提取最终结果
messages LLM Token 和调用元数据 聊天逐字输出、Token 来源过滤
custom 自定义结构化事件 工具进度、业务状态、中间结果
updates
只返回节点本次修改的字段,数据量较小:
for chunk in graph.stream(inputs, stream_mode="updates"):
print(chunk)
values
每一步都返回完整状态:
for state in graph.stream(inputs, stream_mode="values"):
print(state)
适合读取完整消息列表或判断最终输出,但状态较大时传输量也更大。
messages
流式返回:
(message_chunk, metadata)
示例:
for token, metadata in graph.stream(inputs, stream_mode="messages"):
if token.content:
print(token.content, end="", flush=True)
还可以根据节点过滤:
if metadata.get("langgraph_node") == "summarize":
print(token.content, end="")
或者根据标签过滤:
if "joke" in metadata.get("tags", []):
print(token.content, end="")
custom
节点或工具通过 get_stream_writer() 主动发送业务事件:
writer = get_stream_writer()
writer({
"type": "search",
"status": "running",
"progress": 50,
})
适合展示搜索进度、工具调用状态和阶段性结果。
多模式组合
实际 Agent 或 RAG 产品通常组合使用:
for mode, data in graph.stream(
inputs,
stream_mode=["messages", "custom", "values"],
):
if mode == "messages":
...
elif mode == "custom":
...
elif mode == "values":
...
核心选择原则:
看状态变化:updates
看完整状态:values
看逐字回答:messages
看业务进度:custom

389

被折叠的 条评论
为什么被折叠?



