Agent 记忆系统:对话管理、向量检索与长期记忆

一、概念速查

短期记忆 vs 长期记忆 对比表

维度 短期记忆(STM) 长期记忆(LTM)
存储位置 上下文窗口 / 内存 向量数据库 / 知识图谱
生命周期 会话绑定,结束即清理 跨会话持久化
容量限制 模型上下文窗口(4K-128K tokens) 理论上无限(外部存储)
更新频率 每次交互实时更新 选择性巩固,低频率
访问延迟 毫秒级(内存) 10-200ms(网络+检索)
实现方案 LangGraph Checkpointer / 滑动窗口 Mem0 / Zep / Chroma + Embedding

记忆检索策略速查

策略 原理 适用场景 缺陷
相似度检索 查询向量与记忆向量做余弦距离排序 模糊语义联想 不感知时间、不处理否定
时间衰减排序 score = sim * e^(-λ * days) 时效敏感场景(价格、库存) 可能压制高频低质记忆
重要性加权 记忆入库时 LLM 预打分(1-10) 用户偏好、关键事实 打分成本高,依赖 LLM 质量
混合搜索(BM25 + 向量) 关键词精确匹配 + 语义检索融合 通用生产环境 实现复杂度中等

向量数据库选型对比

产品 运维成本 扩展上限 混合搜索 关系查询 适用阶段
Chroma 极低(pip install) 百万级 不支持 本地开发 / 原型验证
pgvector 低(PG 扩展) 千万级 需自行组合 强(SQL) 已有 PG 的中小规模
Milvus 高(需 etcd+MinIO) 十亿级+ 支持 大规模生产,有运维团队
Qdrant 中(Rust 单二进制) 亿级 支持 中(过滤强) 高性能过滤场景
Pinecone 极低(SaaS) 亿级 内置 快速上线,无 DBA 团队

选型路径:原型用 Chroma → 生产初期用 pgvector(有 PG 基础)或 Pinecone(无运维)→ 规模增长后评估 Milvus / Qdrant。

Embedding 模型选型要点

Embedding 模型直接决定语义检索的天花板。同一段文本经不同模型编码后,检索召回率可能相差 15%-30%。

模型 维度 最大输入 语言 适用场景
text-embedding-3-small 1536 8K tokens 多语言 通用,性价比最高
text-embedding-3-large 3072 8K tokens 多语言 高精度需求,成本翻倍
BGE-M3 1024 8K tokens 多语言 开源,支持稠密+稀疏双路
multilingual-e5 1024 512 tokens 多语言 开源,短文本匹配强
m3e 768 512 tokens 中文为主 国内中文场景首选

选型原则:精度优先场景用 text-embedding-3-large(3072 维),成本敏感用 text-embedding-3-small(1536 维)。中文场景在 Recall@5 上 m3e 约 89%,BGE-M3 约 92%,OpenAI 系列约 93%-95%。

代码示例:向量库记忆存储与检索

import chromadb
from chromadb.utils import embedding_functions

client = chromadb.Client()
ef = embedding_functions.DefaultEmbeddingFunction()
collection = client.create_collection(name="agent_memory", embedding_function=ef)

collection.add(
    documents=["用户偏好:喜欢简洁回复,不要解释"],
    metadatas=[{"user_id": "u1", "importance": 8, "timestamp": "2025-01-01"}],
    ids=["mem_001"]
)

results = collection.query(
    query_texts=["用户希望回复风格如何?"],
    n_results=3
)
print(results["documents"])

二、底层原理

混合记忆架构

生产级 Agent 不依赖单一记忆层,而是短期 + 长期并行检索后融合

用户输入

短期记忆检索

长期记忆检索

滑动窗口上下文

向量相似度 Top-K

记忆融合与重排序

注入 LLM 上下文窗口

生成回复

异步写回记忆

短期记忆维护最近 N 轮对话,保证基础连贯性。长期记忆从向量数据库检索跨会话的相关事实。两者经 Rerank 模型精排后合并,送入 LLM。回复生成后,新产生的关键事实异步写回长期记忆。

