发布时间:2026/9/6 4:57:11
Agent 记忆会“满“吗?重要性×时效性×白名单,给记忆排个淘汰优先级 Agent 记忆会满吗重要性×时效性×白名单给记忆排个淘汰优先级本文是「Agent 应用开发工程师」系列第⑤篇 · 上下文是预算缓存是第一刀记忆淘汰是第二刀——把最值得记住的留下。⚡TL;DR · 先看结论Agent 记忆不是无限仓库上下文窗口满了就得淘汰淘汰不能靠先进先出——重要记忆刚说完就被扔了。本文给出一个三维评分公式score importance × recency × whitelist用 Redis 有序集合Sorted Set做优先级淘汰。白名单机制保护关键记忆不被误杀TTL 冷热分层防止刚记住就被扔。所有权重/阈值都是骨架得你自己按场景调参别写死最佳值。前两篇我们讲了预算Context Engineering和缓存Prompt Caching。这一篇接着讲预算的另一半——记忆淘汰。Cache 管的是系统提示和工具定义反复算Memory 管的是用户说了什么、Agent 发现过什么。但窗口就那么大满了之后扔什么比用什么方式存更值得想清楚。这篇不讲怎么用向量库存住所有记忆——那是存储层的事。我们讲满了之后怎么扔三维评分公式、Redis 排序集实现、白名单保护、冷热分层以及调参不该踩的坑。一、先立标准为什么先进先出不适合 Agent先进先出FIFO是最简单的淘汰策略——谁先来谁先走。但在 Agent 场景里它大概率会做错事用户刚说了一句我的项目密码是 XXXXFIFO 可能因为前面排了太多轮对话直接把它挤出去。下次 Agent 就忘了密码。Agent 刚发现了一个关键工具调用结果FIFO 可能因为这条消息在窗口里位置靠前优先淘汰它。所以 Agent 记忆淘汰需要按价值排优先级而不是按时间顺序。一个反直觉的事实长对话里最重要的信息往往出现在中间——既不是最早开场寒暄也不是最晚当前问题。FIFO 和 LRU 在这种场景下都不好用。二、三维评分公式重要性 × 时效性 × 白名单一个可落地的方案是给每条记忆打一个综合分按分淘汰——分最低的先走。score importance × recency_weight × whitelist_boost维度含义评分思路重要性 (importance)这条记忆值多少钱用户明确标注的“记住这个”、工具返回的错误/告警、涉及安全/配置的信息 → 高分日常闲聊 → 低分时效性 (recency)这条记忆多新鲜刚发生的 → 分高半小时前的 → 分逐渐降低。可用指数衰减weight e^(-λ·Δt)白名单 (whitelist)这条记忆能不能碰白名单内的 → 乘一个大系数如 10永不淘汰不在白名单 → 乘 1⚖️权重不说死λ衰减系数、importance分档、whitelist 乘数——全都得按你的场景调。正文给公式和思路不给最佳值。重要性分档示例非固定类别分说明用户明确指令/配置10“记住这个密码”“把这条规则记下来”工具返回错误/告警8API 调用失败、权限不足关键业务数据7订单号、项目 ID、配置项Agent 发现的重要结论5经过推理得出的事实一般对话上下文3日常问答问候/闲聊1开场白、寒暄三、用 Redis 有序集合做优先级淘汰Redis 的Sorted Set有序集合天然适合这个场景ZADD把记忆 ID 和 score 写进去ZRANK查排名ZREMRANGEBYSCORE按分淘汰——不存在遍历所有记忆找最不重要的。# ⚠️ 骨架示例Redis 排序集做记忆淘汰以你实际 Redis 版本为准importredis,time,json rredis.Redis(hostlocalhost,port6379,db0)MEMORY_KEYagent:memory:prioritydefremember(memory_id:str,importance:float,is_whitelisted:boolFalse):写入一条记忆及其评分recency1.0# 刚发生的时效性满分whitelist10.0ifis_whitelistedelse1.0scoreimportance*recency*whitelist r.zadd(MEMORY_KEY,{memory_id:score})defdecay_memories(decay_rate:float0.95):每隔一段时间给所有记忆的时效性乘一个衰减系数formem_idinr.zrange(MEMORY_KEY,0,-1):mem_idmem_id.decode()currentr.zscore(MEMORY_KEY,mem_id)# 白名单记忆不衰减ifcurrentandcurrent10.0:continue# 非白名单时效性衰减new_scorecurrent*decay_rateifcurrentelse0r.zadd(MEMORY_KEY,{mem_id:new_score})defevict_if_full(max_size:int100,evict_count:int10):如果记忆超过上限淘汰评分最低的 evict_count 条currentr.zcard(MEMORY_KEY)ifcurrentmax_size:# 淘汰分最低的to_evictcurrent-max_sizeevict_count# 找到最低分的记忆lowestr.zrange(MEMORY_KEY,0,to_evict-1)# 删除它们formem_idinlowest:r.zrem(MEMORY_KEY,mem_id)print(fEvicted{len(lowest)}memories)为什么用 Sorted Set 而不是 ListList 只能按插入顺序先进先出Sorted Set 可以按分排序取最低分、按范围删除都是 O(log N)——这在记忆量大的时候是质的区别。三个要命的边界别让白名单膨胀白名单记忆不会被淘汰不加控制就会把窗口塞满。建议设白名单上限比如 20 条超限时按importance × recency在白名单内再排一次。衰减需要定时触发decay_memories不是自动的。可以放在每次remember()调用时顺带执行或者用一个定时任务如schedule库周期性触发。分数碰撞如果多条记忆分数相同ZREMRANGEBYSCORE会全删。建议 score 加一个微小的随机扰动importance * recency * whitelist random() * 0.001避免同分批量误杀。四、白名单机制有些记忆不能被淘汰白名单是关键设计。不是所有记忆都该参与淘汰——有些是死了也不能丢的用户身份信息“我是张三”系统配置/偏好“用中文回复”安全凭证“我的 API key 在环境变量里”长任务上下文“我们正在处理订单 #12345”实现上这些记忆的score被乘一个大系数如 10让它们永远排在 Sorted Set 的顶端。# ⚠️ 骨架示例白名单保护逻辑WHITELIST_BOOST10.0defremember_with_whitelist(memory_id:str,importance:float,is_whitelisted:boolFalse):whitelistWHITELIST_BOOSTifis_whitelistedelse1.0recency1.0scoreimportance*recency*whitelist# 如果是白名单记录白名单元数据备用ifis_whitelisted:r.hset(agent:memory:whitelist,memory_id,json.dumps({importance:importance,created_at:time.time()}))r.zadd(MEMORY_KEY,{memory_id:score})⚠️白名单的白不是永久的用户可能改主意“不再用中文”、任务可能结束订单已完成。建议提供一个降级接口把白名单记忆降为普通记忆参与后续淘汰。五、TTL 冷热分层防止刚记住就被扔还有一个常见问题一条记忆刚写进去因为初始分数低比如普通闲聊importance1下一轮淘汰就被扔了。三个办法新记忆保护期新写入的记忆在 TTL 内比如 30 秒不参与淘汰。用 Redis 的EXPIRE或单独维护一个保护期集合。冷热分层分两层——热层当前窗口活跃记忆和冷层存档可回溯但不计入上下文。淘汰只在热层做冷层用单独的淘汰策略如 LRU。最低分兜底给所有记忆设一个score_min比如 0.1避免分数衰减到 0 后下一轮必然被删——但白名单不受此限。# ⚠️ 骨架示例新记忆保护期PROTECTION_TTL30# 秒defremember_with_protection(memory_id:str,importance:float,...):# ... 正常写入逻辑 ...# 在保护期集合中记录r.sadd(agent:memory:protected,memory_id)r.expire(fagent:memory:protect:{memory_id},PROTECTION_TTL)defevict_except_protected(max_size:int):淘汰时跳过保护期内的记忆protectedr.smembers(agent:memory:protected)# 只淘汰不在保护期内的低分记忆...六、和 Context Engineering、Prompt Caching 合起来看系列走到这里三张成本牌已经齐了策略管什么怎么做Context Engineering往窗口里放哪些 token预算分配L0-L5 分层Prompt Caching系统提示/工具定义少算前缀缓存断点 预热记忆淘汰用户说了什么该留三维评分Redis Sorted Set 淘汰三者的关系Context Engineering 决定放什么Prompt Caching 确保放进去的少算记忆淘汰确保**“放不下的扔得对”**。对应试/面试的启发当面试官问Agent 长对话怎么处理不要只答用 RAG 存——把这三张牌串起来比只答一个工具名深得多。七、10 条面向客户/面试的表达红线别这么说该怎么说 / 错在哪「用向量库存所有记忆就行」存是存储层淘汰是策略层存得下不等于窗口放得下「先进先出够用了」Agent 对话里最重要的信息居中FIFO 正好淘汰它「我的评分公式是通用的」权重/阈值按场景调没有万能参数「白名单记忆永不淘汰」白名单会膨胀需要上限和降级机制「Redis 做记忆淘汰很慢」Sorted Set 的 ZRANK/ZREMRANGEBYSCORE 是O(log N)够快「分数越高越重要」分数高只说明现在排在前面衰减会改变排名「衰减系数设一个就行」不同场景短期对话 vs 长期项目衰减速度不同「淘汰了就不管了」淘汰的记忆可以归档到冷层需要时还能回溯「记忆管理不需要测试」模拟长对话、注入关键信息、看它是否被误杀——必须测「我的记忆方案是生产级的」如果没跑过超过窗口的对话它只是骨架别写成已上线八、一句话带走记忆不是无限仓库淘汰是必然的决策用三维评分排优先级用 Redis 排序集落地用白名单保护关键记忆——然后把一切数字标成按场景调参。下期预告第⑥篇讲「Delta Channels」——LangGraph 的 checkpoint 从 O(N²) 降到 O(N) 的实验性功能值得每个做复杂 Agent 的人关注。参考Redis Sorted Set 文档ZADD/ZRANK/ZREMRANGEBYSCOREMemGPT/LangMem 官方文档以发布时版本为准本文评分公式为骨架权重/阈值需按场景调参。本系列目录①Java 后端不做 AgentSpring AI MCP 实战已发布②MCP vs A2A协议栈位置与选型决策树已发布③别再只会写 PromptContext Engineering 才是 Agent 的下一个范式已发布④Prompt 缓存不是玄学命中判定、断点与预热已发布⑤记忆淘汰策略重要性 × 时效性 × 白名单本文⑥LangGraph Delta Channels——下期预告安全与可信 → 成本与跨栈 → 未完待续

