尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

LangGraph 深度解析:stream\_mode messages 与 values 核心区别(含HITL适配与代码实战)

LangGraph 深度解析:stream\_mode messages 与 values 核心区别(含HITL适配与代码实战)
📅 发布时间:2026/7/22 17:56:36

一、前言

在基于 LangGraph 构建 AI Agent、工具调用、人在回路(HITL)交互式应用时,流式输出(stream)是最常用的能力,主要用于实现模型实时打字效果、工具调用状态反馈、人工介入中断等交互场景。

LangGraph 提供多种流式输出模式,其中 stream_mode="messages" 和 stream_mode="values" 是开发中最常用的两种模式。多数开发者会出现认知误区:认为 values 模式是一次性输出、messages 模式是纯流式输出,或是认为两种模式的图执行逻辑存在差异。

本文将从底层原理、执行流程、数据输出规则、HITL 中断适配、代码实战对比五个维度,详细拆解两种模式的核心差异,解决 Agent 开发中流式展示与人工中断冲突的核心问题。

二、核心前置概念铺垫

2.1 HITL 人在回路机制

HITL(Human-in-the-loop,人在回路)是 LangGraph 提供的人工介入能力,核心作用是在 Agent 调用工具的关键节点暂停流程,等待人工确认、修改指令后,再继续执行任务。

关键底层认知:HITL 中断(interrupt)不是大模型的原生能力,也不是模型生成的消息内容。它是 LangGraph 框架底层通过 wrap_tool_call 拦截机制,在工具节点执行前后主动触发的引擎级暂停行为,属于图执行引擎的控制信号,而非模型输出的消息数据。

2.2 Stream 流式输出的本质

LangGraph 的流式输出分为两个完全独立的层级,这是区分两种模式的核心关键:

  1. 内部执行引擎层:负责模型调用、节点运行、路由跳转、状态更新、HITL 中断暂停,stream_mode 不会改变这一层的任何执行逻辑,两种模式下 Agent 的运行流程完全一致。

  2. 对外数据输出层:stream_mode 仅作为数据过滤器,决定图每一步执行完成后,向外暴露什么数据给开发者/前端。

2.3 两种模式基础定义

  • stream_mode="messages":仅过滤并输出大模型、节点产生的消息对象(AIMessage、ToolCallMessage 等),只承载对话、工具调用类业务数据。

  • stream_mode="values":输出图每一个节点执行完成后的完整全局状态快照(State),包含所有对话消息、状态参数、运行上下文,可关联图的执行状态。

三、两种模式核心底层差异(重点)

3.1 数据输出来源差异

3.1.1 messages 模式

数据源仅为模型/节点产出的消息片段。LLM 流式生成的每一个 token、每一段增量消息,都会被实时透传输出。该模式完全屏蔽 LangGraph 引擎的运行控制信号,只专注于对话内容输出。

由于 HITL 的 interrupt 中断是引擎控制信号,不属于消息对象,因此 messages 模式的数据流中完全不存在中断信息。流式循环结束后,无法直接区分流程是「正常执行完毕」还是「被 HITL 中断暂停」。

3.1.2 values 模式

数据源为节点执行完成后的完整 State 快照。LangGraph 的节点是原子执行单元,必须等待单个节点全部执行完毕、状态更新完成后,才会向外输出一次完整状态数据。

该模式不会暴露节点内部 LLM 逐 token 的中间生成过程,因此视觉上呈现「一次性输出完整内容」的效果,但本质是模型依旧流式生成,只是框架过滤了中间增量片段。核心优势是可以通过全局状态快照,配合 get_state() 方法捕获引擎层的 HITL 中断标记。

3.2 流式渲染能力差异

  • messages 模式:支持原生逐字流式渲染,可直接实现前端打字效果,无需额外处理,适合纯对话展示场景。

  • values 模式:原生不支持逐字输出,仅输出节点执行完成后的完整结果。如需流式渲染,需要手动对比前后状态的消息增量,自行封装流式逻辑。

3.3 HITL 中断适配能力差异

  • messages 模式致命缺陷:流式循环终止后,无任何状态标识区分正常结束和中断暂停。无法在流式执行过程中感知 HITL 触发,仅能事后手动查询状态,不适合需要实时弹窗人工确认的交互场景。

  • values 模式核心优势:每次输出完整状态快照,可全程监控 Agent 运行进度。流终止后,通过图状态快照的 __interrupt__ 属性,可精准判断是否触发人工中断,完美适配 HITL 人机交互场景。