这种架构在 LoCoMo 基准测试上的数据显示:Mem0 用 1.44 秒 p95 延迟 + 1,800 tokens 达到了全量上下文 72.9% 准确率的 91.8%(66.9%),换来了 13 倍提速和 90% Token 节省。作为对比,图谱增强版 Mem0g 仅在时序推理等特定场景带来边际收益(综合提升 1.5 分),表明结构化记忆的实际增益集中在常规对话场景,图谱并非普适银弹。

混合架构在实际落地上还需要解决一个关键问题:短期记忆与长期记忆之间的冲突消解。当长期记忆携带的上下文与当前对话窗口中的信息存在分歧时(如用户偏好在近期发生变化),系统需要为短期信息赋予更高优先级。实践中通常采用"短期优先、长期参考"策略——向量检索结果作为补充而非替代,与滑动窗口合并时做去重和置信度排序。

滑动窗口 vs 摘要压缩的场景选择

低(闲聊)

高(含用户偏好)

对话增长

Token 超限?

保留全部

信息密度

滑动窗口丢弃最早

增量摘要压缩

直接丢弃

LLM 生成摘要

摘要替换 N 轮对话

组合后注入上下文

场景 推荐策略 原因
客服对话(用户反复问同一产品) 滑动窗口 最新上下文最重要,信息重复度高
医疗问诊(早期描述关键症状) 摘要压缩 早期信息不可丢失,需压缩保留
代码审查助手 Token 预算 + 摘要 长对话中早期决策理由需可追溯
通用场景 组合策略 滑动窗口兜底 + 高价值信息压缩
窗口策略实现参数对比
策略 实现方式 Token 开销 信息损失 典型窗口大小 冷启动耗时
固定滑动窗口 保留最近 N 轮对话,丢弃超期 低(N×平均轮 tokens) 高(丢弃的早期信息永久丢失) 10-50 轮
Token 预算窗口 保留最近对话至 M tokens,超出后截断 中(精确控制) 中(可能截断中间轮次) 4K-32K tokens
增量摘要 每 N 轮对过期轮次执行 LLM 摘要 高(摘要推理成本) 低(关键信息压缩保留) 取决于压缩比 单次摘要 0.5-2s
分级窗口 L1 保留 N 轮完整 + L2 摘要存档 中高 极低 L1=3-5 轮,L2=20+ 轮 首次摘要延迟

固定滑动窗口实现成本最低,但信息损失不可控。Token 预算窗口是生产中最常用的折中方案——设置 8K-16K 的 hard limit,超出后优先保留最近轮次和含工具调用结果的轮次。分级窗口在追求高准确率的场景(如医疗、法律)中表现最优。

代码示例:滑动窗口 vs 摘要压缩

from collections import deque

class SlidingWindow:
    def __init__(self, max_rounds: int = 10):
        self.buffer = deque(maxlen=max_rounds)

    def add(self, user: str, assistant: str):
        self.buffer.append({"user": user, "assistant": assistant})

    def get_context(self) -> list:
        return list(self.buffer)

class SummaryCompressor:
    def __init__(self, max_rounds: int = 10):
        self.max_rounds = max_rounds
        self.history = []
        self.summary = ""

    def add(self, user: str, assistant: str):
        self.history.append({"user": user, "assistant": assistant})
        if len(self.history) >= self.max_rounds:
            self._summarize()

    def _summarize(self):
        self.summary = f"[摘要压缩] 共 {len(self.history)} 轮对话已压缩"
        self.history = []

    def get_context(self) -> dict:
        return {"summary": self.summary, "recent": self.history}

win = SlidingWindow(3)
cmp = SummaryCompressor(3)

for i in range(5):
    win.add(f"第{i}轮用户", f"第{i}轮助手")
    cmp.add(f"第{i}轮用户", f"第{i}轮助手")

print("滑动窗口上下文轮数:", len(win.get_context()))
print("摘要压缩 - 摘要:", cmp.get_context()["summary"])
print("摘要压缩 - 近期轮数:", len(cmp.get_context()["recent"]))

多用户记忆隔离方案

隔离层

Collection 隔离(物理)

metadata 过滤(逻辑)

RLS(行级安全)

用户 B

collection: user_b

thread: session_2

用户 A

collection: user_a

thread: session_1

