news 2026/6/19 13:42:49

每日一技第二天——RAG会话记忆处理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
每日一技第二天——RAG会话记忆处理

导入

先看这样一个场景:

前两天,我用豆包查高考作文题。我说:

“豆包,简单回答一下今年新高考二卷的语文作文要求写什么。”

它给了我材料主旨和核心立意。我接着又问了一句:

“英语呢?”

就两个字,但豆包准确地回答了新高考二卷的英语作文要求。

它知道我在问什么——它记住了“新高考二卷”,记住了“作文”。

这个体验很自然,自然到我们几乎不会去思考它为什么能做到。

但其实,让AI“记住”这件事,远比看上去复杂。 而如何让RAG系统拥有像豆包那样的会话记忆能力,正是这篇文章要探讨的问题。

大模型的记忆真相:每次请求都是失忆的

很多人用过 ChatGPT、Kimi 这些产品,觉得大模型天生就能记住对话内容。你跟它聊了十几轮,它还记得第一轮你说了什么,感觉像是在跟一个有记忆的智能体对话。

但实际上,大模型 API 的每次请求都是完全独立的。模型不会保存任何对话状态——它没有上一轮对话的概念,没有这个用户之前问过什么的记忆,甚至不知道你是谁。

打个比方:大模型就像一个极其聪明但患有严重失忆症的专家。每次你找他,他都不记得你之前来过。你得把之前聊过的内容全部重新说一遍,他才能接着聊。

那最简单的记忆是怎么实现的?答案很简单——把你之前所有的对话历史全部塞进 messages 数组,每次请求都重新发给 API。模型看到了完整的对话历史,所以显得有记忆,实际上每次都是从头看一遍。

POST https://api.deepseek.com/chat/completions Authorization: Bearer YOUR_API_KEY { "model": "deepseek-v4-flash", "messages": [ {"role": "system", "content": "你是一个高考作文辅导助手"}, {"role": "user", "content": "新高考二卷的作文要求是什么?"}, {"role": "assistant", "content": "材料主旨是关于守住根本的古语..."}, {"role": "user", "content": "英语呢?"} // 这就是会话记忆发挥作用的地方 ], "temperature": 0.3, "max_tokens": 500, "stream": false }

但是,这就会导致一些问题

  1. 超出上下文窗口 :有些模型的上下文窗口只有 4K 或 8K token,塞不下这么多内容,请求直接报错

  2. 费用飙升 :咱们的大模型都是按token计费的,塞这么多内容考虑过钱包的感受吗?

所以,会话记忆的核心问题不是要不要记住历史,而是怎么在有限的Token预算内,尽可能多地保留有用的历史信息 。

会话记忆的五种策略

策略一:完整历史(Full History)

原理:每次调用API时,把整个对话历史(从第一条到最新一条)全部塞进messages数组里。

