5.2 长期记忆:向量数据库与写入机制


5.2 长期记忆:向量数据库与写入机制

短期记忆只能装下当下。Agent 真正的「阅历」——历史对话、用户偏好、领域知识、过往经验——必须存在短期记忆之外的地方。这就是长期记忆,它让 Agent 从「金鱼」变成「有阅历的助手」。这一节讲清长期记忆的载体(向量数据库)、索引(Embedding)、选型与写入机制。

5.2.1 长期记忆的本质:跨会话的档案柜

如果说短期记忆是「工作台」,长期记忆就是「档案柜」:

维度 短期记忆(工作台) 长期记忆(档案柜)
容量 有限(Token 窗口) 近似无限
速度 极快(已在上下文) 慢(需检索)
持久 单次会话 跨会话/跨任务
访问 LLM 直接看 必须先检索再拼进 Prompt

长期记忆的核心动作是「存进档案 → 按需检索 → 拼回工作台」:

💡 长期记忆 ≠ 数据库:传统数据库靠「精确匹配」查(如 WHERE id=123),长期记忆靠「语义相似」查(如「我之前问过类似的吗」)。这种语义检索靠 Embedding + 向量数据库实现,是 Agent 记忆区别于传统存储的根本特征。

5.2.2 Embedding:把文本变成向量

要让计算机做「语义相似」检索,第一步是把文本变成向量——这个过程叫 Embedding

Embedding 是什么

Embedding 把任意长度的文本,映射成一个定长的数值向量(如 768 维或 1536 维浮点数)。

"苹果 2024 营收 $391B" → [0.21, -0.45, 0.88, ..., 0.12] (768 维) "Apple FY2024 revenue" → [0.19, -0.42, 0.91, ..., 0.10] (相似) "今天天气真好" → [-0.33, 0.67, 0.05, ..., -0.88] (不相似)

关键性质:语义相近的文本,向量也相近。

相似度的度量

两个向量的「相似度」通常用余弦相似度点积度量。余弦相似度公式:

\text{sim}(A, B) = \cos(\theta) = \frac{A \cdot B}{\|A\| \cdot \|B\|}
  • 值域 [-1, 1],越大越相似。
  • 1 表示方向完全一致(极相似),0 表示正交(无关),-1 表示反向。
查询: "苹果营收" 候选 A: "Apple revenue 2024" sim = 0.92 ← 最相关 候选 B: "苹果的营养价值" sim = 0.71 ← 一词多义干扰 候选 C: "今天的股市行情" sim = 0.35 ← 不相关

⚠️ Embedding 的多义词问题:「苹果」既可是公司也可是水果。Embedding 把两者混在一个向量里,会让「苹果营收」误匹配到「苹果营养」。对抗多义词干扰,靠查询改写(5.3 节)或混合检索(关键词+语义)。

Embedding 模型选型

模型类型 代表 特点
通用英文 OpenAI text-embedding-3、Cohere 英文强、多语言支持
中文优化 BGE、M3E、Ernie 中文场景更准
多语言 E5、BGE-M3 跨语言检索
领域定制 自己微调 专业领域(医疗、法律)

选型考虑:语言、领域、维度、速度、成本。生产推荐先用通用模型验证,再按需换领域模型。

5.2.3 向量数据库:存储与检索

文本变成向量后,需要专门存储和检索——这就是向量数据库(Vector Database)

向量数据库的核心能力

能力 说明
存储 存向量 + 原文 + 元数据
检索 给一个查询向量,返回最相似的 Top-K
过滤 按元数据预过滤(如「只看用户 A 的记忆」)
更新/删除 增量维护记忆

检索的算法

朴素检索是「线性扫描」——把查询向量与库里每个向量算相似度,排序取 Top-K。但库里几百万向量时,线性扫描太慢。生产向量库用**近似最近邻(ANN)**算法:

算法 思想 代表实现
HNSW 分层小世界图 大多数主流库的默认
IVF 倒排索引 Llama Index、Faiss
PQ 乘积量化压缩 大规模场景

ANN 牺牲少量精度(可能漏掉极少数真正相似项),换取数量级的速度提升

5.2.4 主流向量数据库对比

向量库 类型 特点 适用
Chroma 嵌入式 轻量、零配置、纯 Python 原型、单机、小规模
Pinecone 云托管 全托管、易扩展、收费 生产、不愿运维
Weaviate 自托管 功能全、支持混合检索 生产、需定制
Qdrant 自托管 Rust 实现、高性能 高吞吐生产
Milvus 自托管 分布式、超大规模 亿级向量
pgvector Postgres 扩展 复用现有 PG 已有 PG 的项目
Faiss 仅算法、无服务 自己造轮子

