LangChain 消息处理全解析:缓存、过滤、合并与流式输出实战

LangChain 消息处理全解析:缓存、过滤、合并与流式输出实战

文章目录

在这里插入图片描述


一、消息内存缓存

核心概念

通过 InMemoryChatMessageHistory 将对话历史存储在内存中,使模型能"记住"之前的对话内容。

关键组件

组件作用
InMemoryChatMessageHistory内存中的聊天记录存储器
RunnableWithMessageHistory将模型包装为支持历史记录的可运行对象
memory_store(字典)session_id 为 key 管理多个会话的历史

代码流程

# 1. 创建内存存储字典 memory_store ={}# 2. 定义获取会话历史的函数(按 session_id 区分会话)defget_session_history(session_id:str):if session_id notin memory_store: memory_store[session_id]= InMemoryChatMessageHistory()return memory_store[session_id]# 3. 用 RunnableWithMessageHistory 包装模型 message_model = RunnableWithMessageHistory(model, get_session_history)# 4. 通过 config 指定会话 ID config ={"configurable":{"session_id":"123"}}# 5. 多轮对话,模型自动记住上下文 response1 = message_model.invoke({"input":"你好,我是小明"}, config=config) response2 = message_model.invoke({"input":"我叫什么名字?"}, config=config)# → 模型能回答出"小明",因为历史被缓存了

运行效果

  • 第一轮:用户说"我是小明",AI 正常打招呼
  • 第二轮:用户问"我叫什么名字",AI 能从历史中回忆出"小明"

从LangChain的v0.3版本开始,官⽅建议LangChain⽤⼾不要使⽤
RunnableWithMessageHistory ,⽽是利⽤ LangGraph 持久性 来完成


二、消息过滤

核心概念

使用 filter_messages 函数对消息列表进行筛选,按类型ID过滤消息。

关键函数

from langchain_core.messages import filter_messages 

过滤参数

参数作用示例
include_types只保留指定类型的消息["ai"] → 只保留 AI 消息
exclude_ids排除指定 ID 的消息["4"] → 排除 id 为 “4” 的消息

代码示例

messages =[ HumanMessage(content="你好,我是小明",id="1"), AIMessage(content="你好,小明!很高兴认识你!",id="2"), HumanMessage(content="我想知道我之前的名字",id="3"), AIMessage(content="你之前的名字是小绿!",id="4"),]# 过滤:只保留 AI 消息,且排除 的消息 filtered_messages = filter_messages( messages, include_types=["ai"], exclude_ids=["4"],)# → 结果只剩 的 AIMessage: "你好,小明!很高兴认识你!"

过滤逻辑

原始消息 → include_types=["ai"] 筛掉 Human 消息 → exclude_ids=["4"] 再排除 id=4 → 最终结果

