Agent 的记忆系统怎么设计?短期、长期记忆分别放哪?

Q3-12记忆系统高频记忆系统工作记忆长期记忆写入策略记忆冲突多租户隔离合规

谁在问:一二面高频;做过对话产品或个性化助手的面试官会一路追到写入策略和多租户隔离

口语化问法

  • Agent 的记忆你们怎么做的?短期长期分别放哪儿?
  • 什么东西值得记下来?总不能把所有对话都存进去吧。
  • 用户上个月说喜欢简洁,这个月要详细,你的记忆怎么办?

考察意图

「记忆」是这一章最容易答得漂亮又空洞的题。面试官在筛三层:

  1. 会不会先拆词。 直接答"用向量库存对话历史"的人,把四类完全不同的东西混成了一件事——它们的存储、写入时机、检索方式、失效策略都不一样。
  2. 知不知道难点在写不在存。 存储是最简单的部分。真正的难题是决定写什么什么时候让它失效——记忆库被噪声填满之后,检索准确率会崩,而且是静默地崩。
  3. 有没有合规和多租户意识。 记忆天然含个人信息,跨用户串号是重大事故。一二面能主动提这条的人不多,是明显加分项。

参考答案

图 2 · 60 分与 90 分差在哪:代价、演进、怎么验证

60

60 分答案(及格线)

「记忆」得先拆成四类,各有各的位置:

类型 装什么 放在哪 生命周期
工作记忆 当前任务的消息、工具结果 上下文窗口本身 本轮任务,受窗口和成本约束
会话记忆(短期) 本次会话的滚动摘要、已确认的参数、已执行的写操作 会话存储(KV/Redis),重建上下文时注入 本次会话
长期记忆(跨会话) 用户偏好、稳定事实、历史结论 向量库 + 结构化档案,按需检索注入 长期,需更新与失效机制
程序性记忆 做事的方法、规则、教训 规则文件 / Skills 手册,而不是塞进向量库 随流程变更维护

检索上,长期记忆不能每轮全量注入,要按需检索并且带用户 ID 过滤;写入上要有提取器决定哪些值得记,不能把整段对话都塞进去。

90

90 分答案(有生产经验的回答)

补四层。

1. 难点在写入侧,不在存储侧。 记忆系统失败的典型路径是:一开始什么都记 → 记忆库里全是"用户说了你好"这种噪声 → 检索召回的都是废话 → 有用的记忆被淹没 → 团队以为是检索不行,去调向量模型,其实是写入没门槛。所以我会做三件事:提取器(用模型从对话里抽结构化条目,限定类型:偏好 / 事实 / 约束 / 决定)、阈值(低置信度不写)、黑名单(临时性表达、情绪化表达、敏感类别一律不写)。写入时机通常是回合或会话结束,而不是每句话。

2. 高价值信息走结构化档案,长尾才走检索。 少量高价值的键值(称呼、语言偏好、时区、常用项目)直接常驻上下文,不参与检索——又快又准又便宜。大量长尾条目才走语义检索,并且加时效加权(新的优先)和用户 ID 过滤。这个分层能同时压成本和提准确率。

3. 记忆必须能被更新和遗忘。 只增不改的记忆库是定时炸弹:用户改了偏好,旧条目还在,模型会拿着过期信息做判断。做法是每条记忆带时间戳和来源,同一 key 的新值覆盖旧值并留变更痕迹,而不是并列存两条;再配 TTL 和用户可见可删的入口。这块也是合规要求(个人信息的更正权与删除权)。

4. 三段式看长期记忆。

  • 解决什么:跨会话连续性、个性化、少问用户重复的问题。
  • 代价是什么:写入噪声让检索退化;陈旧记忆污染当前判断;每轮多一次检索的成本与延迟;个人信息带来的合规负担;以及一个隐蔽风险——记忆让 Agent 的行为不可复现,同一个输入对不同用户结果不同,评测和排障都变难。
  • 什么时候不该用:一次性任务;个性化没有实际价值的场景;强合规不允许留存的场景(改用会话内的显式结构化档案,会话结束即丢)。

5. 和 RAG 的关系一句话点到(细节见 Q3-14):技术栈相似,语义完全不同——RAG 检索的是外部知识,离线批量入库、内容基本不变;记忆检索的是关于这个用户和任务的历史,在线增量写入、必须处理更新、冲突和删除。把记忆当成"再建一个 RAG"的团队,都会在更新和冲突上翻车。

追问链

