快速开始
:::python模块组成
流式处理栈包含两个主要层级:- 流式处理 从Pregel引擎发射原始图执行事件。
- 事件流 对事件进行标准化,通过流式转换器处理,并暴露类型化投影。
Pregel引擎
执行图步骤
发射
原始Pregel事件
updates, values, messages, custom, checkpoints, tasks, debug发送到
事件路由器
将每个事件通过转换管道路由
级联通过
流式转换器
值转换器
消息转换器
…
自定义转换器
生成
事件流
应用程序代码所需的投影事件
stream.messages, stream.values, stream.subgraphs, 和stream.output。自定义转换器可在stream.extensions下添加应用特定投影。
事件流提供的服务
运行流在底层事件流上暴露类型化投影:
多个消费者可并发读取这些投影。读取
stream.messages不会阻塞stream.values、stream.subgraphs或stream.output所需的后续事件。
事件流位于流式处理之上,后者通过stream_mode模式(如updates、values、messages、custom、checkpoints、tasks、debug)暴露原始图执行事件。需要低级事件模式访问时使用流式处理;需要类型化投影时使用事件流。
流式消息
使用stream.messages处理聊天模型输出:
:::python
message.text在同步代码中是可迭代的。迭代以逐token输出,或调用str(message.text)获取完整文本。
message.reasoning暴露推理增量。message.tool_calls暴露工具调用片段。每个片段包含调用的id、其name,以及更新部分的args。若需严格按到达顺序获取文本、推理和工具调用片段,应直接迭代消息流原始事件而非单独投影。
:::js
message.text既是异步可迭代对象也是 promise-like 值。迭代以逐token输出,或 await 获取完整文本。
:::
流式子图
使用stream.subgraphs观察嵌套图执行而无需解析命名空间字符串:
:::python
subgraph.graph_name是编译后的图或智能体的name。通过工具(例如通过Deep Agents task工具调用的 create_agent(name=...))派生的命名智能体在此处以该名称显示,打开作用域的事件cause包含回溯到调用工具的lifecycle链接。详见Lifecycle。
针对产品特定流式操作,请参考Deep Agents流式(子智能体流式)和LangChain智能体流式(工具调用和中间件事件)。
流式状态
使用stream.values在每一步后流式完整状态快照:
:::python
流式多投影
:::python 对于异步代码中的并发消费,使用astream_events与asyncio.gather:
stream.interleave(...)按严格到达顺序消费多投影:
中断后恢复
当图因人工输入暂停时,检查stream.interrupted和stream.interrupts,然后通过调用stream_events(..., version="v3")和Command恢复执行。
恢复需要编译时包含检查点功能的图,以及携带线程ID的配置——详见persistence。
:::python
流式所有协议事件
使用运行对象本身以获取原始协议事件流: :::pythonProtocolEvent封装的通道特定负载。转换器的process(event)接收相同结构。
:::python
namespace是从根图到事件发射作用域的路径。根是空数组[]。每个子执行添加一个"name:runtime_id"段,因此嵌套工具调用在子图内显示为["researcher:6f4d", "tools:91ac"]。名称在:前的部分是稳定的图/节点名称,后缀是单次调用的运行ID。若仅需关注特定子树,stream.subgraphs已实现此过滤。
通道与事件生命周期
原始事件通过通道流动。通道名称显示在事件的method中,每个通道发射特定形态的事件。
类型化投影(
stream.messages、stream.values等)基于这些渠道构建。渠道名称在遍历运行对象时直接显示为原始事件的method字段。
消息
messages渠道建模内容块输出。其数据中的event字段为以下之一:
message-startcontent-block-startcontent-block-deltacontent-block-finishmessage-finish
message-finish可能包含Token使用量;不可恢复的模型调用失败会作为消息错误事件出现。
每个content-block-delta事件携带其index处的内容块的type:
content-block-finish携带完整块。忽略您不认识的Delta类型,并持续读取流。
直接消费原始内容块事件而非使用stream.messages投影:
:::python
工具
tools渠道暴露工具执行。其数据中的event字段为以下之一:
tool-startedtool-output-deltatool-finishedtool-error
messages渠道将工具执行与原始工具调用内容块关联。
生命周期
lifecycle渠道跟踪根运行、子图和子智能体的状态。其数据中的event字段为以下之一:
startedrunningcompletedfailedinterrupted
event外,生命周期数据可能包含可选的graph_name、error和cause,描述子作用域的启动原因(父工具调用、扇出发送或边过渡)。
自定义投影
流式转换器是事件流中的投影层。它们观察协议事件,维护自身状态,并暴露运行派生的视图(如工具活动、Token总量、进度事件、产物或消息)。StreamChannel是转换器用于发布这些视图的投影原语。
内置投影(stream.messages、stream.values、stream.subgraphs、stream.output)和产品特定投影(LangChain的stream.tool_calls、Deep Agents的stream.subagents)自身也是使用相同契约的转换器。用户转换器通过编译时或运行时注册叠加在顶层,其投影显示在stream.extensions下。
当现有投影无法匹配应用需求时,编写自定义投影。
转换器工作原理
事件流从LangGraph Pregel引擎的流式输出开始。运行时将 chunks 规范化为协议事件,然后流处理器通过转换器栈路由每个事件。 流处理器是单流的中心调度器。对于每个协议事件,它执行以下操作:- 按顺序调用已注册转换器的
process(event)钩子。 - 将命名的
StreamChannel推送回协议事件流。 - 除非转换器抑制,否则将事件存储在运行流中。
- 在运行结束时调用每个转换器的
finalize()或fail()。
StreamChannel、承诺或其他投影对象。
转换器结构
转换器实现StreamTransformer接口:
:::python
init()创建投影对象。用户转换器投影显示在stream.extensions下。process()观察每个协议事件。参见流式所有协议事件的ProtocolEvent结构。仅在有意抑制原始事件时返回false。finalize()在流成功结束时关闭或解决非通道投影。fail()向非通道投影传播错误。
声明必需的流模式
required_stream_modes控制底层图在流期间发出的Pregel模式。运行时将每个转换器的required_stream_modes的并集作为stream_mode参数传递给图的.stream()调用。未声明的模式永不发出——声明("custom",)是触发custom事件流的原因。
:::python
process()接收图发出的所有事件并负责按event["method"]过滤。声明开启上游发射,但不会缩小process()的视野。有效值是Pregel流模式:"messages"、"tools"、"custom"、"values"、"updates"、"checkpoints"、"tasks"、"debug"。每个转换器必须声明其作用的每个模式——未声明的模式不会由图发出,且不会到达process()。
StreamChannel
StreamChannel是转换器用于流式输出的投影原语。它始终在stream.extensions.<name>暴露可迭代的流。构造函数参数决定是否将每个push()也作为custom:<name>事件注入运行的主事件流——即投影的值是否在遍历原始协议事件时可见。
:::js
:::python
命名通道的有效载荷必须可序列化,因为每个推送的值也会成为主流中的
custom:<name> 协议事件。将承诺、异步可迭代对象、类实例和其他进程内句柄保存在无名通道中。
流处理器拥有通道生命周期。一旦 init() 返回一个通道,处理器将在运行结束时为你关闭或失败它。转换器仅推送值。
示例:命名通道
向StreamChannel 传递一个字符串名称,通过 stream.extensions 和 将每个推送的值作为 custom:<name> 协议事件转发到运行的 main 事件流:
:::python
示例:无名通道
没有名称,通道仅是侧信道投影——可通过stream.extensions 访问,但消费者迭代原始事件时不可见。这对于持有无法序列化到主事件流的进程内句柄(承诺、异步可迭代对象、类实例)的投影是正确的选择。
下面的示例将无名通道与 get_stream_writer 配合使用,该通道允许图节点发出 custom-通道事件,转换器随后将其排入投影:
:::python
示例:最终值投影
当投影不应流入主事件流时,使用无名流、承诺或其他进程内对象: :::python在调用时注册或编译时注册
在调用时传递 transformers 以进行本地实验: :::python内置:ToolCallTransformer
:::python
LangGraph 将 ToolCallTransformer 作为内置功能提供。注册它以在普通的 StateGraph 上暴露 stream.tool_calls:
相关
LangGraph 定义了流式输出的基础。要使用 LangChain 或 Deep Agents 的流式输出,请查阅相关产品文档:- LangChain agent streaming 涵盖 ReAct 风格的智能体消息、工具调用和中间件更新。
- Deep Agents streaming 涵盖子智能体、嵌套消息和子智能体工具调用。
- LangChain frontend patterns 和 LangGraph frontend patterns 展示了基于流式状态构建的 UI 用例。
- LangSmith Streaming API 涵盖了在背后部署 Agent Server 的图中进行流式输出的情况。
langchain-protocol 在 PyPI 和 @langchain/protocol 在 npm 上使用。
官方原文:src/oss/langgraph/event-streaming.mdx · 非官方翻译,译文由 AI 生成,以英文原文为准。