对于新应用,我们推荐使用 事件流——这是在 LangChain v1.3 中引入的类型化投影 API。事件流为每个投影(消息、值、工具调用、子图)提供独立的迭代器,因此您可以独立消费它们,而不是根据 stream_mode 数据块进行分支处理。
LangChain 实现了一个流式处理系统,用于实时反馈更新。 流式处理对于提升基于大语言模型构建的应用的响应能力至关重要。通过逐步显示输出,即使在完整响应准备就绪之前,流式处理也能显著改善用户体验(UX),尤其是在处理大语言模型延迟的情况下。

概述

LangChain 的流式处理系统让您可以将智能体运行的实时反馈呈现在您的应用中。 LangChain 流式处理可以实现以下功能: 更多端到端示例请参阅下方的常见模式部分。

支持的流模式

将以下一个或多个流模式作为列表传递给 stream 或 astream 方法:

智能体进度

要流式传输智能体进度,请使用带 stream_mode="updates" 的 stream 或 astream 方法。这会在每个智能体步骤后发出一个事件。 例如,如果您有一个调用一次工具的智能体,您应该会看到以下更新:
  • LLM 节点:AIMessage 带有工具调用请求
  • 工具节点:ToolMessage 带有执行结果
  • LLM 节点:最终的 AI 响应
通过 config 传递一个 thread_id,以便对会话进行检查点保存,后续轮次可以恢复相同的对话历史。thread_id 独立于 stream_mode;您也可以在传递 thread_id 的同时传递 context,用于工具从 runtime.context 读取的每次运行数据。
Output
使用 thread_id 持久化会话历史需要为智能体配置一个 检查点存储器。在 LangSmith 部署上,检查点存储器是自动配置的。在本地运行时,需要显式传递一个,例如 create_agent(..., checkpointer=InMemorySaver())。为简洁起见,本页剩余的代码片段省略了 thread_id,但在生产环境中您应该传递它。

大语言模型 token

要流式传输大语言模型生成时的 token,请使用 stream_mode="messages"。下方您可以看到智能体流式传输工具调用和最终响应的输出。
流式传输大语言模型 token
Output
将智能体作为节点封装在父 StateGraph 中? create_agent 返回一个编译后的图,因此将其用作节点会使其成为一个子图。除非您传递 subgraphs=True,否则父图上的 stream_mode="messages" 将不会发出来自内部智能体大语言模型调用的 token 块。参见 子图输出。

自定义更新

要在工具执行时流式传输其更新,您可以使用 get_stream_writer。
流式传输自定义更新
Output
如果您在工具内部添加了 get_stream_writer,您将无法在 LangGraph 执行上下文之外调用该工具。

多模式流式传输

您可以通过将流模式作为列表传递来指定多个流模式:stream_mode=["updates", "custom"]。 每个流式传输的块是一个包含 type、ns 和 data 键的 StreamPart 字典。使用 chunk["type"] 判断流模式,使用 chunk["data"] 访问有效负载。
多模式流式传输
Output

常见模式

以下是展示流式处理常见用法的示例。

流式传输思考/推理 token

一些模型在生成最终答案前会进行内部推理。您可以通过过滤 type 为 "reasoning" 的标准内容块来流式传输这些思考/推理 token。
必须在模型上启用推理输出。配置详情请参阅推理部分和您的提供商集成页面。要快速检查模型的推理支持,请查看 models.dev。
要从智能体流式传输思考 token,请使用 stream_mode="messages" 并过滤推理内容块:
Output
无论模型提供商如何,这都以相同的方式工作——LangChain 通过 content_blocks 属性将特定于提供商的格式(Anthropic thinking 块、OpenAI reasoning 摘要等)标准化为标准的 "reasoning" 内容块类型。 要直接从聊天模型(不使用智能体)流式传输推理 token,请参阅使用聊天模型进行流式传输。

流式传输工具调用

您可能希望同时流式传输:
  1. 在工具调用生成时流式传输部分 JSON
  2. 流式传输已完成、已解析的工具调用
