【自然语言处理与大模型】LangChainV1.0入门指南:核心组件Streaming

本文介绍LangChain支持的4中流式输出方式。流式输出让应用能够在 LLM 生成完整响应之前,就实时地将结果逐步返回给用户。这对于提升用户体验至关重要。LangChain 支持的流式模式:

模式 参数值 输出内容 使用场景
Agent Progress stream_mode="updates" 每个 agent step 后的状态更新 监控执行流程、调试
LLM Tokens stream_mode="messages" LLM 生成的每个 token(含元数据) 实时显示文本、UI渲染
Custom Updates stream_mode="custom" 用户自定义的任意数据 显示进度、工具执行状态
混合模式 stream_mode=["updates", "custom"] 元组 (mode, chunk) 需要多种流式数据

要想激活流式输出,请将invoke改成stream 或 astream,并指定stream_mode参数。

一、Agent Progress 模式

将stream方法里面传入stream_mode="updates",来开启Agent Progress模式。

python 复制代码
from langchain.agents import create_agent
from dotenv import load_dotenv

# 加载 .env 文件中的环境变量(如 API Key),override=True 确保覆盖已有的环境变量
load_dotenv(override=True)


# 定义一个普通的 Python 函数作为工具
def get_weather(city: str) -> str:
    """获取所给城市的天气"""

    return f"{city}现在是晴天"


# 创建 Agent 实例
agent = create_agent(
    model="deepseek-chat",  # 指定使用的模型,这里是 deepseek-chat
    tools=[get_weather]    # 将函数作为工具列表传入。
                            # LangChain 很智能,即使没有使用 @tool 装饰器,
                            # 它也能自动识别该函数的类型注解和文档字符串,将其封装为 Agent 可用的工具。
)


# --- 演示 1:打印原始的流式输出块 ---
print("--- 原始流式数据 ---")
for chunk in agent.stream(
    {"messages": [{"role": "user", "content": "长沙今天天气如何"}]}, # 输入用户消息
    stream_mode="updates"  # 指定流模式为 "updates",意味着只返回有更新的状态块
):
    print(chunk)  # 打印原始 chunk。你会看到每一行都是一个字典,包含 Agent 的中间步骤(如思考、调用工具)或最终回复。


# --- 演示 2:解析并美化输出 ---
print("\n--- 解析后的内容 ---")
for chunk in agent.stream(
    {"messages": [{"role": "user", "content": "长沙今天天气如何"}]},
    stream_mode="updates"
):
    # 遍历 chunk 字典中的键值对(通常是 Agent 的名称或步骤名称)
    for k, v in chunk.items():
        print(f'当前{k}输出:')
        
        # v['messages'] 是该步骤产生的消息列表
        # 我们取列表中最后一条消息 (-1) 的内容,这在 Agent 思考或回复时通常是最关键的部分
        print(f'{v["messages"][-1].content}')

二、LLM tokens模式

将stream方法里面传入stream_mode="messages",来开启LLM tokens模式,实现打字机效果。

python 复制代码
from langchain.agents import create_agent


# 定义一个普通的 Python 函数作为工具
def get_weather(city: str) -> str:
    """获取所给城市的天气"""

    # 这里模拟了返回结果
    return f"{city}现在是晴天"


# 创建 Agent 实例
agent = create_agent(
    model="deepseek-chat",
    tools=[get_weather],    # 当一个不使用 tool 装饰器的函数传入的时候也可以被当做工具
)

# 使用流式输出,stream_mode="messages" 会逐步生成消息对象
for token, metadata in agent.stream(
    {"messages": [{"role": "user", "content": "长沙今天天气如何"}]},
    stream_mode="messages",
):
    # metadata['langgraph_node'] 显示当前是由哪个节点产生的输出(如 agent 或 tools)
    print(f"node: {metadata['langgraph_node']}")
    
    # token.content_blocks 包含当前消息的具体内容块
    print(f"content: {token.content_blocks}")
    print("\n")

三、Custom Updates 模式

自定义模式的最佳使用场景就是将工具的输出内容也变成流式输出。

  • 在stream或astream方法里面传入 sream_mode="custom"
  • 使用 get_stream_writer() 从工具内部发送自定义更新
