本节摘要:记忆不是一块存储,是一套带时程与分工的分层系统。本节给出记忆的四分层架构——工作记忆、情景记忆(航行日志)、语义记忆(知识库)、程序记忆(指向技能库),说明各层的容量、延迟与持久性档位,制定"什么值得记"的写入策略与知识库的更新纪律,并解释黑匣子为什么必须是只追加的只读视角。
黑匣子的发明始于空难调查员的绝望:航空史上几起悬案,唯一目击者随机坠海,调查只能靠残骸倒推——知道结局,却永远不知道驾驶舱里最后那几分钟发生了什么。一位深陷其中的工程师后来提出:给飞机装一台砸不坏、只记录、事后谁也改不了的仪器。这个思路在智能体上原样成立:记忆系统最硬核的部分不是"记得多",而是记录经得起事后逐帧追问,且不被任何一方篡改。上一章各环节产生的记录,本节给它们安排各自的家。
按信息保留的时程与用途,记忆分四层,各层的容量、延迟、持久性档位完全不同:
| 层 | 装什么 | 时程 | 档位特点 | 服务对象 |
|---|---|---|---|---|
| 工作记忆 | 当前决策窗口的工作集 | 步级到任务级 | 容量小、读写快、易失 | 全舱段的当步决策 |
| 情景记忆(航行日志) | 何时何地做了什么、结果如何 | 天到月 | 只追加、带时间戳、可回放 | 复盘、审计、学习样本 |
| 语义记忆(知识库) | 世界结构与规则:标签、地图、约束 | 月到永久 | 版本化、可修订、需审计 | 规划舱的程序与约束 |
| 程序记忆(技能库) | 怎么干活的配方 | 月到永久 | 随技能库版本管理 | 行为展开(第 6 章) |
分层的关键纪律是读写契约:工作记忆允许自由读写但必须易失(它只该是缓存,不是真相——真相在状态板);航行日志只追加、任何人不得修改(篡改一字节,审计价值归零);知识库可以修订但必须版本化(修订历史本身就是记忆)。四层各守其位,才能各尽其用。
只进不出的日志是慢性毒药:存储成本只是小事,真正的代价是检索稀释——重要的记录淹没在垃圾里,等真要查的时候,等于没有记录。写入决策在"记录一条"之前过三问:事后会不会追问(动作、回执、失败、接管必记);学习用不用得上(成功与失败的任务轨迹是第 8 章学习的原料,按采样率记);丢了会不会心疼(中间调试态、高频重复读数,摘要记或不记)。三问的答案组合出四个档位:全量、采样、摘要、丢弃。
from enum import Enum import time, json class Retention(Enum): FULL = "全量" # 事后必追问:动作、回执、失败、接管 SAMPLE = "采样" # 学习原料:任务轨迹按比例留 SUMMARY = "摘要" # 高频读数:按窗口聚合留统计量 DROP = "丢弃" # 调试中间态:留计数不留内容 class MemoryBay: """黑匣子舱主结构:三层存储 + 写入策略。""" def __init__(self, log_store, knowledge_base): self.working = {} # 工作记忆:易失字典 self.log = log_store # 航行日志:只追加存储 self.kb = knowledge_base # 知识库:版本化存储 self.stats = {"dropped": 0} def record(self, event, payload): tier = policy_for(event) if tier is Retention.DROP: self.stats["dropped"] += 1 return entry = {"t": time.monotonic(), "event": event, "payload": payload} if tier is Retention.SUMMARY: self._aggregate(event, payload) return if tier is Retention.SAMPLE and not self._sampled(event): return self.log.append(entry) # 只追加:无修改接口,物理杜绝篡改 def recall(self, since=None, until=None, event=None): """回放:按时间窗与事件类型检索,供复盘与学习。""" return self.log.query(since=since, until=until, event=event) def learn_fact(self, fact, source_event): """语义写入:知识库修订必须挂来源,走版本化。""" self.kb.commit(fact, provenance=source_event) # 可追溯的修订
代码里的纪律都长在结构上:日志对象没有修改接口——想篡改得先改类定义,审计时一眼识破;知识库的每次修订强制挂上来源事件,知识"是怎么来的"本身就是一条记忆;丢弃计数照常保留——"丢了多少"也是可追问的信息。
语义记忆最怕的不是缺,是陈旧与矛盾。仓库地图换了货架布局,旧知识不更新,规划舱就会自信地走向一堵新墙。更新纪律按这条链走:证据先行(修订由日志事件触发,"感知多次发现拓扑不符"才允许动地图)、版本化(每次修订留版本号与来源,错了能回滚)、冲突裁决(新证据与旧知识矛盾时,按证据置信度与时效裁决,而不是后来的赢)。这套纪律与 2.4 节拓扑层的修订事件对得上:结构性变化的修订事件,就是知识库更新的证据链入口。

知识库的版本化与回滚也值得一并落地:
class VersionedKnowledgeBase: """语义记忆:修订挂证据链,错了能回滚。""" def __init__(self, store): self.store = store self.versions = [] def commit(self, fact, provenance): version = {"id": len(self.versions) + 1, "fact": fact, "provenance": provenance, # 修订的日志证据 "t": time.monotonic()} self.versions.append(version) self.store.apply(fact) return version["id"] def rollback_to(self, version_id): """回滚:按版本链重放到指定点。""" for v in reversed(self.versions[version_id:]): self.store.undo(v["fact"]) self.versions = self.versions[:version_id]
记忆舱的联调围绕三性展开:完整性(按写入策略应记的事件全都在——抽样比对舱段动作流与日志流)、不可篡改性(尝试修改历史条目应当失败,追加接口无更新通道)、可回放性(任取时间段回放,决策链能完整重建)。回放性是硬指标:回放不出来等于没记,第 7 章的事故复盘全押在它身上。
按症状排查:重启失忆(重启后目标与进度蒸发)是工作记忆被当成了真相源——把该持久化的状态移交 5.3 节的检查点;检索劣化(查一条记录翻满页)查写入策略是否失守——采样与摘要档没执行,垃圾混进了日志;知识库打架(新旧事实互相矛盾)查修订是否走了证据链——绕过事件的直改,正是矛盾之源。
💡 关键直觉:日志的第一读者不是人,是三个月后的机器自己。第 8 章的学习要从日志里取训练数据,第 7 章的调试要靠日志重建现场——今天偷懒少记的,明天都要加倍还。
分了层,还差最急的一层怎么运转:当前决策窗口的工作集怎么装配、怎么遗忘。下一节进工作记忆的现场。