原始: [Human#1, AI#2, Human#3, AI#4] ↓ include_types=["ai"] 中间: [AI#2, AI#4] ↓ exclude_ids=["4"] 结果: [AI#2] 

三、消息合并

核心概念

使用 merge_message_runs连续的同类型消息合并为一条,避免多条连续 Human 或 AI 消息导致模型报错或行为异常。

关键函数

from langchain_core.messages import merge_message_runs 

代码示例

messages =[ HumanMessage(content="你好",id="1"), HumanMessage(content="我是小明",id="2"),# 连续两条 Human AIMessage(content="你好,小明!",id="3"), AIMessage(content="很高兴认识你!",id="4"),# 连续两条 AI] merged_messages = merge_message_runs(messages)

合并效果

合并前(4条): human: 你好 human: 我是小明 ai: 你好,小明! ai: 很高兴认识你! 合并后(2条): human: 你好\n我是小明 ai: 你好,小明!\n很高兴认识你! 

两种使用方式

# 方式一:直接调用函数合并后传给模型 merged_messages = merge_message_runs(messages) model.invoke(merged_messages)# 方式二:通过管道(pipe)操作,合并与模型调用串联 chain = merge_message_runs | model response = chain.invoke(messages)

管道方式更简洁,适合在 LangChain 链式调用中使用。


四、流式输出

什么是流式输出

流式输出(Streaming) 是指 AI 模型逐字返回内容,而不是等待全部生成完毕后一次性返回。就像 ChatGPT 那样,文字一个个"打"出来,而不是突然全部出现。

为什么需要?

AI 生成长文本可能需要几秒甚至更长时间。传统方式用户需要等待整个响应完成才能看到内容,体验很差。流式输出实时展示生成过程,让用户感觉响应更快,交互更自然。

特性非流式流式
用户体验需要等待实时看到
适用场景短文本聊天对话、长文本
内存占用一次性加载逐块处理
可控性无法中断可随时停止

典型应用

  1. 聊天机器人:像 ChatGPT 一样逐字显示
  2. 文章生成:实时展示生成过程
  3. 代码生成:逐行显示代码
  4. 实时翻译:边翻译边显示

五、同步 vs 异步流式

LangChain 提供两种流式方式:同步(stream)和异步(astream)。

核心区别

特性同步 stream异步 astream
调用chain.stream()chain.astream()
循环for chunk inasync for chunk in
阻塞阻塞线程不阻塞,可并发
场景单个请求多个并发请求
性能一般更高

工作原理

同步流式: 阻塞当前线程,处理一个请求时无法处理其他请求。就像排队买咖啡,必须等前一个人买完。

异步流式: 使用协程机制,等待 AI 响应时可以切换到其他任务。就像服务员可以同时为多桌客人点单。

何时使用异步?

推荐:

  • 多用户 Web 应用
  • 高并发聊天机器人
  • 与其他异步操作结合

不需要:

  • 简单的单次调用
  • 学习测试阶段

六、流式输出基础用法

同步流式

from langchain_deepseek import ChatDeepSeek from langchain_core.output_parsers import StrOutputParser model = ChatDeepSeek(model="deepseek-chat", streaming=True) parser = StrOutputParser() chain = model | parser for chunk in chain.stream("写一个关于程序员的笑话"):print(chunk, end="|", flush=True)

关键点:

  • streaming=True:必须设置
  • flush=True:立即刷新输出

异步流式

import asyncio asyncdefmain(): chain = model | parser asyncfor chunk in chain.astream("写一个关于程序员的笑话"):print(chunk, end="|", flush=True)if __name__ =="__main__": asyncio.run(main())

关键点:

  • async def:定义异步函数
  • async for:异步迭代
  • asyncio.run():运行入口

七、输出解析器

StrOutputParser 是最常用的解析器,将模型输出转换为纯文本。

作用:

  • 提取文本内容
  • 去除多余格式
  • 统一输出格式

自定义解析器:

defcustom_parser(output:str)->str:return output.strip().replace("。","!") chain = model | parser | custom_parser 

应用场景:

  • 格式转换(Markdown → HTML)
  • 内容过滤审核
  • 特殊字符处理

八、流式输出实际应用

1. 聊天机器人

用户发送消息后,AI 回复逐字显示,像真人打字。使用异步流式提高响应速度。

2. 多用户并发

Web 应用中多个用户同时请求,异步流式可以并发处理。

性能对比:

  • 同步:3个请求需要 15 秒(串行)
  • 异步:3个请求只需 5 秒(并发)

3. FastAPI 集成

from fastapi import FastAPI from fastapi.responses import StreamingResponse @app.get("/chat")asyncdefchat_stream(question:str):asyncdefgenerate():asyncfor chunk in chain.astream(question):yield chunk return StreamingResponse(generate(), media_type="text/plain")

九、常见问题

1. 没有流式效果?

原因: 忘记 streaming=Trueflush=True

2. async for 报错?

原因: 使用了 ainvoke() 而不是 astream()

ainvoke() 返回完整结果,astream() 返回流式迭代器。

3. 性能对比

  • 单个请求:同步和异步相近
  • 多个并发:异步快 3 倍

十、总结对比

功能函数/类用途
内存缓存InMemoryChatMessageHistory + RunnableWithMessageHistory让模型记住多轮对话上下文
消息过滤filter_messages按类型/ID 筛选消息
消息合并merge_message_runs合并连续同类型消息
流式输出stream / astream实时逐字返回,提升体验
输出解析StrOutputParser将模型输出转为纯文本

典型应用场景

  • 内存缓存:多轮对话场景,用户问"我之前说了什么"时模型能回答
  • 消息过滤:只提取 AI 回复做摘要、排除某些敏感消息
  • 消息合并:用户连续发了多条消息时,合并后再发给模型,避免格式错误
  • 流式输出:聊天机器人逐字显示、长文本生成、FastAPI 接口集成

流式输出要点

  1. 流式输出 = 实时返回,提升体验
  2. 同步 = 简单,适合学习
  3. 异步 = 高性能,适合生产
  4. 必须设置 streaming=Trueflush=True

Read more

Cursor完全卸载与重装指南:go-cursor-help辅助工具

Cursor完全卸载与重装指南:go-cursor-help辅助工具 【免费下载链接】go-cursor-help解决Cursor在免费订阅期间出现以下提示的问题: You've reached your trial request limit. / Too many free trial accounts used on this machine. Please upgrade to pro. We have this limit in place to prevent abuse. Please let us know if you believe this is a mistake. 项目地址: https://gitcode.com/GitHub_

By Ne0inhk
2025年PostgreSQL 详细安装教程(windows)

2025年PostgreSQL 详细安装教程(windows)

前言 PostgreSQL 是一个功能强大的开源关系型数据库管理系统(ORDBMS),以下是对它的全面介绍: 基本概况 * 名称:通常简称为 "Postgres" * 类型:对象-关系型数据库管理系统 * 许可:开源,采用类MIT许可证 * 首次发布:1996年(起源于1986年的POSTGRES项目) * 最新版本:PostgreSQL 16(截至2023年9月发布) 核心特性 1. 标准兼容性 * 完全符合ACID(原子性、一致性、隔离性、持久性) * 高度兼容SQL标准 2. 高级功能 * 复杂查询 * 外键 * 触发器 * 可更新视图 * 事务完整性 * 多版本并发控制(MVCC) 3. 扩展性 * 支持自定义数据类型 * 自定义函数 * 使用不同编程语言编写代码(如PL/pgSQL, PL/Python,

By Ne0inhk
在vsCode中使用node.js调试js代码时报错3221225477

在vsCode中使用node.js调试js代码时报错3221225477

我们在第一次使用node.js时,可能会遇到版本不兼容的问题,在使用时就会报错。推荐下载nodejs使用nvm下载 Nvm下载  选择nvm-setup.zip进行下载,下载好了后,打卡按照步骤点击下载(环境变量会自动配置,包括后面nodejs配置环境),下载完成后按win+r输入cmd 在命令行界面输入 nvm list available 查看可下载的nodejs版本 推荐下载18.20.4版本的,大部分都兼容,在命令行界面输入 nvm install 18.20.4  同样你可以在nvm中下载更多版本的 nvm use 18.20.4 使用use后面跟上你想切换的版本就可以切换使用的nodejs版本了 这样就解决了在使用vscode中nodejs会报3221225477错的问题了

By Ne0inhk
小白必看:MoE 架构详解(大模型入门指南),一篇搞定!

小白必看:MoE 架构详解(大模型入门指南),一篇搞定!

一、概念解读 MoE,即混合专家模型(Mixture of Experts),它的核心概念可以用 “术业有专攻” 来简单概括。想象一下,你要解决一系列复杂的问题,有一个全能型的智者,他什么都懂,但当问题数量众多且繁杂时,他处理起来可能会有些吃力,效率也不高。而 MoE 架构就像是组建了一个专家团队,每个专家都擅长某一特定领域,当问题出现时,能够迅速找到对应的专家来解决,大大提高了解决问题的效率。 MoE并非把整个网络应用于每一个输入,而是去学习一种计算成本较低的映射函数,通过这个函数来判断网络中的哪些部分(也就是哪些专家)能够最高效地处理给定的输入。此外,MoE模型中还配备了一个路由器,它的作用是有选择地激活完成给定任务所需要的特定专家,而不是针对每一项任务都激活整个神经网络。 混合专家(MoE)模型的专家(Expert)是什么?专家(Expert)是训练好的子网络(神经网络或层),通常是一个独立的前馈神经网络(FFNN),也可以是更复杂的网络结构。 MoE模型将一个复杂的任务拆分成多个子任务,每个子任务都交给一个专门的“专家”来处理。这些专家各自拥有独特的专长,

By Ne0inhk