python 复制代码
from langgraph.config import get_stream_writer
python 复制代码
def get_weather(city: str) -> str:
    """ 获取指定城市的天气信息 """
    writer = get_stream_writer()  # 流式写入器

    # 自定义进度更新
    writer("正在访问网络"*20)  # 无论我加多长,这里面的内容并不会一个个蹦出来(无流式效果)
    writer(f"正在搜索{city}天气"*20)  # get_stream_writer是实现不同的writer之间的间隔停顿

    result = f"{city}现在是晴天"
    writer(result) # 但是可以通过这种方式来输出,或者使用混合模式
    return result   # return的结果是不会被输出的



agent_with_custom = create_agent(
    model='deepseek-chat',
    tools=[get_weather]
)


for chunk in agent_with_custom.stream(
    input={"messages": [{"role": "user", "content": "长沙今天天气如何"}]},
    stream_mode="custom"
):
    print(chunk)

【注】 如果在工具中添加 get_stream_writer(),该工具将无法在 LangGraph 执行上下文之外被调用。

python 复制代码
get_weather({"city": "长沙"})  # 报错

四、混合模式

可以同时使用多种流式模式,接收 (mode, chunk) 元组,传入一个列表stearm_mode=[]

python 复制代码
# --- 循环 1:直接打印原始输出,用于观察数据结构 ---

for chunk in agent_with_custom.stream(
    input={"messages": [{"role": "user", "content": "长沙今天天气如何"}]},
    # stream_mode 是一个列表,表示我们希望同时获取两种流数据:
    # "updates": 标准的节点更新数据(包含 Agent 的思考和回复)
    # "custom": 开发者自定义的输出数据(通常用于传递特定的 Token 计数、调试信息等)
    stream_mode=["updates", "custom"]
):
    # 打印原始 chunk 观察
    # 输出格式是一个元组,第一个元素是模式名称(如 "updates" 或 "custom")
    # 第二个元素是该模式下的具体数据内容
    print(chunk)


print("\n--- 解析并分类输出 ---\n")

# --- 循环 2:根据模式类型处理数据 ---

for chunk in agent_with_custom.stream(
    input={"messages": [{"role": "user", "content": "长沙今天天气如何"}]},
    stream_mode=["updates", "custom"]
):
    # chunk 是一个元组:(mode_name, mode_data)
    # 判断当前 chunk 属于哪种模式
    if chunk[0] == "custom":
        # 如果是 "custom" 模式,直接打印自定义数据(chunk[1])
        print(chunk[1])
    else:
        # 如果是 "updates" 模式(chunk[0] == "updates"),处理标准节点更新数据
        # chunk[1] 是一个字典,键是节点名称,值是节点数据
        for k, v in chunk[1].items():
            # 提取该节点最后一条消息的内容并打印,通常包含 Agent 的思考或最终回复
            print(v["messages"][-1].content)

如何让 Agent 同时以多种模式(这里是 updates 和 custom)进行流式输出。这在需要同时监控 Agent 的标准思考过程(updates)和获取自定义中间数据(custom)时非常有用。

相关推荐
Aotman_2 小时前
Vue.directive:自定义指令及传参
前端·javascript·vue.js·elementui·ecmascript·es6
wangchen_02 小时前
C++<fstream> 深度解析:文件 I/O 全指南
开发语言·前端·c++
程序员码歌2 小时前
短思考第266天,玩IP路上的几点感悟,这几点很重要!
前端·后端·创业
2501_946230982 小时前
Cordova&OpenHarmony用户账户管理
android·javascript
梵得儿SHI2 小时前
2025 Vue 技术实战全景:从工程化到性能优化的 8 个落地突破
前端·javascript·vue.js·pinia2.2·响应式数据分片·展望vue3.6·2025年vue技术栈
熊猫钓鱼>_>2 小时前
解决Web游戏Canvas内容在服务器部署时的显示问题
服务器·前端·游戏·canvas·cors·静态部署·资源路径
梦6502 小时前
React 封装 UEditor 富文本编辑器
前端·react.js·前端框架
Hao_Harrision2 小时前
50天50个小项目 (React19 + Tailwindcss V4) ✨ | DoubleClickHeart(双击爱心)
前端·typescript·react·tailwindcss·vite7
qq. 28040339842 小时前
react 编写规范
前端·react.js·前端框架