3.4 核心差异汇总表

对比维度 stream_mode="messages" stream_mode="values"
内部图执行逻辑 完整执行路由、中断、状态更新(无差异) 与 messages 模式完全一致
输出数据内容 仅模型/节点生成的消息片段 节点执行完成后的完整全局状态
逐字流式渲染 原生支持,开箱即用 原生不支持,需手动封装增量逻辑
HITL 中断捕获 无法实时捕获,无法区分结束状态 可精准捕获,适配人工介入场景
适用场景 纯对话流式展示、无人工中断需求 工具调用、HITL 人机交互、流程状态监控

四、完整代码实战与逐行解析

本节通过可运行代码,直观对比两种模式的输出差异、HITL 中断捕获效果,所有代码基于 LangGraph 最新稳定版本,可直接复制运行。

4.1 环境依赖安装

pip install langgraph langchain-openai python-dotenv

4.2 完整实战代码

import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, MessagesState
from langgraph.prebuilt import ToolNode, tools_condition# 加载环境变量(配置模型API密钥)
load_dotenv()# 1. 定义工具(模拟需要人工审核的工具调用场景)
def get_weather(city: str) -> str:"""查询指定城市天气信息"""return f"{city} 当前气温26℃,天气晴朗,无降水"# 注册工具列表
tools = [get_weather]# 初始化大模型并绑定工具,开启原生流式能力
llm = ChatOpenAI(model="gpt-4o", api_key=os.getenv("OPENAI_API_KEY"), streaming=True)
llm_with_tools = llm.bind_tools(tools)# 2. 定义Agent核心节点
def agent(state: MessagesState):"""Agent思考节点:调用模型生成回复/工具调用指令"""resp = llm_with_tools.invoke(state["messages"])return {"messages": [resp]}# 初始化工具执行节点
tool_node = ToolNode(tools)# 3. 构建LangGraph工作流
graph_builder = StateGraph(MessagesState)
# 添加核心节点
graph_builder.add_node("agent", agent)
graph_builder.add_node("tools", tool_node)
# 添加条件路由:Agent需要调用工具时,跳转至工具节点
graph_builder.add_conditional_edges("agent", tools_condition)
# 工具执行完成后,重新回到Agent节点
graph_builder.add_edge("tools", "agent")
# 设置图入口
graph_builder.set_entry_point("agent")# 核心配置:在工具节点执行前触发HITL中断,等待人工确认
graph = graph_builder.compile(interrupt_before=["tools"])if __name__ == "__main__":# 初始化用户请求user_input = {"messages": [("user", "帮我查询北京的实时天气")]}# ========== 测试1:stream_mode="messages" 模式 ==========print("===== 【messages模式】流式输出结果 =====")print("特点:仅输出消息片段,无法捕获HITL中断\n")stream_messages = graph.stream(user_input, stream_mode="messages")for chunk in stream_messages:# 打印流式消息片段print(f"消息片段:{chunk}")# 流结束后查询状态,无法实时感知中断snapshot_msg = graph.get_state()print(f"\nmessages模式-是否触发中断:{snapshot_msg.__interrupt__ if snapshot_msg.__interrupt__ else '否'}")print("-" * 80)# ========== 测试2:stream_mode="values" 模式 ==========print("===== 【values模式】流式输出结果 =====")print("特点:输出完整状态快照,可精准捕获HITL中断\n")stream_values = graph.stream(user_input, stream_mode="values")for state_snapshot in stream_values:# 打印每一步的完整状态消息latest_msg = state_snapshot["messages"][-1]print(f"最新消息内容:{latest_msg.content if latest_msg.content else '无文本内容(工具调用)'}")# 流结束后捕获中断信息snapshot_val = graph.get_state()print(f"\nvalues模式-是否触发中断:{snapshot_val.__interrupt__ if snapshot_val.__interrupt__ else '否'}")print(f"中断详情:{snapshot_val.__interrupt__}")