指定 stream_mode="messages" 将流式传输智能体中所有大语言模型调用生成的增量消息块。要访问带有已解析工具调用的完整消息:
  1. 如果这些消息被记录在状态中(如 create_agent 中的模型节点),请使用 stream_mode=["messages", "updates"] 通过状态更新访问完整消息(如下所示)。
  2. 如果这些消息未被记录在状态中,请使用自定义更新或在流式循环期间聚合数据块(下一节)。
如果您的智能体包含多个大语言模型,请参阅下方关于从子智能体进行流式传输的部分。
Output

访问完整消息

如果完整消息被记录在智能体的状态中,您可以使用 stream_mode=["messages", "updates"],如流式传输工具调用部分所示,在流式传输期间访问完整消息。
在某些情况下,完整消息并未反映在状态更新中。如果您能访问智能体内部,可以使用自定义更新在流式传输期间访问这些消息。否则,您可以在流式循环中聚合消息块(见下文)。 考虑下面的示例,我们将流写入器集成到一个简化的护栏中间件中。此中间件演示了工具调用以生成结构化的“安全/不安全”评估(也可以使用结构化输出来实现):
然后,我们可以将此中间件集成到我们的智能体中,并包含其自定义流事件:
Output
或者,如果您无法向流中添加自定义事件,您可以在流式循环中聚合消息块:

支持人工介入的流式处理

要处理人工介入的中断,我们在上面的示例基础上进行构建:
  1. 我们使用人工介入中间件和检查点存储器配置智能体。
  2. 我们收集在 "updates" 流模式期间生成的中断。
  3. 我们用一个命令来响应这些中断。
Output
接下来,我们为每个中断收集一个决定。重要的是,决定的顺序必须与我们收集的动作顺序一致。 为了说明,我们将编辑一个工具调用并接受另一个:
Output
然后,我们可以通过向同一个流式循环传递一个命令来恢复:
Output

从子智能体进行流式传输

当智能体在任何点包含多个大语言模型时,通常需要在消息生成时区分其来源。 为此,请在创建每个智能体时传递一个 name。然后在 "messages" 模式下进行流式传输时,该名称可以通过元数据中的 lc_agent_name 键获取。 下面,我们更新流式传输工具调用示例:
  1. 我们将工具替换为一个内部调用智能体的 call_weather_agent 工具。
  2. 我们为每个智能体添加一个 name。
  3. 我们在创建流时指定 subgraphs=True。
  4. 我们的流处理与之前相同,但我们添加了逻辑,使用 create_agent 的 name 参数来跟踪哪个智能体处于活动状态。
当您在智能体上设置 name 时,该名称也会附加到该智能体生成的任何 AIMessage 上。
首先,我们构建智能体:
接下来,我们向流式循环添加逻辑,以报告哪个智能体正在发出 token:
Output

禁用流式传输

在某些应用中,您可能需要禁用特定模型的单个 token 流式传输。这在以下情况下很有用:
  • 处理多智能体系统时,控制哪些智能体流式传输其输出。
  • 混合使用支持流式传输和不支持流式传输的模型。
  • 部署到 LangSmith 时,希望阻止某些模型输出流式传输到客户端。
在初始化模型时设置 streaming=False。
部署到 LangSmith 时,对任何不希望其输出流式传输到客户端的模型设置 streaming=False。此配置在部署前的图代码中完成。
并非所有聊天模型集成都支持 streaming 参数。如果您的模型不支持,请改用 disable_streaming=True。此参数通过基类在所有聊天模型上可用。
更多详情请参阅 LangGraph 流式传输指南。

v2 流式格式

需要 LangGraph >= 1.1。
将 version="v2" 传递给 stream() 或 astream() 可以获得统一的输出格式。每个块都是一个包含 type、ns 和 data 键的 StreamPart 字典——无论流模式或模式数量如何,形状都相同:
v2 格式也改进了 invoke()——它返回一个带有 .value 和 .interrupts 属性的 GraphOutput 对象,清晰地将状态与中断元数据分离:
更多关于 v2 格式的详情,包括类型收窄、Pydantic/数据类强制转换和子图流式传输,请参阅 LangGraph 流式传输文档。

相关内容