图 1 · 五层追问树:面试官会往哪儿挖
存不是难点:五层全绕着「写什么、什么时候失效、会不会串号」

  1. 什么该写进长期记忆、什么不该?怎么实现这个判断?

    期望该写稳定可复用的:偏好、稳定事实、硬约束(预算上限、不能用某供应商)、重要决定及理由。不该写:一次性细节、临时状态、情绪化表达、模型自己的推测(会被当事实反复引用,污染最重)、敏感类别。实现靠带 schema 的提取器(限定 type,不许自由文本)+ 置信度阈值 + 去重合并
    信号点出「模型的推测不该写」和「去重合并」→ 被噪声坑过;答「重要的就记下来」却给不出实现 → 没做过
  2. 用户上个月说喜欢简洁,这个月要详细。记忆冲突怎么处理?

    期望先要能检测到冲突——同一 key 不同 value,前提是记忆有结构(key/value/时间戳),纯自由文本连冲突都发现不了。原则:新值覆盖旧值 + 留变更历史,不是两条并存。边界是偏好可能场景相关(写周报要简洁、写方案要详细),这时给记忆加适用条件而不是覆盖
    信号提出「结构化才能检测冲突」和「场景相关的偏好要带条件而非覆盖」→ 做过真产品;答「用最新的」却不提怎么发现 → 停在表面
  3. 长期记忆每轮都检索吗?成本和延迟怎么控?

    期望不每轮做,触发条件收窄到:新会话开始、话题切换、命中个性化意图,其余轮次复用本会话已注入的记忆。控成本三条:注入设 token 配额、高价值键值常驻不检索、检索结果按条数上限而不是相似度阈值(相似度在记忆场景很不稳)。记忆变动会击穿 prompt 缓存,稳定与易变部分分开放
    信号说「按触发条件检索而不是每轮」并考虑 prompt 缓存影响 → 算过账;答「每次都检索,反正很快」→ 没在高频场景跑过
  4. 记忆系统在合规上要注意什么?

    期望五条:① 用户可见可删的入口;② 敏感类别(健康、证件、金融账号)不入库或脱敏后写;③ TTL 与最小化;④ 多租户隔离要在存储层强制(按用户分 namespace),不能靠每次查询记得加条件;⑤ 日志与记忆分离,调试日志别把记忆全量打出来
    信号主动提「隔离要在存储层强制而不是查询层靠自觉」→ 有安全直觉;只答「注意隐私」→ 口号
  5. 线上出现 A 用户的记忆被检索给了 B 用户,怎么处理?

    期望先止血再查因:开关整体关掉记忆注入 → 评估影响面:哪些会话注入了跨用户记忆、什么敏感级别、有没有落到下游,这是合规事件不只是技术故障 → 归因三种:漏了用户过滤、共用一个 namespace、缓存键没带 user_id(最隐蔽,并发才复现)→ 这是架构缺陷不是 bug:隔离下沉存储层、缓存键强制带身份、双账号交叉探测
    信号先降级止血、定性为合规事件、修复落到「存储层隔离 + 缓存键带身份」→ 处理过真事故;只答「加用户 ID 过滤」→ 下次在缓存层再犯
「把对话历史丢进向量库就叫记忆」的人,第 1 层就露馅;真正的分水岭在第 4、5 层——隔离是架构问题,不是加个过滤条件的问题。

评分要点

  1. 先拆分类:工作记忆 / 会话记忆 / 长期记忆 / 程序性记忆,并给出各自存储位置
  2. 明确难点在写入策略而不是存储选型
  3. 有写入门槛:提取器 + 类型约束 + 置信度阈值 + 黑名单
  4. 高价值结构化档案常驻、长尾走检索的分层设计
  5. 记忆可更新可失效:时间戳、覆盖而非并列、TTL
  6. 检索按触发条件而非每轮,且有注入预算
  7. 说得出长期记忆的代价(噪声、陈旧污染、不可复现、合规负担)
  8. 加分:多租户隔离在存储层强制,缓存键带身份
  9. 加分:用户可见可删、敏感类别不入库

常见错误

「把对话历史存进向量库就是记忆」——四类混成一类,后续追问全塌。
记忆只增不改,说不出冲突检测与失效机制。
每轮都做记忆检索并全量注入,没有预算概念。
把模型的推测当事实写进记忆,导致错误被反复引用放大。
用纯自由文本存记忆,结果连"发生了冲突"都发现不了。
完全不提合规与多租户隔离——在 toB 或个人助手场景是硬伤。
认为记忆系统就是 RAG 的一个应用,看不出在线增量、更新、删除这些结构性差异。
出了串号问题只说"加上用户过滤",没意识到隔离该在存储层强制。

关联学习