选型决策树

💡 新手选型建议Chroma 起步 → Qdrant/Weaviate 进生产。Chroma 零配置适合原型验证;当规模或可靠性要求上来,迁到 Qdrant 或 Weaviate。Pinecone 适合「不想运维、付费换省心」的团队。

5.2.5 记忆的写入策略

把什么写进长期记忆、什么时候写,是 5.2 节的核心问题。

写入的「不该全写」原则

第 2.2 节已强调:不是所有观察都值得写进长期记忆。全量写入会让库膨胀且充满噪声。

写入策略 触发 内容
全量写入 每步 所有 Thought/Action/Observation
里程碑写入 任务关键节点 完成的子目标、关键决策
偏好写入 检测到偏好变化 「用户喜欢简洁回答」
事实写入 关键事实更新 「公司 A 营收已发布」
反思写入 任务失败/成功后 经验笔记(Reflexion)

写入的「该写什么」

该写 不该写
用户长期偏好 临时闲聊
关键事实与决策 中间步骤细节
任务的成功/失败经验 重复的过程数据
跨会话有用的信息 仅本次任务相关的临时态

一个分层写入的模板

按类型分库,每库不同的写入与检索策略,是大型 Agent 的常见做法。

5.2.6 去重与更新

写入时会遇到两个问题:重复写入信息更新

去重

同一个事实可能被多次写入(如每次对话都确认「用户时区 UTC+8」)。

去重方式 做法
完全去重 文本完全相同则不写
语义去重 语义相似度高则合并
键去重 用元数据键(如 user_id+key)判重

更新(矛盾消解)

新事实可能与旧事实矛盾(如「用户时区是 UTC+8」→ 后来「用户搬到 UTC-5」)。

处理 做法
新覆旧 直接覆盖(适用于时效数据)
版本保留 都存,按时间排序
标记失效 旧的标记 invalid 但不删
冲突告警 触发人工确认

⚠️ 不处理矛盾 = 记忆出错:一个同时存「用户在 UTC+8」和「用户在 UTC-5」的 Agent,下次决策时会迷惑。矛盾消解是长期记忆的必修课——通常用「新覆旧 + 关键变更触发确认」组合。

5.2.7 短期-长期记忆的协同:RAG 流水线预告

把短期与长期记忆串起来用,就是下一节 RAG 的核心。先给个全景预告:

这个「查询 → 向量化 → 检索 → 拼上下文 → 推理 → 写回」的闭环,就是 RAG 的完整流水线,5.3 节会详细展开。

5.2.8 长期记忆的反模式

反模式 表现 后果 正确做法
全量写入 每步都存 库膨胀+噪声多 分类型分级写入
不检索只用 长期记忆存了不用 等于没存 每轮按需检索
不分库 偏好/事实/经验混存 检索互相干扰 按类型分库
不去重 同一事实写 N 次 浪费空间+排名失真 语义/键去重
不更新 旧事实不消解 决策矛盾 新覆旧+版本管理
过早大规模 一开始就上 Milvus 运维成本高 Chroma 起步按需升级

💡 长期记忆的设计核心是「克制」:不是「能存多少存多少」,而是「该存的存、该查的查、该忘的忘」。一个塞满但从不被检索的记忆库,比一个精简但高频使用的库更没用。

本节小结

  • 长期记忆 = 跨会话的档案柜,近似无限容量但需检索。它区别于传统数据库的根本特征是语义检索(靠 Embedding),而非精确匹配。
  • Embedding 把文本变成定长向量,语义相近的向量也相近。相似度用余弦相似度度量。多义词干扰靠查询改写或混合检索对抗。
  • 向量数据库用 ANN 算法(HNSW/IVF/PQ)实现近似最近邻检索,牺牲少量精度换数量级速度。主流库:Chroma(原型)、Pinecone(托管)、Weaviate/Qdrant(生产)、Milvus(超大规模)、pgvector(已有 PG)。
  • 写入策略:不全写,按类型分级——偏好/事实/经验/归档分库。配合去重(完全/语义/键)与矛盾消解(新覆旧/版本/告警)。
  • 长期记忆设计核心是「克制」:该存的存、该查的查、该忘的忘。塞满但不被检索的库等于没用。

下一节《5.3 RAG 检索增强生成》将把短期与长期记忆串成完整流水线,讨论从朴素 RAG 到 Advanced RAG 的演进。


作者与出处
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 会发光的石头的小龙虾 转发
评论区 (0)
U