AI Agent白手起家57: 上下文记忆系统——基于 Redis 的长短期记忆实现
纲要记忆系统的核心挑战多轮对话与上下文窗口限制多用户会话隔离技术选型为什么选择Redis架构设计基础组件ConversationBufferMemoryRedisChatMessageHistory智能总结自动摘要链防止上下文溢出会话隔离基于session_id的 Key 管理完整实现项目结构记忆管理器MemoryManager类总结链设计保持人格统一读写流程与自动触发逻辑可运行示例总结与相关度说明记忆系统要解决什么问题任何聊天机器人都面临两个核心问题上下文窗口有限大模型一次能处理的 token 数量有上限。对话轮次增多历史记录不断累积迟早会撑爆窗口。多用户隔离张三和李四的对话不能混在一起否则智能体会“串台”把别人的事当成你的事。一个健壮的记忆系统必须在“记住足够上下文”和“不超出窗口限制”之间找到平衡同时保证每个用户的记忆是独立的。技术选型为什么用 Redis记忆存储有很多选择但Redis在对话场景下有天然优势读写极快内存存储适合高频率的聊天消息存取。数据结构匹配对话记录是一条一条追加的与Redis的 List 结构天然吻合。键值隔离通过不同的 Key 可以轻松实现多用户会话隔离。LangChain 官方提供了RedisChatMessageHistory组件可以将对话消息以标准格式直接存入Redis省去了手动序列化和解析的麻烦。架构设计历史记录否是用户发送消息Agent 执行器get_memory 读取历史Redis条数 80?返回原始历史调用总结链压缩清除旧记录保存摘要到 RedisLLM 生成回复set_memory 存储新消息核心思路每次读取时检查当前会话的消息条数。若超过阈值例如 80 条触发总结链将历史压缩为一段摘要清空旧记录后只保留摘要。这样上下文窗口永远不会无限膨胀同时保留了关键信息。完整实现项目结构memory_demo/ ├── config.py ├── memory_manager.py ├── main.py └── .env依赖安装pipinstalllangchain langchain-openai langchain-community redis python-dotenv配置文件config.py# config.pyimportosfromdotenvimportload_dotenv load_dotenv()classConfig:OPENAI_API_KEYos.getenv(OPENAI_API_KEY)OPENAI_BASE_URLos.getenv(OPENAI_BASE_URL,https://api.openai.com/v1)REDIS_URLos.getenv(REDIS_URL,redis://localhost:6379/0)MAX_HISTORY_LENGTHint(os.getenv(MAX_HISTORY_LENGTH,80))记忆管理器memory_manager.py这是记忆系统的核心封装了读取、写入和自动总结的全部逻辑。# memory_manager.pyfromtypingimportListfromlangchain.memoryimportConversationBufferMemoryfromlangchain_community.chat_message_historiesimportRedisChatMessageHistoryfromlangchain_openaiimportChatOpenAIfromlangchain.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimportStrOutputParserfromconfigimportConfigclassMemoryManager:带自动摘要的对话记忆管理器def__init__(self,system_prompt:str):self.memory_keychat_historyself.llmChatOpenAI(modelgpt-3.5-turbo,temperature0,openai_api_keyConfig.OPENAI_API_KEY,base_urlConfig.OPENAI_BASE_URL,)# 构建总结链summary_template(system_prompt\n\n以下是你和用户之间的对话记录请用第一人称「我」对其进行摘要提取关键信息保留用户的核心诉求和你的处理结果。\n对话记录:\n{chat_history}\n\n摘要:)self.summary_promptChatPromptTemplate.from_template(summary_template)self.summary_chainself.summary_prompt|self.llm|StrOutputParser()def_get_history(self,session_id:str)-RedisChatMessageHistory:获取指定会话的 Redis 历史记录对象returnRedisChatMessageHistory(session_idsession_id,urlConfig.REDIS_URL)defget_memory(self,session_id:str)-ConversationBufferMemory:读取会话记忆超过阈值时自动压缩historyself._get_history(session_id)messageshistory.messages# 如果消息数量超过阈值触发总结iflen(messages)Config.MAX_HISTORY_LENGTH:# 将所有消息格式化为文本chat_textformsginmessages:role用户ifmsg.typehumanelse助手chat_textf{role}:{msg.content}\n# 调用总结链生成摘要summaryself.summary_chain.invoke({chat_history:chat_text})# 清空 Redis 中的旧记录history.clear()# 将摘要作为新的系统级消息存入history.add_user_message(以下为历史对话摘要)history.add_ai_message(summary)# 返回标准的 ConversationBufferMemoryreturnConversationBufferMemory(memory_keyself.memory_key,chat_memoryhistory,return_messagesTrue,)defsave_memory(self,session_id:str,user_input:str,ai_output:str)-None:保存一轮对话到记忆historyself._get_history(session_id)history.add_user_message(user_input)history.add_ai_message(ai_output)演示主程序main.py模拟多轮对话观察记忆读取和自动总结的行为。# main.pyfromlangchain_openaiimportChatOpenAIfromlangchain.agentsimportAgentExecutor,create_tool_calling_agentfromlangchain.promptsimportChatPromptTemplate,MessagesPlaceholderfromlangchain.toolsimporttoolfromconfigimportConfigfrommemory_managerimportMemoryManager# 定义一个简单的工具供测试tooldefget_weather(city:str)-str:查询城市天气returnf{city}今天晴天25°Ctools[get_weather]defmain():system_prompt你是小浪助手友好且专业地回答用户问题。memory_managerMemoryManager(system_promptsystem_prompt)llmChatOpenAI(modelgpt-3.5-turbo,temperature0,openai_api_keyConfig.OPENAI_API_KEY,base_urlConfig.OPENAI_BASE_URL,)# 模拟两个不同用户的会话foruser_idin[user_001,user_002]:print(f\n 会话{user_id})memorymemory_manager.get_memory(user_id)promptChatPromptTemplate.from_messages([(system,system_prompt),MessagesPlaceholder(variable_namechat_history),(human,{input}),MessagesPlaceholder(variable_nameagent_scratchpad),])agentcreate_tool_calling_agent(llm,tools,prompt)executorAgentExecutor(agentagent,toolstools,memorymemory,verboseFalse,handle_parsing_errorsTrue)# 第一轮resexecutor.invoke({input:f你好我叫{user_id}请记住我的名字。})print(助手:,res[output])memory_manager.save_memory(user_id,f你好我叫{user_id}请记住我的名字。,res[output])# 第二轮resexecutor.invoke({input:我叫什么名字})print(助手:,res[output])memory_manager.save_memory(user_id,我叫什么名字,res[output])# 检查记忆是否隔离print(f---{user_id}的 Redis 消息数: ---)historymemory_manager._get_history(user_id)print(len(history.messages))if__name____main__:main()运行说明确保本地Redis服务已启动默认localhost:6379。在.env中填入OPENAI_API_KEY。执行python main.py观察两个用户的记忆完全独立互不干扰。关键设计总结链中的人格保持在构造总结提示词时刻意将原始的system_prompt拼接在最前面。这样总结出来的摘要仍然以“我是小浪助手”的第一人称视角叙述避免了摘要内容变成冷冰冰的第三方记述从而在后续对话中保持人格统一。许多开发者容易忽略这一点导致压缩后的记忆与原始角色设定产生割裂。总结本文实现了一个基于Redis的智能体记忆系统核心特性包括多用户会话隔离、自动触发摘要压缩、以及人格统一的第一人称总结。这套方案可直接嵌入任何 LangChain 单智能体项目有效解决长对话上下文溢出的痛点。本文覆盖了 Redis 记忆存储、会话隔离、总结链设计、自动压缩触发逻辑等全部技术细节并提供了示例代码。