相关新闻

2026/9/6 4:52:10

Yojimbo 1.11.0 深度体验:本地优先的信息管理与全文搜索

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

2026/9/6 4:52:10

QEMU性能瓶颈在哪里?从指令翻译到设备模拟的系统分析

摘要:QEMU 的性能瓶颈是一个系统性问题,并非由单一因素造成。本文从系统角度拆解其开销来源:指令翻译(TCG)是纯 CPU 成本,对计算密集型负载影响最大;SoftMMU 内存路径的查找与失效开销对内存密集…

2026/9/6 5:47:13

数据结构:非比较排序:计数排序

前面我们介绍的冒泡、选择、插入、归并、快排等排序算法,本质上都属于比较排序——它们通过元素之间的两两比较来决定先后顺序。本篇我将带大家认识一种另辟蹊径的非比较排序算法——计数排序(Counting Sort),它不靠比较,而是借助数组下标直接…

2026/9/6 5:47:13

关店前最后一晚,我把验证码全部过了一遍

关店前最后一晚,我把验证码全部过了一遍 一个关店卖家的告别: 「决定关店那天,我把店铺里最后的链接都下架了。下架也弹验证,我一个个过,过得很平静。旁边老婆问:都要关了还这么认真干嘛?我说&…

2026/9/6 5:47:13