4.3 代码核心逻辑解析

  1. HITL 中断配置:interrupt_before=["tools"] 表示在执行工具节点前强制暂停流程,触发人工中断,该行为由 LangGraph 引擎底层完成,与模型无关。

  2. 模型流式配置:模型开启 streaming=True,保证模型本身是逐 token 生成,排除模型输出方式的干扰。

  3. messages 模式执行逻辑:仅透传模型生成的工具调用消息,流式循环结束后无任何中断提示,只能事后查询状态,无法实时交互。

  4. values 模式执行逻辑:输出每一步完整状态,流程暂停后可通过 __interrupt__ 属性精准获取中断原因、待执行工具信息,支持前端实时弹窗确认。

4.4 运行现象总结

  • messages 模式:控制台仅打印模型工具调用消息,无法从流式迭代过程中感知中断,用户无法区分任务完成/暂停。

  • values 模式:控制台打印完整对话状态,流终止后可清晰读取中断信息,明确知晓当前流程卡在工具执行阶段,等待人工介入。

五、常见认知误区修正

5.1 误区1:values 模式模型是一次性输出

正确结论:模型本身始终是流式逐 token 生成,两种模式的模型输出逻辑完全一致。values 模式无逐字效果,是因为框架只输出「节点执行完成后的最终状态」,屏蔽了节点内部的中间增量片段,并非模型一次性返回结果。

5.2 误区2:messages 模式下 Graph 不处理任何逻辑

正确结论:stream_mode 只改变数据输出规则,不改变图的执行逻辑。两种模式下的节点运行、路由跳转、中断触发、状态更新全部正常执行,无任何差异。

5.3 误区3:HITL 是模型的能力

正确结论:HITL 是 LangGraph 框架的拦截能力,通过 wrap_tool_call 机制拦截工具调用流程、主动暂停任务。模型仅负责生成工具调用指令,完全不知情中断行为,因此不会生成任何与中断相关的消息。

六、生产环境最佳实践

在实际 Agent 开发中,绝大多数包含工具调用、人工确认、流程暂停的场景,统一推荐使用 stream_mode="values":

  1. 兼顾状态可观测性:可全程监控 Agent 运行步骤、工具调用状态、中断信息,便于调试和前端状态同步。

  2. 适配 HITL 交互:精准捕获中断信号,实现人工确认、指令修改、流程恢复等完整交互逻辑。

  3. 兼容流式展示:可通过对比前后 State 消息增量,手动封装逐字流式效果,同时保留中断捕获能力。

仅纯对话、无工具调用、无人工介入的简单场景,可使用 stream_mode="messages" 快速实现原生流式打字效果。

七、总结

1. messages 与values 模式的核心区别是数据输出维度不同,而非图执行逻辑不同,内部引擎运行、模型调用、中断触发完全一致。

2. messages 聚焦「消息内容输出」,原生支持逐字流式,但无法捕获引擎级 HITL 中断,不适合交互式工具 Agent。

3. values 聚焦「全局状态输出」,原生无逐字流式,但可精准捕获中断信号,是工具调用、HITL 人机交互的首选模式。

4. HITL 中断属于框架引擎的控制信号,不属于模型消息数据,这是 messages 模式无法适配中断场景的底层根本原因。

相关新闻

  • 关于 springmvc 中的 ResponseBody 和 RequestBody 两个注解的差别
  • McBSP时钟停止模式配置SPI通信:原理、配置与实战指南
  • TMS320F2837xD ADC中断与后处理模块(PPB)实战指南

最新新闻

  • 从研发到上市踩坑无数?2026企业产品全周期第三方检测选型指南 - 互联网科技品牌测评
  • DataInfra-RedactionEverything 性能优化指南:提升本地脱敏效率的 10 个技巧
  • GW03新程序测试
  • 2026年7月最新卡地亚绍兴滨海万达广场维修保养服务电话 - 卡地亚官方售后中心
  • Lazytainer核心原理大揭秘:从网络监控到容器休眠的完整实现
  • 为什么选择AIRS?科学智能研究者不可错过的开源工具集

日新闻

  • AI云原生实战05-金融AI上云最难的不是技术,是“不出事“——TCE银行风控架构拆解
  • 2026年GEOSEO优化公司选型深度测评:五大硬核标准严选,这六家重塑搜索增长新格局 - 品牌前沿专家
  • **核验!2026年7月卡地亚香港**售后网点地址及服务电话公告 - 卡地亚服务中心

周新闻

  • SaaS软件行业GEO实践:AI搜索时代的品牌可见性与获客新路径
  • 什么是PCTFE?医药高端包装的“防潮王牌“材料
  • 【JVM调优实战】16-可视化利器-JConsole-VisualVM-JMC

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号