存储和检索随着数据量增长系统会面临两个问题检索信噪比持续下降存储成本不可控。香农信息论也解释了这件事高概率事件的信息量趋近于零不值得长期存储低概率但关键事件的信息量极大必须持久化保留。重要性评估就是干这件事的它是信息过滤器。它会为每条信息打一个分数这个分数决定后续的衰减速度、复习频率和淘汰优先级。那么重要性如何评估1.1 六维度评估模型在 PowerMem 中评估一条信息的重要性比想象中复杂。它使用了一个六维评估模型即从六个维度进行综合评估、加权汇总维度权重评估什么relevance关联度0.30信息与用户当前上下文的关联程度novelty新颖度0.20信息的新鲜程度是否为首次出现emotional_impact情感强度0.15信息是否包含强烈的情感色彩actionable可操作性0.15信息是否需要用户采取行动factual事实性0.10信息的客观事实程度personal个人相关性0.10信息与用户个人的关联程度拿前面举例的会议消息来说。它与「Q2 的工作」高度相关relevance ≈ 0.8包含明确的时间地点factual ≈ 0.8用户必须参加不能错过actionable ≈ 0.9但情感上中性emotional_impact ≈ 0.2那么从使用六维评估模型加权计算出的重要性分数大致如下0.3×0.8 0.2×0.5 0.15×0.2 0.15×0.9 0.1×0.8 0.1×0.6 ≈ 0.72即最终得出的重要性评估分数为 0.72。六维评估模型是重要性评估的重要理论基础。1.2 双路径评估LLM 与规则引擎PowerMem 设计了两条重要性评估执行路径确保系统在任何情况下都能给出评分。第一条路径就是基于六维评估模型得出的评分第二路径则是在第一条路径不可用时进行优雅降级的规则引擎计算方案。路径一LLM 深度评估优先当 LLM 可用时会直接走这一条评估路径。系统要求 LLM 根据六维度评估模型从六个维度分别分析返回结构化 JSON。得到的结果示例如下{ importance_score: 0.72, reasoning: 会议安排对用户具有明确的时间约束和行动要求, criteria_scores: { relevance: 0.8, novelty: 0.5, emotional_impact: 0.2, actionable: 0.9, factual: 0.8, personal: 0.6 } }PowerMem 从这个 LLM 回复的结构化 JSON 中提取importance_score字段作为重要性评分。但实际上因为 LLM 的回答会有一定的不可预知性所以为了确保即使 LLM 返回格式不规范系统也不会崩溃可以拿到对应的评分数据PowerMem 使用了一种三级回退的方式来进行解析首先尝试解析 JSON 拿到最准确的数据若解析失败则用正则表达式匹配评分数字若再失败即返回保底的默认值 0.5。值得注意的是LLM 返回的结构化 JSON 中的六维数据实际上并未直接参与最后的权重的计算在这里让 LLM 返回六维数据只是为了通过 Chain-of-Thought 的结构化分解来辅助 LLM 推理让最终答案更可靠稳定。路径二规则引擎兜底当 LLM 不可用时路径一则失效规则引擎会接管重要性分数的计算。虽然精度会有所下降但能保证系统能正常运行。规则引擎基于一组可量化的信号来累加分数的内容长度 100 字符0.1 50 字符0.05命中关键词每个 0.1包含?或!各 0.05元数据标记了优先级high/medium0.2/0.1最终分数上限为 1.0规则引擎评分精度不如 LLM 评分但确保了系统在 LLM 不可用时仍能正常运行这种优雅降级graceful degradation设计是生产级系统的重要特征。即不会因为一个外部服务的故障就导致整个记忆系统停摆。二、分类与参数初始化2.1 三层记忆模型重要性分数确定了之后下一步就要给信息分类来决定这条信息属于哪一层的记忆。不知道大家还是否记得前一篇聊过的大脑的记忆分层机制。即信息先进入容量有限的海马体短期存储经过记忆巩固后转移至新皮层长期存储只有那些被反复激活的、与已有知识建立了丰富关联的、或伴随强烈情绪体验的信息才能获得优先转移权。PowerMem 把这个过程翻译为三层模型层级生物学类比倍率典型存活时间working工作记忆前额叶皮层×0.5数小时~1 天short_term短期记忆海马体×1.5数天~数周long_term长期记忆新皮层×2.0数周~数月而分类的逻辑又以重要性分数为依据≥ 0.8进入 long_term≥ 0.6进入 short_term其余归入 working。不同层级的衰减速率不同层级越高衰减越慢信息活得越久if score self._algo.long_term_threshold: # 0.8 return long_term if score self._algo.short_term_threshold: # 0.6 return short_term return working前面算出来的会议信息重要性评分为 importance 0.72命中了≥ 0.6但不到0.8。所以落入short_term短期记忆。2.2 遗忘参数初始化分类分完了但是分类只回答了「这条信息该待在哪一层」更具体的问题是应该忘多快为了巩固记忆什么时候要再复习一遍PowerMem 在分类完成后会为每条记忆生成一整套可随生命周期演进的数值档案。即系统会为这条记忆建立一份元数据卡片用来记录这条信息记忆的强度、衰减参数、复习计划和管理状态等。元数据卡片在结构上分成两块字段职责metadata.intelligence一些数值指标重要性、层级、保留率、衰减率、复习时刻表、访问/复习计数等metadata.memory_management记忆生命周期开关是否待晋升、待遗忘、待归档、是否仍活跃依旧以会议信息为例importance 0.72short_term逐一说明核心参数的设计意图和计算方式。2.2.1 初始保留率初始保留率决定了一条信息在形成瞬间的牢固程度越重要的信息在写入时就应该被赋予越高的初始保留率低重要性内容在认知层面本就应更脆弱更容易在竞争中让出存储与检索带宽。在 PowerMem 中的初始保留率就是重要性分数乘以一个默认为 1.0 的全局配置参数initial_retention self.initial_retention * importance_score # 会议示例1.0 × 0.72 0.72得到的初始保留率实际上会写入两个字段initial_retention字段用于记录创建时的快照当初记得有多牢current_retention字段用于跟踪当前的有效保留水平创建时两者数值相同之后current_retention会随衰减和复习而变化。2.2.2 关于遗忘速度working / short_term / long_term 对应到认知学科中的工作记忆、海马体、新皮层即越接近长期存储层单位时间内的遗忘应该越慢。所以不同的记忆层级需要有各自不同的衰减系数。在 PowerMem 中不同记忆层级的衰减系数为{ working: 0.5, # 强度参数 S 最小忘得最快 short_term: 1.5, long_term: 2.0, # 强度参数 S 最大忘得最慢 }那么针对开头的会议信息这条信息落在了 short_term故系数为 1.5当前这条消息的衰减率为0.1全局基础衰减率 × 1.5short_term 衰减系数 0.15若记忆分类在 working那么衰减率为0.1全局基础衰减率 × 0.5working 衰减系数 0.05若记忆分类在 long_term那么衰减率为0.1全局基础衰减率 × 2long_term 衰减系数 0.2可以看到不同的记忆分类衰减率不同参数越大遗忘越慢。2.2.3 如何做复习调度在认知学原理中有提到间隔重复的核心原则是复习先密后疏要在快要忘记但还能拯救的时间窗内进行复习不能太早等于白看一遍也不能太晚已经彻底忘了。所以 PowerMem在记忆创建时就排好复习时间点而不是等到需要时才临时决定。PowerMem 通过两步生成这张复习时刻表第一步给定基准间隔。系统预设五个基准间隔小时[1, 6, 24, 72, 168]分别对应约 1 小时、6 小时、1 天、3 天、7 天。五个间隔是全局配置所有记忆共享同一组基准值。第二步按重要性压缩间隔。基准间隔对所有记忆一视同仁但不同重要性不同分类的记忆不该用同一个节奏复习一条密码信息应该比一句闲聊被更频繁地唤醒。所以 PowerMem 用了一个公式根据重要性分数对每个基准间隔做压缩adjusted_interval interval * (1 - importance_score * adjustment_factor)interval是基准间隔的数据如 1h、6h、24himportance_score是前面算出来的会议信息的重要性参数 0.72adjustment_factor是压缩系数默认 0.3控制压缩的力度乘积importance_score × adjustment_factor决定了最多能压缩多少最终结果adjusted_interval是压缩后的实际间隔下限 0.5 小时这么解释公式还是太抽象还是用会议信息importance 0.72来拆一遍。这时压缩乘子即对应公式中的(1 - importance_score * adjustment_factor)部分是1 - 0.72 × 0.3 0.784也就是说每个基准间隔都会变成原来的 78.4%。通过计算得出的五个时间点如下次序基准间隔调整后间隔建议复习时刻示意第 1 次1h≈ 0.78h约 47 分钟T₀ 47min第 2 次6h≈ 4.7hT₀ 4.7h第 3 次24h≈ 18.8hT₀ 18.8h第 4 次72h≈ 56.4h约 2.4 天T₀ 2.4d第 5 次168h≈ 131.7h约 5.5 天T₀ 5.5d换个角度再看如果一条信息没有那么重要假设 importance 0.3压缩乘子则变成1 - 0.3 × 0.3 0.91即每个基准间隔都会变成原来的 91%这条信息的五个复习时间点会更靠后次序基准间隔调整后间隔建议复习时刻示意第 1 次1h≈ 0.91h约 55 分钟T₀ 55min第 2 次6h≈ 5.46hT₀ 5.46h第 3 次24h≈ 21.84hT₀ 21.84h第 4 次72h≈ 65.52h约 2.7 天T₀ 2.7d第 5 次168h≈ 152.88h约 6.4 天T₀ 6.4d效果很明显。importance 0.72 的会议信息五轮复习的间隔时间点都被明显提前importance 0.3 的不那么重要的信息复习间隔只被轻微压缩。复习次数越往后复习时间的差距越大。重要性越高系统越早把它拉回复习窗口记忆被重新巩固的机会也就越多。当算完五个时间点后 PowerMem 会把它们存入完整的复习时刻表同时会初始化几个字段配合复习时刻表工作字段含义next_review时刻表中的第一个时间点即下一次建议复习的时间。系统通过这个字段知道最近一次复习该在什么时候last_reviewed最近一次复习的时间戳。刚创建时等于创建时刻之后每完成一次复习就更新review_count已经完成了几轮复习。创建时为 0每完成一轮加 1reinforcement_factor复习成功后保留率的提升幅度默认 0.3。决定每次温故能补回多少遗忘这几个字段和时刻表一起构成了一套完整的复习追踪机制next_review告诉系统什么时候该复习review_count和last_reviewed记录已经复习了多少次reinforcement_factor决定复习一次能恢复多少当到达next_review并完成一次复习时review_count递增、last_reviewed更新、current_retention按reinforcement_factor提升next_review推进到下一个时间点。至此形成提取再巩固的工程闭环。2.2.4 生命周期状态机除了保留率、衰减率、复习时刻这些连续的数值记忆在系统中还有一些生命周期状态需要管理这条记忆是否该晋升到更高的层级是否该被淘汰是否该从活跃检索池中移除在 PowerMem 中也都有对应的标志位创建时初始化为全新、活跃、尚未触发任何处置{ should_promote: false, // 是否应该晋升到更高的层级 should_forget: false, // 是否应该被淘汰 should_archive: false, // 是否应该从活跃检索池转入归档 is_active: true // 是否仍处于活跃状态 }should_promote这条记忆是否应该晋升到更高的层级如 working → short_term。如果一条 working 记忆被反复访问说明它对用户很有价值应该晋升到 short_term 甚至 long_term获得更慢的衰减速度。should_forget这条记忆是否应该被淘汰。当衰减因子跌破阈值0.3或者一条记忆在 7 天内从未被任何人访问过系统就会标记它为待遗忘。should_archive这条记忆是否应该从活跃检索池转入归档。归档不同于遗忘归档的记忆不会被物理删除只是不再参与日常检索。is_active这条记忆是否仍处于活跃状态参与正常的检索和服务。除此之外PowerMem 还会初始化一个access_count计数器记录这条记忆被访问了多少次这个计数器和标志位们配合工作比如should_promote的判断条件之一就是被访问超过 3 次。2.2.5 落库完整的元数据档案所有参数都计算完毕后系统将它们打包成一个结构化的字典返回。在新增记忆时合并进记忆的metadata元数据中与正文内容一并写入存储后端。至此参数建档完成。计时器从这一刻开始滴答作响。三、衰减计算时间开始走记忆系统中的遗忘机制也开始运作保留率开始随着时间的流逝慢慢往下掉。先回顾一下艾宾浩斯遗忘曲线的数学形式R(t) e^(-λt)它时指数衰减的。3.1 PowerMem 的衰减公式PowerMem 把理论公式翻译为代码rate self.decay_rate if decay_rate is None else decay_rate decay_factor math.exp(-hours_elapsed / (24 * rate))要看懂这条会议信息衰减的有多快关键是要看懂分母24 × rate这个数。24 × rate是这条记忆的特征衰减时间单位是小时。把这个数记作SStrength即S 24 × rate。S 越大分母越大指数衰减就越慢记忆活得就越久。代入公式会变为更清爽的形式decay_factor e^(-t / S)这个公式有一个很漂亮的性质当时间t走过一个 S保留率必然衰减到e^(-1) ≈ 37%。也就是说无论 S 是几个小时只要时间走完一个 S 剩下的记忆都是原来的 37%。这是指数衰减的固有特征。所以只要知道 S 是多少小时就大致知道这条记忆遗忘的节奏。还是拿这条会议信息举例它落在 short_termrate 0.15那么S 24 × 0.15 3.6小时也就是说这条会议信息每过3.6 小时保留率就会衰减到上一刻的 37% 左右。最后还有一处工程细节PowerMem 中存在一条回退机制调用方首先会按记忆类型算出类型专属的衰减率并传入但如果调用方没有传就使用全局默认的衰减率进行计算。这种机制保证了即使旧版本的元数据中缺少类型信息衰减计算也不会出错。3.2 彩蛋一个关键的工程取舍PowerMem 用的衰减公式和经典艾宾浩斯论文里的公式其实是等价的只是写法不同。经典论文写的是R(t) e^(-λt)那个 λ 叫做衰减常数和 PowerMem 的 S 互为倒数λ 1 / S。之所以提这件事是因为如果把 PowerMem 的默认参数和经典艾宾浩斯实验的参数放在一起对比就能发现一个有意思的细节从经典的艾宾浩斯实验数据反推出 λ ≈ 0.821。但 PowerMem 默认配置对应的 λ ≈ 0.417大约只有文档推导值的一半参数来源λ 值1 小时后保留率设计意图经典艾宾浩斯实验数据~0.821~44%无意义音节ZOF、WUX纯记忆实验PowerMem 默认配置~0.417~66%语义信息天然遗忘更慢这个差异不是 bug而是一个工程决策。理论上艾宾浩斯使用的是无意义音节人类对这类孤立符号的遗忘速度最快但 PowerMem 存储的是具有语义关联的实际信息对语义信息的遗忘自然会比孤立音节更慢所以 PowerMem 使用了更温和的衰减速率来匹配这一现实。通过衰减参数可在.env中配置INTELLIGENT_MEMORY_DECAY_RATE也可以精细控制遗忘的激进程度decay_rateS 24 × rateλ 1/S1 小时后保留率风格0.051.2~0.833~43%激进遗忘0.1默认2.4~0.417~66%平衡0.24.8~0.208~81%温和遗忘衰减参数越小遗忘越激进。3.3 衰减时间表好现在把上面的一切串起来就会得到这条会议信息完整的衰减过程时间距创建时长衰减因子状态刚创建0h1.000新鲜1 小时后1h≈ 0.757轻度衰减4.3 小时后4.3h≈ 0.300跌破遗忘阈值0.36 小时后6h≈ 0.189深度衰减24 小时后24h≈ 0.0013几乎归零可以看到一条 short_term 记忆在约 4.3 小时后衰减因子就会跌破 0.3 的遗忘阈值但这并不意味着它会被立即删除遗忘决策的执行时机取决于记忆何时被访问。四、访问触发4.1 将遗忘决策延迟到访问时衰减一直在后台进行但遗忘的决策只在实际访问记忆时才被执行。这里有个认知学背景当一个已巩固的记忆被主动提取时它会暂时回到可塑状态然后需要重新巩固。这个提取到再巩固的循环会加强对应的神经连接。在工程层面这意味着记忆的命运不应该由时间单向决定而应该在每次被访问时重新评估。访问是记忆系统最重要的反馈信号。一条信息被频繁访问说明它对用户有价值应该被保留甚至晋升。一条信息长期无人问津即使最初很重要也应该被遗忘。这种懒惰求值的设计降低了系统的计算负担不需要后台定时任务批量扫描所有记忆。4.2 四道关卡当用户通过Memory.get()或Memory.search()访问记忆时会依次执行四道检查。第一关遗忘检查两个触发遗忘的条件# 衰减因子跌破阈值 rate self._resolve_decay_rate(memory) decay_factor self.calculate_decay(created_at, decay_raterate) if decay_factor self.working_threshold: # 0.3 return True # 静默遗忘从未被使用且已过 7 天 if access_count 0 and time_elapsed timedelta(days7): return True两个条件满足其一即触发遗忘。第一条衰减到了阈值以下该淘汰了。第二条也容易理解从未被使用过本身就是最强的遗忘信号。满足了遗忘触发条件调用方负责执行删除。第二关晋升检查三个条件满足其一即晋升# 高频访问被访问 3 次以上 if access_count 3: return True # 通过时间检验存活超过 24 小时 if time_elapsed timedelta(hours24): return True # 本质上很重要重要性分数大于0.6 if importance self.short_term_threshold: # 0.6 return True晋升的效果working → short_term或short_term → long_term。衰减速率倍率从高降到低信息获得更长的寿命。在会议信息这个例子中importance0.72 ≥ 0.6第一次访问时就直接满足晋升条件。如果它此时还是 short_term将升级为 long_term。一条信息通过晋升机制实现了从临时便签到长期知识的演变。这是人脑记忆巩固过程的工程对应。第三关归档检查两个条件# 自然老化超过 30 天 if time_elapsed timedelta(days30): return True # 本质上不重要重要性分数小于0.3 if importance self.working_threshold: # 0.3 return True归档不同于遗忘。被归档的记忆不会被物理删除但从活跃检索池中移除进入存档状态。用户仍可通过专门的归档检索接口访问。第四关周期重处理每当访问次数是 5 的倍数第 5 次、第 10 次……或记忆类型发生变更系统重新计算全部 Ebbinghaus 元数据。这确保记忆的参数始终与其访问模式保持一致。随着访问累积衰减率和复习调度逐步趋于稳定这正是间隔重复效应在工程层面的体现。五、搜索加权5.1 干扰理论在搜索中的体现记忆的困难不在于存不进去而在于取不出来。随着存储信息增多记忆之间的交叉干扰呈指数级增长。当用户搜索「Q2 评审」时如果系统只按语义相似度排序可能出现这种情况一条 3 个月前的会议纪要语义完美匹配排在最前面。而昨天刚更新的评审时间变更信息排在后面。语义匹配度最高 ≠ 用户最需要。PowerMem 通过为搜索结果引入时间维度来解决这个问题。5.2 排序公式先上公式final_score relevance_score × decay_factorrelevance_score是关键词匹配度decay_factor是前面提到的衰减因子这个公式做了一次交叉排序。高语义匹配但时间久远的记忆可能被中等匹配度但非常新鲜的记忆超越记忆语义匹配度衰减因子final_score排名1 分钟前的闲聊中等匹配0.450.990.4513 小时前的会议记录高度匹配0.920.290.27210 天前的会议记录完美匹配0.98~0.00~0.00末尾大白话讲新鲜度在搜索排序中有一票否决权。再怎么匹配衰减到接近零的老记忆也会被沉到底部。此外搜索本身也是记忆访问。在进行搜索时会对每条搜索结果依次调用Memory.get实现批量生命周期管理。六、全局优化6.1 为什么需要全局优化前面讲的都是针对单条记忆的实时管理。但记忆系统还需要周期性的全局治理。随着信息不断积累重复、冗余、碎片化等问题都会逐渐显现。这类似于大脑在睡眠阶段进行的记忆整理。海马体将记忆重放并转移至新皮层同时去除重复信息、合并相似记忆、强化重要连接。PowerMem 提供三种互补的优化策略。6.2 三种优化策略1精确去重基于内容哈希的精确匹配。系统维护一个hash → [memories]的映射保留每组中最早创建的记录删除其余。一次最多处理 10,000 条记录。完全相同的两条信息只留一条。这是最基础的清理。2语义去重基于 embedding 余弦相似度识别语义高度近似但措辞不同的记忆。使用 O(N×M) 逐对比较默认阈值 0.95。相似度超过阈值的较新记忆被删除保留最早的那条。比如「Q2 评审改到下周三了」和「Q2 review 推迟到下周三」语义相同但文字不同语义去重能识别出来。3记忆压缩对多条语义相似但不严格重复的记忆使用 LLM 将其总结为一条精炼的合成记忆。流程分两步贪心聚类将相似度超过阈值默认 0.85的记忆归为一组LLM 摘要使用提示模板让 LLM 生成精炼摘要用一条合成记忆替换整个聚类这三个机制与遗忘衰减协同构成从微观逐条衰减到宏观批量压缩的完整记忆质量管理体系。总结信息量不小。回顾这条会议信息在 PowerMem 中走过的路下周五下午三点评审 Q2 需求文档 进入系统 ↓ 重要性评估 → 这条信息有多重要 → 0.72 ↓ 分类 → 分到哪一层 → 短期记忆 ↓ 参数初始化 → 配一个衰减计时器 → 衰减率和复习间隔已排好 ↓ 时间流逝 → 衰减进行中保留率持续下降 ↓ 被访问 → 还活着吗需要升级吗 → 检查通过晋升为长期记忆 ↓ 被搜索 → 排在第几位 → 时间新鲜度 × 语义匹配度 ↓ 全局优化 → 有重复吗能压缩吗 → 去重与合并核心思路贯穿始终用有限资源保留最有价值的信息同时保持检索的高信噪比。六个节点各司其职重要性评估解决记住什么分类解决记住多久衰减解决何时淘汰