三种隔离级别:

  1. Collection 隔离:每用户独立向量集合。安全性最高,资源利用率最低。适合金融、医疗等合规强场景。
  2. Metadata 过滤:共享 collection,每条向量携带 user_id 标签,查询时强制过滤。资源利用率最高,需防范查询注入。
  3. RLS 行级安全:仅 pgvector 支持,PostgreSQL 原生行级权限控制,兼顾资源利用与安全。

隔离方案的选择取决于合规要求与资源预算。物理隔离的上限是 Collection 数(Milvus 建议不超过 65536),逻辑隔离的上限是过滤性能。

三、架构设计原则

记忆写入时机

时机 写入内容 策略
每轮对话结束 用户偏好、关键决策 异步写,不阻塞主流程
任务完成 执行路径、成功/失败标记 批量写入 + 元数据标注
工具调用后 工具返回结果摘要 LLM 摘要后再写入,避免冗余
LLM 空闲期 短期记忆→长期记忆巩固 后台进程扫描 STM 做摘录

核心原则:写入异步化,不阻塞推理路径。高频写入采用批量 buffer,每 100 条或每 30 秒 flush 一次。

写入内容的质量控制

并非所有信息都值得写入长期记忆。写入前需经过"感知→判断→提炼"三步过滤:感知层识别潜在有价值信息(工具返回结果、用户明确表达偏好、决策变更),判断层用轻量级分类器(或 LLM 单次调用)过滤掉寒暄、重复和噪声内容,提炼层对原始文本做摘要压缩后入库。一套经过调优的过滤链路通常可以削减 50%-70% 的无效写入。

检索策略组合

事实查询('价格?')

偏好查询('喜欢什么?')

历史查询('上次怎么做的?')

关系查询('和什么有关?')

用户查询

查询类型

混合搜索 BM25 + 向量

重要性排序 Top-K

时间衰减 + 时间范围过滤

知识图谱遍历

Rerank 精排

Top-5 注入上下文

生产环境起点是混合搜索(BM25 + 向量)+ Rerank。这以大约 20% 的额外复杂度换取了关键词精确匹配的显著增益。只有在处理高度关联的知识库且需要多跳推理时,才引入 GraphRAG。

检索策略对比总结
策略 召回率(Recall@5) 精确率 延迟(p95) 实现难度
纯向量余弦相似度 60-75% 中等 50-100ms
BM25 全文检索 50-65% 高(关键词精确匹配) 10-30ms
混合搜索(BM25 + 向量) 75-90% 60-120ms
混合 + Rerank 80-93% 极高 80-200ms 中高
混合 + Rerank + MMR 去重 78-90% 极高(结果多样性强) 100-250ms

MMR(最大边界相关性)在 Top-20 候选结果中做多样性重排序,避免检索结果高度同质化。加入 MMR 通常会使 Recall@5 略微下降 2-3%,但显著提升生成质量——因为 LLM 收到的输入信息面更广。

记忆过期清理

三种遗忘策略组合使用:

记忆池

年龄 > TTL?

归档到冷存储

重要性 < 阈值?

删除

相似度 > 0.85?

合并到已有记忆

保留

  • 时间衰减:指数函数 importance_now = original * e^(-λ * days)。λ 按记忆类型配置:用户偏好 λ=0.01(衰减慢),对话印象 λ=0.1(衰减快)。
  • 重要性评分:写入时 LLM 打分(1-10 分制,低价值如"用户打了个招呼"2 分,优先淘汰)。
  • 相似度合并:新记忆与已有记忆余弦相似度 >0.85 时触发 LLM 驱动的增量合并,避免同一事实的冗余副本。
不同遗忘策略的存储影响数据
策略 30 天累积记忆量 检索延迟(p95) 信息利用率
无遗忘 100%(基准) 500ms-2s 呈下降趋势
仅 TTL 过期 40-60% 120-300ms 可能误删有用信息
TTL + 重要性评分 25-40% 80-150ms 高价值信息保留
TTL + 重要性 + 合并去重 15-30% 60-100ms 无冗余,精炼

从第一天就设计遗忘机制,不要等到存储爆炸再补。没有遗忘的记忆系统最终会淹没在信息噪声中,检索质量随记忆量增长逆向下降。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