相关新闻

AI 编码变快了,为什么工程交付反而没变快?

AI 编码变快了,为什么工程交付反而没变快?

这半年我一直在用 Cursor 和 Claude Code 写代码。说实话,单看编码速度,确实比以前快了一倍不止。一个 CRUD 接口从写代码到跑通,以前要半小时,现在十分钟搞定。但问题来了:项目整体交付速度并没有变快。不仅没变快&am…

2026/10/12 2:27:24 阅读更多 →
终端安全管理系统选型指南:5个关键维度与3款主流产品对比

终端安全管理系统选型指南:5个关键维度与3款主流产品对比

TSafe、Ivanti Endpoint Manager、ManageEngine Endpoint Central三款产品为对比对象,从功能覆盖、适用场景、差异化优势三个层面进行深度分析,为企业IT决策者提供选型参考。安得卫士TSafe依托18大功能模块、全平台终端适配(Windows/Linux/ma…

2026/10/12 2:27:33 阅读更多 →
为什么你的Windows 11 LTSC系统需要Microsoft Store?完整安装指南

为什么你的Windows 11 LTSC系统需要Microsoft Store?完整安装指南

为什么你的Windows 11 LTSC系统需要Microsoft Store?完整安装指南 【免费下载链接】LTSC-Add-MicrosoftStore Add Windows Store to Windows 11 24H2 LTSC 项目地址: https://gitcode.com/gh_mirrors/ltscad/LTSC-Add-MicrosoftStore 还在为Windows 11 LTSC系…

2026/10/12 19:34:02 阅读更多 →

最新新闻

外部AI服务封装为编码助手Skill:网关调度与配额缓存实战

外部AI服务封装为编码助手Skill:网关调度与配额缓存实战

在进行这类封装之前,我建议你先想清楚一个问题:为什么要费力气把一个外部AI服务变成本地编码工具的Skill?单纯为了好看肯定不值得,真正驱动这件事的痛点,大概率是配额不够用、调用不够顺、或者团队里多人共用一套能力时…

2026/10/13 4:04:59 阅读更多 →
3W 学习法:从零上手 Cursor,打造高效 Java 开发体验(TaoToken 统一 Key 接入篇)

3W 学习法:从零上手 Cursor,打造高效 Java 开发体验(TaoToken 统一 Key 接入篇)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 4:04:59 阅读更多 →
Java跨平台Word转PDF:加水印与中文字体乱码解决方案

Java跨平台Word转PDF:加水印与中文字体乱码解决方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 4:04:59 阅读更多 →
储能辅助火电机组AGC二次调频的控制策略与容量优化配置

储能辅助火电机组AGC二次调频的控制策略与容量优化配置

1. 问题切入点:AGC二次调频的痛点与储能进场逻辑电力系统频率稳定是所有运行人员最敏感的一根神经。一次调频靠机组固有调速器动作,只能把频率变化“刹住”,无法把频率拉回额定值;真正把频率恢复到50Hz、消除区域联络线功率偏差的…

2026/10/13 4:04:59 阅读更多 →
Cursor 卡慢问题排查:把 Base URL 改到 TaoToken 后的请求链路优化

Cursor 卡慢问题排查:把 Base URL 改到 TaoToken 后的请求链路优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 4:04:59 阅读更多 →
Python+Django+Vue实现流浪狗救助捐赠平台全栈开发实战

Python+Django+Vue实现流浪狗救助捐赠平台全栈开发实战

从接到这个项目需求的第一天起,我就很清楚它要解决的不只是"给流浪狗一个展示页面"这么简单。真正的痛点在信息不对称:救助站有狗没人领、有需求找不到稳定的捐赠来源,热心市民想帮忙却不知道钱和物具体用到了哪里。所以这个基于Py…

2026/10/13 4:03:59 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →