• Memory 记忆设计讨论:为什么 Agent Memory 不能只靠向量数据库?


    这是 Agent Memory 系列的第二篇文章。上一篇先给出了一个总体判断:Memory 是一套让 Agent 能够持续使用历史上下文的能力。

    这篇只讨论一个经常出现的问题:

    既然 Agent 需要从历史信息中找内容,接入向量数据库不就可以了吗?

    我的答案是:向量数据库很有用,但它只解决了召回问题的一部分,不能单独承担 Memory。

    一、向量数据库解决了什么

    向量数据库通常把文本或其他内容转换成向量,再根据向量之间的距离找出语义上相似的内容。

    例如,用户说:

    继续处理我上次的旅行计划。

    系统可以把这句话转换成向量,然后从历史对话中找出和“旅行计划”语义相近的内容。这比只依赖关键词更灵活,因为“出行安排”“订酒店”“航班选择”可能没有相同的字面词,却属于同一个语义主题。

    对于长文本、开放问法和模糊表达,向量检索确实很有价值。

    但“相似”不等于“应该使用”。

    二、相似内容不一定是当前上下文

    假设用户过去有两个旅行计划:

    • 去年夏天的日本旅行
    • 今年冬天的家庭旅行

    用户说“继续上次的旅行计划”,两个计划都可能被向量检索召回。相似度只能说明它们都和旅行有关,不能判断用户指的是哪一个。

    因此,系统还需要结合:

    • 任务标识
    • 时间范围
    • 目的地
    • 当前会话
    • 用户的指代习惯
    • 是否存在多个候选任务

    如果有两个候选都合理,最好的行为不是让模型硬猜,而是向用户澄清。

    三、向量检索不知道权限

    再看一个更严重的问题。

    用户可能同时参与个人旅行、家庭旅行和公司的商务出差。它们的记录来源不同,允许使用的范围也不同。

    向量检索只关心内容是否相似,并不天然知道:

    • 这条信息属于谁?
    • 当前 Agent 是否有权访问?
    • 信息是否只允许在某个任务中使用?
    • 是否包含不应该暴露给当前应用的内容?

    “先把所有相似内容搜出来,再让模型判断哪些不能看”是很危险的做法。因为敏感信息已经进入了模型上下文,后面的 Prompt 约束不能替代真正的访问控制。

    更可靠的顺序应该是:

    先确认用户、任务和权限范围,再做召回;召回结果还要经过服务端过滤,最后才交给模型。

    权限不是检索结果的一个排序因素,而是检索前的硬约束。

    四、向量检索不知道信息是否过期

    用户去年说过:“预算控制在 8000 元以内。”

    今年他说:“这次预算可以到 10000 元。”

    两句话都可能和当前旅行计划相关,向量检索也可能把它们都找出来。但系统必须知道后一条在当前计划中替代了前一条,而不是让模型自己猜哪条更新。

    这需要结构化字段,例如:

    • 生效时间
    • 失效时间
    • 版本号
    • 替代关系
    • 当前状态
    • 适用范围

    向量可以帮助找到候选内容,但不能替代版本和生命周期管理。

    五、向量检索无法处理事实冲突

    用户可能先说“酒店最好靠近市中心”,后来又说“这次为了安静,远一点也可以”。

    这不是简单的重复信息,而是一个条件变化:通常偏好可能仍然是靠近市中心,但本次任务有一个明确例外。

    如果所有内容只保存成向量,系统很难可靠表达:

    • 长期偏好是什么
    • 本次例外是什么
    • 例外适用到什么时候
    • 本次例外是否已经结束

    真正的 Memory 需要一个处理冲突的过程。新信息应该先成为候选,再由规则、来源、时间和用户确认决定它是新增、更新、替代,还是只在当前任务中临时生效。

    六、向量检索也不能表示任务进度

    “酒店已经筛选了三家,但还没有确认付款”是任务状态,不是语义记忆。

    如果把它写成一段摘要并向量化,下一次召回时可能找得到,但系统无法保证它是当前任务的最新状态,也无法安全地执行下一步。

    任务状态至少应该结构化表示:

    goal: 完成家庭旅行预订
    done: 已确定目的地,已筛选酒店
    missing: 尚未确认酒店和付款方式
    next: 展示三家候选酒店
    blocker: 等待用户确认
    

    这类数据应该直接查询,而不是依赖相似度和摘要推断。

    七、那向量数据库应该放在哪里

    我的理解是,向量检索应该作为 Retrieval,也就是召回层的一部分。

    一条更完整的读取链路可以是:

    1. 确认当前用户、任务、会话和权限
    2. 查询结构化的任务状态和当前有效事实
    3. 用关键词检索精确匹配内容
    4. 用向量检索补充语义相关内容
    5. 根据时间和来源进行排序
    6. 检查来源、完整性、时效性和上下文预算
    7. 组装成 Agent 可以使用的上下文

    向量召回在这里很重要,但它的位置是“帮助找到相关内容”,而不是“定义什么内容可以成为事实”。

    八、为什么第一阶段不必急着选择最复杂的存储

    如果事件契约、来源、作用域和事实更新机制还没有定义清楚,先建设复杂的存储系统,往往会把一个尚未明确的产品问题包装成数据库问题。

    一个更稳妥的起点是:

    • 用关系表保存事件、证据、候选、正式记忆和任务状态
    • 为正文和证据建立可追溯引用
    • 用向量索引提供语义召回
    • 让索引可以重建,而不是把索引当作唯一事实来源

    这样未来可以增加全文检索、图关系查询或其他索引,而不用改变产品事实的定义。

    结论

    向量数据库解决的是“哪些内容语义上相似”。

    Agent Memory 还要解决:

    • 这条内容是否属于当前任务
    • 当前 Agent 是否有权看到
    • 信息是否仍然有效
    • 新旧事实如何冲突
    • 任务做到哪一步
    • 用户如何纠正和删除
    • 外部动作是否真的成功

    所以更准确的说法是:

    向量数据库可以是 Agent Memory 的一个重要组件,但向量数据库本身不是 Agent Memory。

    下一篇继续讨论:如果不把所有内容塞进一个向量库,工程上到底应该设计哪些数据对象。

  • 相关阅读:
    2022牛客多校联赛第九场 题解
    初识设计模式 - 命令模式
    C# 如何将表格数据转成实体
    再谈基于Ocelot API网关和IdentityServer的API认证与授权
    【Android 开发】 面试官刨根问底?教你如何避免翻车沟通表达能力
    springboot整合redis,并使用@Cacheable等注解进行缓存
    Nginx莫名奇妙返回了404
    静息态fMRI中的非线性功能网络连接
    @hook扩展分析
    [BSidesCF 2020]Had a bad day1
  • 原文地址:https://www.cnblogs.com/duwenlong/p/22926147