messages = [ {"role": "user", "content": "第一轮问题"}, {"role": "assistant", "content": "第一轮回答"}, {"role": "user", "content": "第二轮问题"}, {"role": "assistant", "content": "第二轮回答"}, # ... 所有历史 {"role": "user", "content": "第N轮问题"} ]

维度

评价

Token控制

❌ 无控制,随轮次线性增长

信息保留

✅ 完整,零丢失

实现复杂度

⭐ 极低,只是维护一个数组

额外API调用

适用场景

对话≤5轮的简单场景、Demo演示

痛点:第10轮对话时,Token可能已经上万,成本陡增,甚至超出模型上下文窗口上限。

策略二:滑动窗口(Sliding Window)

原理:只保留最近K轮对话,超出部分直接丢弃。

# 只保留最近5轮(10条消息) MAX_ROUNDS = 5 messages = full_history[-MAX_ROUNDS * 2:] # 每轮包含user+assistant两条

维度

评价

Token控制

✅ 按轮数精确控制,成本稳定

信息保留

⚠️ 丢失早期关键信息(预算、实体、意图)

实现复杂度

⭐ 极低,切片即可

额外API调用

适用场景

大多数客服场景(近期信息权重高)

痛点:用户第1轮说“我的预算是5000元”,第8轮问“那款红色的多少钱?”——模型完全忘了5000这个关键约束,因为已经被挤出去了。

策略三:Token截断(Token Truncation)

原理:不按轮数切,而是按Token数量精确控制。历史太长时,从最早的消息开始截断,直到总Token数不超过阈值。

维度

评价

Token控制

✅ 按Token精确控制,绝不超限

信息保留

⚠️ 丢失早期信息,且每条消息长度不一,截断粒度不可控

实现复杂度

⭐⭐ 中,需要token计数工具(如tiktoken)

额外API调用

适用场景

消息长度差异大的场景

对比滑动窗口:如果用户前5轮都是一句话,第6轮发了一篇2000字的长文,滑动窗口按轮数切可能刚好把早期的关键信息丢掉;Token截断可以按“真实占用”公平处理。

策略四:摘要压缩(Summary Compression)

原理:当对话超过一定轮数或Token阈值时,调用LLM把旧对话压缩成一段摘要,后续请求携带“历史摘要 + 最近几轮对话”。

def compress_history(old_messages): prompt = f""" 请将以下对话压缩为不超过200字的摘要,必须保留: 1. 用户提到的所有数字类信息(预算、价格、数量) 2. 用户提到的所有实体名称(产品名、人名) 3. 用户的明确意图或偏好 对话内容:{old_messages} """ return llm(prompt) # 调用一次LLM生成摘要 # 后续请求 messages = [ {"role": "system", "content": f"历史摘要:{summary}"}, # + 最近3轮原始对话 ]

维度

评价

Token控制

✅ 大幅压缩,成本可控

信息保留

⚠️ 保留关键信息,但细节有损

实现复杂度

⭐⭐⭐ 高,需要设计压缩Prompt、触发策略、更新机制

额外API调用

每次压缩1次LLM调用(额外成本)

适用场景

长对话、需要长期记忆的复杂场景

痛点:

  • 摘要越压越“虚”,多次压缩后“5000元预算”变成“用户有预算约束”

  • 增量更新策略:是覆盖还是合并?

策略五:混合策略(Hybrid Strategy)

原理:分层管理,短期保留最近N轮完整对话,长期维护摘要或向量库,按需组合。

维度

评价

Token控制

✅ 精确可控,可配置各层占比

信息保留

✅ 长期摘要+短期完整,兼顾

实现复杂度

⭐⭐⭐⭐ 最高,需设计协同机制

额外API调用

触发时1次(摘要生成)或每次(向量检索)

适用场景

生产级系统(推荐)

混合策略的变体:

  • 滑动窗口+摘要

  • 滑动窗口+向量检索

  • 三层结构:System Prompt(角色固定)+ 长期摘要 + 短期滑动窗口

一张表总结对比

策略

Token控制

信息保留

实现复杂度

额外API调用

一句话评价

完整历史

❌ 无控制

✅ 完整

⭐ 极低

短对话专用

滑动窗口

✅ 按轮数

⚠️ 丢早期

⭐ 极低

简单粗暴

Token截断

✅ 按Token

⚠️ 丢早期

⭐⭐ 中

公平但机械

摘要压缩

✅ 大幅压缩

⚠️ 有损

⭐⭐⭐ 高

每次1次

性价比之选

混合策略

✅ 精确可控

✅ 兼顾

⭐⭐⭐⭐ 最高

触发时1次

生产级标配

会话记忆的存储方案

对话历史需要一个地方存起来。不同场景下,存储方案的选择也不一样。

1、内存存储(HashMap / ConcurrentHashMap)

最简单的方案:用一个 Map 把每个会话的对话历史存在内存里。

优点是简单快速,读写都是内存操作。缺点也很明显:服务重启后数据全丢,只能单机使用,对话多了内存占用会很大。

适合开发调试和小规模部署。

2、Redis 存储

用 Redis 存储序列化后的消息列表,天然支持过期清理。

具体操作:将消息列表序列化为 JSON 存入 Redis,设置 30 分钟过期,读取的时候就从Redis 取出并反序列化。

优点:分布式(多个服务实例共享)、高性能、自带过期机制。缺点:需要序列化 / 反序列化,Redis 重启也会丢数据(除非开启持久化)。

适合生产环境。

3、数据库存储

用数据库表存储每条消息,字段设计大概是这样:

优点:持久化、可审计(查看任意历史对话)、可做数据分析(统计热门问题、平均对话轮数等)。缺点:读写性能比内存和 Redis 低,需要数据库连接管理。

适合需要审计和数据分析的企业场景。

4、选型建议

维度内存Redis数据库
读写性能极快(纳秒)快(毫秒)较慢(毫秒~十毫秒)
持久化不支持可选(AOF/RDB)天然支持
分布式不支持天然支持支持
过期清理需自己实现原生支持(TTL)需定时任务
实现复杂度极低
适用场景开发调试生产环境审计 / 分析场景

生产环境推荐方案:Redis做主存储+数据库做归档 。对话进行时,消息存 Redis(快速读写);对话结束后,异步写入 数据库(持久化、审计)。

学习途径:马丁老师

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/19 13:35:08

如何快速掌握Ultimaker Cura:新手3D打印切片软件完整指南

如何快速掌握Ultimaker Cura:新手3D打印切片软件完整指南 【免费下载链接】Cura 3D printer / slicing GUI built on top of the Uranium framework 项目地址: https://gitcode.com/gh_mirrors/cu/Cura Ultimaker Cura是全球最受欢迎的3D打印切片软件&#x…

作者头像 李华
网站建设 2026/6/19 13:29:18

FanControl终极指南:Windows风扇智能温控与精准优化的完整教程

FanControl终极指南:Windows风扇智能温控与精准优化的完整教程 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Tre…

作者头像 李华
网站建设 2026/6/19 13:25:20

pandas多维聚合与滚动计算的工程实践指南

1. 项目概述:为什么多维聚合不是“加个groupby”那么简单 我在银行数据平台组干了八年,从最早用SQL写几十行嵌套子查询做客户分层,到后来带团队重构整个风险指标计算引擎,踩过的坑比写的代码还多。今天聊的这个主题——“多维聚合…

作者头像 李华
网站建设 2026/6/19 13:24:08

PySpark缺失值处理:从语义解析到生产级容错实践

1. 为什么在 PySpark 里“填空”比“删空”更值得花时间琢磨 做数据工程或机器学习项目,你肯定遇到过这样的场景:上游系统传来的订单表里, customer_id 列有 12% 是 null;用户行为日志中, session_duration 字段大…

作者头像 李华
网站建设 2026/6/19 13:23:57

如何快速掌握开源手写笔记工具:Rnote完整入门指南

如何快速掌握开源手写笔记工具:Rnote完整入门指南 【免费下载链接】rnote Sketch and take handwritten notes. 项目地址: https://gitcode.com/GitHub_Trending/rn/rnote 你是否正在寻找一款功能强大且免费的开源手写笔记软件?Rnote正是你需要的…

作者头像 李华