数据库工程:索引策略落地避坑实战指南‌

数据库工程:索引策略落地避坑实战指南‌ 2026年4月安徽合肥轨道交通3号线南延线的运维管理系统,在早高峰运维数据上报时段突然出现了大面积的接口超时,全线12个站点的运维人员上报完巡检数据之后,系统提交按钮转了半分钟都没有反应…

2026/9/6 5:47:13

网络原理:初识网络的一些基本概念

IP地址网络通信的本质是计算机之间数据的传输。网络里有很多主机,因此需要知道数据从哪个主机发出,哪个主机接收,所以需要IP地址定位主机。IP地址也可以标识网络中的设备,如路由器。格式:32位二进制,一般分…

2026/9/6 5:47:13

Java PrintStream 详解:从基础用法到实战技巧

1. 引言在 Java 开发中,PrintStream 是一个极其常用的输出流类。无论是控制台打印、日志输出还是文件写入,PrintStream 都扮演着重要角色。本文将深入讲解 PrintStream 的核心概念、常用方法以及实战中的注意事项。2. 什么是 PrintStreamPrintStream 是 …

2026/9/6 5:42:13

FANUC机器人CC-Link从站与三菱PLC主站通信配置与故障排查指南

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

2026/9/6 0:06:59

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/6 0:06:59

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/6 0:06:59

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/6 0:06:59

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/6 0:06:59

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/6 0:06:59

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/5 2:45:13

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/5 2:30:42

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/5 2:46:50

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…