可追踪的记忆
记忆和摘要系统并不新鲜。 许多 Agent 系统都有类似能力。 但 AI RP 需要的记忆,不只是把事实存下来,还要能说明这些事实从哪里来,为什么会影响现在。
记忆系统已经很常见
现在只要谈 Agent,几乎都会谈记忆。
常见做法是:
- 从对话里提取事实。
- 把长对话压缩成摘要。
- 在下一轮生成前检索相关内容。
- 把检索结果放回提示词。
这套流程很容易理解,也确实有用。
对于普通任务型 Agent 来说,它通常已经够用了。系统只要记得用户偏好、项目背景、任务进度,就能减少重复询问,提高连续性。
但 AI RP 的情况不完全一样。
AI RP 里的记忆,不只是为了让系统“记得一些信息”。它还会影响角色关系、世界状态、剧情走向和玩家体验。
所以这里的记忆系统需要更强的可追踪性。
酒馆生态的特殊之处
酒馆面向的用户,是来玩 AI RP 的。
他们不是只想让系统完成一个外部任务。他们在意的是一段叙事能不能成立。
在这样的场景里,记忆错误会带来很明显的问题。
例如:
- 角色突然记得一件从未发生过的事。
- 系统忘记了几轮前已经承诺过的约定。
- 某个 NPC 的态度发生变化,但使用者看不出原因。
- 一条摘要把玩家没有做过的行动写成了事实。
- 一条长期记忆来自模型误解,却在后续多次被注入。
这些问题都不是简单的“记忆召回率不够高”。
它们会破坏叙事因果。
在 AI RP 中,使用者通常会追问:
- 这条记忆是从哪一轮来的?
- 当时是谁说了这句话?
- 这是用户确认过的事实,还是模型自己推断的?
- 这条记忆为什么会在这一轮被注入?
- 它有没有覆盖旧记忆?
- 它和另一条记忆是否冲突?
如果系统回答不了这些问题,记忆就会变成新的黑箱。
AI RP 需要能揭示因果关系的记忆
普通记忆系统常常只关心两件事:
存了什么 → 取出什么AI RP 需要多问几步:
为什么存下它 → 它来自哪里 → 它更新了什么 → 它为什么在现在被使用这就是“可追踪的记忆”。
一条记忆不应该只是孤立的文本。它最好能带上下面这些信息:
- 来源楼层。
- 来源消息。
- 所属分支。
- 记忆类型,是事实、摘要,还是未闭合事项。
- 作用域,是全局、会话、分支,还是楼层。
- 提取或更新的理由。
- 与其他记忆的关系。
- 当前是否仍然有效。
- 本轮是否被检索、被注入、被裁剪。
这样使用者才能看见一条记忆在叙事中的位置。
例如,系统不只是告诉你:
角色 A 害怕水。它还应该能告诉你:
这条记忆来自第 12 楼。
当时角色 A 在河边提到童年溺水经历。
第 18 楼的摘要强化了这条事实。
当前分支仍然保留这条记忆。
本轮因为场景发生在码头,所以它被注入提示词。这才是 AI RP 中更有用的记忆。
摘要尤其需要追踪
摘要是记忆系统里最容易出问题的部分。
因为摘要会压缩信息。
压缩会带来两个风险。
第一,细节会丢失。原本带有条件、语气和不确定性的内容,可能被压成一个更确定的句子。
第二,因果会被改写。原本只是角色怀疑某件事,摘要可能写成了事情已经发生。
如果摘要没有来源,使用者很难判断它是否可信。
所以摘要也需要被追踪:
- 短摘要覆盖了哪些楼层。
- 长摘要由哪些短摘要压缩而来。
- 摘要里哪些内容来自用户输入,哪些来自 AI 输出。
- 压缩时是否丢弃了重要条件。
- 新摘要是否更新、替代或冲突了旧摘要。
这不是为了把摘要系统做得复杂,而是为了让压缩之后的信息仍然可以回查。
摘要越长,越需要知道它从哪里来。
记忆关系也很重要
记忆之间不只是并列关系。
有些记忆支持另一条记忆。
有些记忆更新另一条记忆。
有些记忆和另一条记忆冲突。
例如:
第 5 楼:角色 B 说自己从未去过王都。
第 20 楼:角色 B 承认自己曾经在王都受训。这两条信息不能简单地同时存在,然后都被注入提示词。
系统需要知道它们之间的关系。
第二条可能是在更新第一条,也可能是在揭示角色 B 之前说谎。不同解释会带来不同剧情含义。
因此,记忆系统需要能够表达关系边,例如:
- supports:一条记忆支持另一条记忆。
- updates:一条记忆更新另一条记忆。
- contradicts:一条记忆和另一条记忆冲突。
这些关系不是装饰。它们是叙事因果的一部分。
分支让记忆追踪更必要
TavernHeadless 有真正的分支结构。
这意味着,同一个会话里可能存在多条故事线。
在主线里,角色 A 可能活着。在另一条分支里,角色 A 可能已经死亡。
如果记忆只放在会话级别,这两条故事线就会互相污染。
所以记忆也需要作用域。
有些记忆属于全局。比如世界观常识。
有些记忆属于会话。比如整个会话都确定的背景。
有些记忆属于分支。比如这条故事线里的选择和后果。
有些记忆只属于某个楼层。比如一次回合的临时判断。
可追踪的记忆要能回答:这条记忆属于哪条线,它从哪里继承来,又有没有在当前分支被更新。
否则,分支会让记忆问题变得更难排查。
和 Prompt Runtime 的关系
Prompt Runtime 关注的是提示词运行过程。
它可以告诉使用者:这一轮哪些记忆被注入了,哪些被排除,记忆摘要是否进入了提示词。
但这只回答了一部分问题。
如果使用者继续问:这条被注入的记忆从哪里来,为什么它存在,是否可靠,它和旧记忆有什么关系,就需要记忆系统自己的追踪能力。
因此,两者分工不同。
Prompt Runtime 说明记忆在本轮提示词中怎样被使用。
可追踪的记忆说明记忆本身怎样形成、怎样更新、怎样和其他记忆发生关系。
两者合在一起,才能回答完整的问题:
这条记忆为什么存在,又为什么在这一轮影响了回复?和 Memory Agent 的关系
后续如果引入 Memory Agent,它不应该只是一个自动写记忆的后台进程。
它应该提出建议,并留下理由。
例如:
- 建议新增哪条事实。
- 建议更新哪条旧记忆。
- 建议标记哪条记忆为过时。
- 建议保留哪个冲突,等待后续确认。
- 建议把哪条记忆从楼层提升到分支。
这些建议不应该静默生效。
影响叙事正史的记忆写入,应当有明确的提交边界。至少要能在事后看到:是谁提出了这条写入,依据是什么,最后是否被接受。
这样 Memory Agent 才不会变成另一个难以解释的状态修改者。
可追踪记忆解决的核心问题
可追踪记忆解决的不是“存得更多”。
它解决的是下面几个问题。
来源可查
每条记忆应该尽量能回到来源楼层和来源消息。
如果一条记忆有问题,使用者可以回到当时的上下文,而不是只能看到一段孤立摘要。
更新可查
记忆不是一次写入后永远不变。
角色关系会改变,事实会被补充,误解会被澄清。
系统需要记录旧记忆如何被更新,新记忆是否替代了旧记忆。
冲突可查
AI RP 中,冲突不一定都是错误。
有些冲突是剧情的一部分,例如角色说谎、误会、信息不完整。
系统不应该简单删除冲突,而应该先把冲突标出来,让后续流程判断。
注入可查
一条记忆存在,不代表它每一轮都应该进入提示词。
使用者需要知道本轮为什么选择了它,为什么没有选择另一条记忆,以及它是否因为预算被裁剪。
分支可查
同一会话下不同分支的记忆应当互不污染。
使用者需要知道当前分支继承了什么,修改了什么,和其他分支有什么差异。
成本很高,受益也很高
可追踪的记忆会带来成本。
系统需要记录来源、作用域、关系、状态和后台作业结果。摘要压缩时也要保留覆盖范围和来源列表。记忆检索和注入时,还要记录本轮为什么选中或排除某些记忆。
API 和 SDK 也要把这些信息以稳定结构暴露出来。
前端如果要展示它,还需要有合适的 Inspector。否则信息太多,使用者也看不明白。
另外,可追踪不等于完全正确。
LLM 仍然可能提取出错误记忆。摘要仍然可能压缩出偏差。系统只能让这些错误更容易被发现和修正,而不能保证它们永远不发生。
这些都是负担。
但对于 AI RP 来说,这个负担有意义。