Skip to main content

Agent 长对话 Memory 怎么设计?四层机制解决摘要丢信息

· 6 min read

长对话的 Agent Memory 不是「压缩就行」,是分层管理。

  1. 问题核心:summary 平等压缩所有内容,用户核心目标和硬性偏好被一起稀释
  2. Working Memory:类似 system prompt 的常驻字段,永久不参与压缩,守住硬性约束。
  3. 分段增量摘要:滚动窗口分段保存,每段打时间戳 + 优先级标签,不合并。
  4. 向量数据库兜底:摘要丢细节没关系,原文存向量库按需召回。
  5. 多 Agent 方案:Coordinator + Observer + Reflect + Retriever 四角色分工。
  6. 场景选型:几十轮轻量对话 / 中长期 / 超长期多工具三档,对号入座。

摘要为什么会丢信息?

根因是「一锅煮」——所有内容被平等压缩,没有分层。

多轮对话 summary 丢信息是工程界公认的痛点,但 4 个具体原因往往被混在一起讨论:

  1. 平等对待所有内容:核心需求和闲聊被同等压缩,硬性约束被噪声淹没。
  2. 时序丢失:早期「不要用 Vue」和后期闲聊「今天天气不错」,几轮后根本分不清哪条是约束。
  3. 静态偏好和临时会话混在一起压缩:用户身份、长期目标这些不该压缩的东西,被一起扔进 summary。
  4. 粗颗粒度丢失细节:否定类需求("不要出错"、"输出简洁")、工具参数级别的约束,summary 根本装不下。

说白了,这不是 summary 模型的锅,是 system prompt 没设计好——没告诉模型「哪些是底线、哪些可以压缩」。

四层机制组合拳

第一层:Working Memory 兜住底线

Working Memory 是一组常驻字段,类似 system prompt,每轮对话都注入 context,永远不参与 summary 压缩。

具体存什么:

  • 用户核心目标(硬性)
  • 硬性偏好(语言、风格、工具栈)
  • 禁止项(明确禁止的行为)
  • 身份信息、业务约束

关键设计:字段化更新,不是字符串叠加。用户改了一个偏好,直接替换对应字段,不要往 working memory 末尾追加新内容。叠加会导致前后信息不一致,模型产生「幻觉」——其实不是模型幻觉,是你自己存的内容前后矛盾。

优势:低成本,守住最高优先级硬性要求。

局限:只能存预设字段,无法覆盖零散的历史对话细节——这些交给后面三层。

第二层:分段增量摘要保留时序

不要一次性把全部对话压成一段 summary。

设置阈值(经验值 2K token),超过就滚动压缩:

  • 第 1~10 轮 → summary_1
  • 第 11~20 轮 → summary_2
  • 每段独立保存,不合并
  • 每段打标签:时间戳 + 优先级标志 + 约束条件

用户目标、硬性约束标高权重,闲聊标低权重。检索时优先加载高优先级分段,低权重内容按需取舍。

对比一次性总摘要的优势:分段保留时序逻辑,不会抹平早期的关键信息。

实操时,优先级打标完全可以在 system prompt 里写好——让模型在生成 summary 时顺手标,不是额外工程。

第三层:向量数据库存原文兜底

摘要丢细节没关系,向量数据库存的是完整原文,按需召回。

具体做法:

  • 每次对话完结,request + response 全文存入向量数据库,不只存 summary
  • 喂给 LLM 的 context 里,塞的是精简 summary
  • 当模型发现 summary 信息不足、回答不上来时,触发向量检索,召回原始上下文

核心设计哲学:summary 是给 LLM 看的「压缩视图」,向量数据库是「原文档案库」。两者不冲突,是不同抽象层级的互补。

第四层:多 Agent 分工

超长期对话 + 高频工具调用 + 海量返回结果,单 agent 撑不住,需要 共享 memory bus + 多 Agent 分工

  • Coordinator(主对话 agent):只拿近期上下文 + memory store 注入的高优信息,负责回复用户。
  • Observer agent:订阅对话流和工具流,抽取结构化事实,写入 memory store。
  • Reflect agent:对 memory store 做优先级评估、冲突消解、过时标记。
  • Retriever agent:负责向量数据库的语义召回,补全细节。

通过事件队列解耦,各 agent 异步处理,主对话 agent 只看「已经处理好的」有效记忆。

三种场景怎么落地?

按对话长度和工具复杂度,分三档。

场景一:轻量对话(几十轮 + 少量工具)

单 agent,无需向量数据库。

context 拼装:

system prompt
+ 最近的 N 轮对话(滑动窗口截断)
+ working memory 固定字段

典型场景:客服电话问答,客户问完就走,没必要保存偏好到向量库。

场景二:中长期对话

加一层向量数据库召回。

context 拼装:

system prompt
+ working memory(高频固定信息,markdown 格式)
+ chat history(最近对话历史)
+ 向量数据库 top K 召回(query embedding 检索)

对话完结后,把完整原文存到向量数据库,下次召回用。

场景三:超长期 + 多工具 + 海量返回

多 Agent + 共享 memory bus。

四角色分工见上文,主对话 agent 的 context 拼装:

memory store(高优信息注入)
+ 向量数据库召回(细节补充)
+ 近期对话上下文

对话完结后:

  • Observer agent 抽取事实 → memory store
  • Reflect agent 评估优先级 / 消解冲突 / 标记过时
  • 原文存入向量数据库

哪些设计「过了」?

多 agent 方案里的 Reflect agent 独立存在这点其实值得讨论:

  • Observer 写完 memory store,Reflect 再去评估优先级和冲突——这两步能不能合并?
  • 写完就立刻检查冲突,和「写完另起一个 agent 检查」,本质上没区别。
  • 分开反而 不及时:中间空窗期,主 agent 已经基于「未消解」的 memory 做出决策。

我的判断:四角色架构是工业界常见的「标准答案」,但 Reflect 这步如果不是必须,可以合并到 Observer 里——减少一个事件循环,主 agent 看到的永远是最新最干净的 memory

所以这套方案不用原封照搬,理解每一层的目的之后,按需裁剪 才是工程落地的正确姿势。


References

  1. 08 吐血整理的Agent memory 设计 —— AI_Julie