Agent 记忆系统:对话管理、向量检索与长期记忆
一、概念速查
短期记忆 vs 长期记忆 对比表
| 存储位置 | 上下文窗口 / 内存 | 向量数据库 / 知识图谱 |
| 生命周期 | 会话绑定,结束即清理 | 跨会话持久化 |
| 容量限制 | 模型上下文窗口(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 不依赖单一记忆层,而是短期 + 长期并行检索后融合:
#mermaid-svg-KOYR1MnNcLH6KLqo{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KOYR1MnNcLH6KLqo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KOYR1MnNcLH6KLqo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KOYR1MnNcLH6KLqo .error-icon{fill:#552222;}#mermaid-svg-KOYR1MnNcLH6KLqo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KOYR1MnNcLH6KLqo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KOYR1MnNcLH6KLqo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KOYR1MnNcLH6KLqo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KOYR1MnNcLH6KLqo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KOYR1MnNcLH6KLqo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KOYR1MnNcLH6KLqo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KOYR1MnNcLH6KLqo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KOYR1MnNcLH6KLqo .marker.cross{stroke:#333333;}#mermaid-svg-KOYR1MnNcLH6KLqo svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KOYR1MnNcLH6KLqo p{margin:0;}#mermaid-svg-KOYR1MnNcLH6KLqo .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-KOYR1MnNcLH6KLqo .cluster-label text{fill:#333;}#mermaid-svg-KOYR1MnNcLH6KLqo .cluster-label span{color:#333;}#mermaid-svg-KOYR1MnNcLH6KLqo .cluster-label span p{background-color:transparent;}#mermaid-svg-KOYR1MnNcLH6KLqo .label text,#mermaid-svg-KOYR1MnNcLH6KLqo span{fill:#333;color:#333;}#mermaid-svg-KOYR1MnNcLH6KLqo .node rect,#mermaid-svg-KOYR1MnNcLH6KLqo .node circle,#mermaid-svg-KOYR1MnNcLH6KLqo .node ellipse,#mermaid-svg-KOYR1MnNcLH6KLqo .node polygon,#mermaid-svg-KOYR1MnNcLH6KLqo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KOYR1MnNcLH6KLqo .rough-node .label text,#mermaid-svg-KOYR1MnNcLH6KLqo .node .label text,#mermaid-svg-KOYR1MnNcLH6KLqo .image-shape .label,#mermaid-svg-KOYR1MnNcLH6KLqo .icon-shape .label{text-anchor:middle;}#mermaid-svg-KOYR1MnNcLH6KLqo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KOYR1MnNcLH6KLqo .rough-node .label,#mermaid-svg-KOYR1MnNcLH6KLqo .node .label,#mermaid-svg-KOYR1MnNcLH6KLqo .image-shape .label,#mermaid-svg-KOYR1MnNcLH6KLqo .icon-shape .label{text-align:center;}#mermaid-svg-KOYR1MnNcLH6KLqo .node.clickable{cursor:pointer;}#mermaid-svg-KOYR1MnNcLH6KLqo .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KOYR1MnNcLH6KLqo .arrowheadPath{fill:#333333;}#mermaid-svg-KOYR1MnNcLH6KLqo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KOYR1MnNcLH6KLqo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KOYR1MnNcLH6KLqo .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KOYR1MnNcLH6KLqo .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KOYR1MnNcLH6KLqo .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KOYR1MnNcLH6KLqo .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KOYR1MnNcLH6KLqo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KOYR1MnNcLH6KLqo .cluster text{fill:#333;}#mermaid-svg-KOYR1MnNcLH6KLqo .cluster span{color:#333;}#mermaid-svg-KOYR1MnNcLH6KLqo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KOYR1MnNcLH6KLqo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KOYR1MnNcLH6KLqo rect.text{fill:none;stroke-width:0;}#mermaid-svg-KOYR1MnNcLH6KLqo .icon-shape,#mermaid-svg-KOYR1MnNcLH6KLqo .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KOYR1MnNcLH6KLqo .icon-shape p,#mermaid-svg-KOYR1MnNcLH6KLqo .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KOYR1MnNcLH6KLqo .icon-shape .label rect,#mermaid-svg-KOYR1MnNcLH6KLqo .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KOYR1MnNcLH6KLqo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KOYR1MnNcLH6KLqo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KOYR1MnNcLH6KLqo :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
用户输入
短期记忆检索
长期记忆检索
滑动窗口上下文
向量相似度 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 摘要压缩的场景选择
#mermaid-svg-I4dCjaKgGLZlNiPd{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-I4dCjaKgGLZlNiPd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-I4dCjaKgGLZlNiPd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-I4dCjaKgGLZlNiPd .error-icon{fill:#552222;}#mermaid-svg-I4dCjaKgGLZlNiPd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-I4dCjaKgGLZlNiPd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-I4dCjaKgGLZlNiPd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-I4dCjaKgGLZlNiPd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-I4dCjaKgGLZlNiPd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-I4dCjaKgGLZlNiPd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-I4dCjaKgGLZlNiPd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-I4dCjaKgGLZlNiPd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-I4dCjaKgGLZlNiPd .marker.cross{stroke:#333333;}#mermaid-svg-I4dCjaKgGLZlNiPd svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-I4dCjaKgGLZlNiPd p{margin:0;}#mermaid-svg-I4dCjaKgGLZlNiPd .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-I4dCjaKgGLZlNiPd .cluster-label text{fill:#333;}#mermaid-svg-I4dCjaKgGLZlNiPd .cluster-label span{color:#333;}#mermaid-svg-I4dCjaKgGLZlNiPd .cluster-label span p{background-color:transparent;}#mermaid-svg-I4dCjaKgGLZlNiPd .label text,#mermaid-svg-I4dCjaKgGLZlNiPd span{fill:#333;color:#333;}#mermaid-svg-I4dCjaKgGLZlNiPd .node rect,#mermaid-svg-I4dCjaKgGLZlNiPd .node circle,#mermaid-svg-I4dCjaKgGLZlNiPd .node ellipse,#mermaid-svg-I4dCjaKgGLZlNiPd .node polygon,#mermaid-svg-I4dCjaKgGLZlNiPd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-I4dCjaKgGLZlNiPd .rough-node .label text,#mermaid-svg-I4dCjaKgGLZlNiPd .node .label text,#mermaid-svg-I4dCjaKgGLZlNiPd .image-shape .label,#mermaid-svg-I4dCjaKgGLZlNiPd .icon-shape .label{text-anchor:middle;}#mermaid-svg-I4dCjaKgGLZlNiPd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-I4dCjaKgGLZlNiPd .rough-node .label,#mermaid-svg-I4dCjaKgGLZlNiPd .node .label,#mermaid-svg-I4dCjaKgGLZlNiPd .image-shape .label,#mermaid-svg-I4dCjaKgGLZlNiPd .icon-shape .label{text-align:center;}#mermaid-svg-I4dCjaKgGLZlNiPd .node.clickable{cursor:pointer;}#mermaid-svg-I4dCjaKgGLZlNiPd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-I4dCjaKgGLZlNiPd .arrowheadPath{fill:#333333;}#mermaid-svg-I4dCjaKgGLZlNiPd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-I4dCjaKgGLZlNiPd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-I4dCjaKgGLZlNiPd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-I4dCjaKgGLZlNiPd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-I4dCjaKgGLZlNiPd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-I4dCjaKgGLZlNiPd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-I4dCjaKgGLZlNiPd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-I4dCjaKgGLZlNiPd .cluster text{fill:#333;}#mermaid-svg-I4dCjaKgGLZlNiPd .cluster span{color:#333;}#mermaid-svg-I4dCjaKgGLZlNiPd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-I4dCjaKgGLZlNiPd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-I4dCjaKgGLZlNiPd rect.text{fill:none;stroke-width:0;}#mermaid-svg-I4dCjaKgGLZlNiPd .icon-shape,#mermaid-svg-I4dCjaKgGLZlNiPd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-I4dCjaKgGLZlNiPd .icon-shape p,#mermaid-svg-I4dCjaKgGLZlNiPd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-I4dCjaKgGLZlNiPd .icon-shape .label rect,#mermaid-svg-I4dCjaKgGLZlNiPd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-I4dCjaKgGLZlNiPd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-I4dCjaKgGLZlNiPd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-I4dCjaKgGLZlNiPd :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
否
是
低(闲聊)
高(含用户偏好)
对话增长
Token 超限?
保留全部
信息密度
滑动窗口丢弃最早
增量摘要压缩
直接丢弃
LLM 生成摘要
摘要替换 N 轮对话
组合后注入上下文
| 客服对话(用户反复问同一产品) | 滑动窗口 | 最新上下文最重要,信息重复度高 |
| 医疗问诊(早期描述关键症状) | 摘要压缩 | 早期信息不可丢失,需压缩保留 |
| 代码审查助手 | 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"]))
多用户记忆隔离方案
#mermaid-svg-KUHY7hkGRkYanW3F{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KUHY7hkGRkYanW3F .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KUHY7hkGRkYanW3F .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KUHY7hkGRkYanW3F .error-icon{fill:#552222;}#mermaid-svg-KUHY7hkGRkYanW3F .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KUHY7hkGRkYanW3F .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KUHY7hkGRkYanW3F .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KUHY7hkGRkYanW3F .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KUHY7hkGRkYanW3F .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KUHY7hkGRkYanW3F .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KUHY7hkGRkYanW3F .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KUHY7hkGRkYanW3F .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KUHY7hkGRkYanW3F .marker.cross{stroke:#333333;}#mermaid-svg-KUHY7hkGRkYanW3F svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KUHY7hkGRkYanW3F p{margin:0;}#mermaid-svg-KUHY7hkGRkYanW3F .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-KUHY7hkGRkYanW3F .cluster-label text{fill:#333;}#mermaid-svg-KUHY7hkGRkYanW3F .cluster-label span{color:#333;}#mermaid-svg-KUHY7hkGRkYanW3F .cluster-label span p{background-color:transparent;}#mermaid-svg-KUHY7hkGRkYanW3F .label text,#mermaid-svg-KUHY7hkGRkYanW3F span{fill:#333;color:#333;}#mermaid-svg-KUHY7hkGRkYanW3F .node rect,#mermaid-svg-KUHY7hkGRkYanW3F .node circle,#mermaid-svg-KUHY7hkGRkYanW3F .node ellipse,#mermaid-svg-KUHY7hkGRkYanW3F .node polygon,#mermaid-svg-KUHY7hkGRkYanW3F .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KUHY7hkGRkYanW3F .rough-node .label text,#mermaid-svg-KUHY7hkGRkYanW3F .node .label text,#mermaid-svg-KUHY7hkGRkYanW3F .image-shape .label,#mermaid-svg-KUHY7hkGRkYanW3F .icon-shape .label{text-anchor:middle;}#mermaid-svg-KUHY7hkGRkYanW3F .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KUHY7hkGRkYanW3F .rough-node .label,#mermaid-svg-KUHY7hkGRkYanW3F .node .label,#mermaid-svg-KUHY7hkGRkYanW3F .image-shape .label,#mermaid-svg-KUHY7hkGRkYanW3F .icon-shape .label{text-align:center;}#mermaid-svg-KUHY7hkGRkYanW3F .node.clickable{cursor:pointer;}#mermaid-svg-KUHY7hkGRkYanW3F .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KUHY7hkGRkYanW3F .arrowheadPath{fill:#333333;}#mermaid-svg-KUHY7hkGRkYanW3F .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KUHY7hkGRkYanW3F .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KUHY7hkGRkYanW3F .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KUHY7hkGRkYanW3F .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KUHY7hkGRkYanW3F .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KUHY7hkGRkYanW3F .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KUHY7hkGRkYanW3F .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KUHY7hkGRkYanW3F .cluster text{fill:#333;}#mermaid-svg-KUHY7hkGRkYanW3F .cluster span{color:#333;}#mermaid-svg-KUHY7hkGRkYanW3F div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KUHY7hkGRkYanW3F .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KUHY7hkGRkYanW3F rect.text{fill:none;stroke-width:0;}#mermaid-svg-KUHY7hkGRkYanW3F .icon-shape,#mermaid-svg-KUHY7hkGRkYanW3F .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KUHY7hkGRkYanW3F .icon-shape p,#mermaid-svg-KUHY7hkGRkYanW3F .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KUHY7hkGRkYanW3F .icon-shape .label rect,#mermaid-svg-KUHY7hkGRkYanW3F .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KUHY7hkGRkYanW3F .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KUHY7hkGRkYanW3F .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KUHY7hkGRkYanW3F :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
隔离层
Collection 隔离(物理)
metadata 过滤(逻辑)
RLS(行级安全)
用户 B
collection: user_b
thread: session_2
用户 A
collection: user_a
thread: session_1
三种隔离级别:
隔离方案的选择取决于合规要求与资源预算。物理隔离的上限是 Collection 数(Milvus 建议不超过 65536),逻辑隔离的上限是过滤性能。
三、架构设计原则
记忆写入时机
| 每轮对话结束 | 用户偏好、关键决策 | 异步写,不阻塞主流程 |
| 任务完成 | 执行路径、成功/失败标记 | 批量写入 + 元数据标注 |
| 工具调用后 | 工具返回结果摘要 | LLM 摘要后再写入,避免冗余 |
| LLM 空闲期 | 短期记忆→长期记忆巩固 | 后台进程扫描 STM 做摘录 |
核心原则:写入异步化,不阻塞推理路径。高频写入采用批量 buffer,每 100 条或每 30 秒 flush 一次。
写入内容的质量控制
并非所有信息都值得写入长期记忆。写入前需经过"感知→判断→提炼"三步过滤:感知层识别潜在有价值信息(工具返回结果、用户明确表达偏好、决策变更),判断层用轻量级分类器(或 LLM 单次调用)过滤掉寒暄、重复和噪声内容,提炼层对原始文本做摘要压缩后入库。一套经过调优的过滤链路通常可以削减 50%-70% 的无效写入。
检索策略组合
#mermaid-svg-nMYHt4LT9djmCe4r{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nMYHt4LT9djmCe4r .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nMYHt4LT9djmCe4r .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nMYHt4LT9djmCe4r .error-icon{fill:#552222;}#mermaid-svg-nMYHt4LT9djmCe4r .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nMYHt4LT9djmCe4r .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nMYHt4LT9djmCe4r .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nMYHt4LT9djmCe4r .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nMYHt4LT9djmCe4r .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nMYHt4LT9djmCe4r .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nMYHt4LT9djmCe4r .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nMYHt4LT9djmCe4r .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nMYHt4LT9djmCe4r .marker.cross{stroke:#333333;}#mermaid-svg-nMYHt4LT9djmCe4r svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nMYHt4LT9djmCe4r p{margin:0;}#mermaid-svg-nMYHt4LT9djmCe4r .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-nMYHt4LT9djmCe4r .cluster-label text{fill:#333;}#mermaid-svg-nMYHt4LT9djmCe4r .cluster-label span{color:#333;}#mermaid-svg-nMYHt4LT9djmCe4r .cluster-label span p{background-color:transparent;}#mermaid-svg-nMYHt4LT9djmCe4r .label text,#mermaid-svg-nMYHt4LT9djmCe4r span{fill:#333;color:#333;}#mermaid-svg-nMYHt4LT9djmCe4r .node rect,#mermaid-svg-nMYHt4LT9djmCe4r .node circle,#mermaid-svg-nMYHt4LT9djmCe4r .node ellipse,#mermaid-svg-nMYHt4LT9djmCe4r .node polygon,#mermaid-svg-nMYHt4LT9djmCe4r .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nMYHt4LT9djmCe4r .rough-node .label text,#mermaid-svg-nMYHt4LT9djmCe4r .node .label text,#mermaid-svg-nMYHt4LT9djmCe4r .image-shape .label,#mermaid-svg-nMYHt4LT9djmCe4r .icon-shape .label{text-anchor:middle;}#mermaid-svg-nMYHt4LT9djmCe4r .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nMYHt4LT9djmCe4r .rough-node .label,#mermaid-svg-nMYHt4LT9djmCe4r .node .label,#mermaid-svg-nMYHt4LT9djmCe4r .image-shape .label,#mermaid-svg-nMYHt4LT9djmCe4r .icon-shape .label{text-align:center;}#mermaid-svg-nMYHt4LT9djmCe4r .node.clickable{cursor:pointer;}#mermaid-svg-nMYHt4LT9djmCe4r .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nMYHt4LT9djmCe4r .arrowheadPath{fill:#333333;}#mermaid-svg-nMYHt4LT9djmCe4r .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nMYHt4LT9djmCe4r .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nMYHt4LT9djmCe4r .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nMYHt4LT9djmCe4r .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nMYHt4LT9djmCe4r .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nMYHt4LT9djmCe4r .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nMYHt4LT9djmCe4r .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nMYHt4LT9djmCe4r .cluster text{fill:#333;}#mermaid-svg-nMYHt4LT9djmCe4r .cluster span{color:#333;}#mermaid-svg-nMYHt4LT9djmCe4r div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nMYHt4LT9djmCe4r .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nMYHt4LT9djmCe4r rect.text{fill:none;stroke-width:0;}#mermaid-svg-nMYHt4LT9djmCe4r .icon-shape,#mermaid-svg-nMYHt4LT9djmCe4r .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nMYHt4LT9djmCe4r .icon-shape p,#mermaid-svg-nMYHt4LT9djmCe4r .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nMYHt4LT9djmCe4r .icon-shape .label rect,#mermaid-svg-nMYHt4LT9djmCe4r .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nMYHt4LT9djmCe4r .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nMYHt4LT9djmCe4r .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nMYHt4LT9djmCe4r :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
事实查询('价格?')
偏好查询('喜欢什么?')
历史查询('上次怎么做的?')
关系查询('和什么有关?')
用户查询
查询类型
混合搜索 BM25 + 向量
重要性排序 Top-K
时间衰减 + 时间范围过滤
知识图谱遍历
Rerank 精排
Top-5 注入上下文
生产环境起点是混合搜索(BM25 + 向量)+ Rerank。这以大约 20% 的额外复杂度换取了关键词精确匹配的显著增益。只有在处理高度关联的知识库且需要多跳推理时,才引入 GraphRAG。
检索策略对比总结
| 纯向量余弦相似度 | 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 收到的输入信息面更广。
记忆过期清理
三种遗忘策略组合使用:
#mermaid-svg-EGDzG2FD8ISPvn7I{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-EGDzG2FD8ISPvn7I .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EGDzG2FD8ISPvn7I .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EGDzG2FD8ISPvn7I .error-icon{fill:#552222;}#mermaid-svg-EGDzG2FD8ISPvn7I .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EGDzG2FD8ISPvn7I .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EGDzG2FD8ISPvn7I .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EGDzG2FD8ISPvn7I .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EGDzG2FD8ISPvn7I .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EGDzG2FD8ISPvn7I .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EGDzG2FD8ISPvn7I .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EGDzG2FD8ISPvn7I .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EGDzG2FD8ISPvn7I .marker.cross{stroke:#333333;}#mermaid-svg-EGDzG2FD8ISPvn7I svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EGDzG2FD8ISPvn7I p{margin:0;}#mermaid-svg-EGDzG2FD8ISPvn7I .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-EGDzG2FD8ISPvn7I .cluster-label text{fill:#333;}#mermaid-svg-EGDzG2FD8ISPvn7I .cluster-label span{color:#333;}#mermaid-svg-EGDzG2FD8ISPvn7I .cluster-label span p{background-color:transparent;}#mermaid-svg-EGDzG2FD8ISPvn7I .label text,#mermaid-svg-EGDzG2FD8ISPvn7I span{fill:#333;color:#333;}#mermaid-svg-EGDzG2FD8ISPvn7I .node rect,#mermaid-svg-EGDzG2FD8ISPvn7I .node circle,#mermaid-svg-EGDzG2FD8ISPvn7I .node ellipse,#mermaid-svg-EGDzG2FD8ISPvn7I .node polygon,#mermaid-svg-EGDzG2FD8ISPvn7I .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-EGDzG2FD8ISPvn7I .rough-node .label text,#mermaid-svg-EGDzG2FD8ISPvn7I .node .label text,#mermaid-svg-EGDzG2FD8ISPvn7I .image-shape .label,#mermaid-svg-EGDzG2FD8ISPvn7I .icon-shape .label{text-anchor:middle;}#mermaid-svg-EGDzG2FD8ISPvn7I .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-EGDzG2FD8ISPvn7I .rough-node .label,#mermaid-svg-EGDzG2FD8ISPvn7I .node .label,#mermaid-svg-EGDzG2FD8ISPvn7I .image-shape .label,#mermaid-svg-EGDzG2FD8ISPvn7I .icon-shape .label{text-align:center;}#mermaid-svg-EGDzG2FD8ISPvn7I .node.clickable{cursor:pointer;}#mermaid-svg-EGDzG2FD8ISPvn7I .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-EGDzG2FD8ISPvn7I .arrowheadPath{fill:#333333;}#mermaid-svg-EGDzG2FD8ISPvn7I .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-EGDzG2FD8ISPvn7I .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-EGDzG2FD8ISPvn7I .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EGDzG2FD8ISPvn7I .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-EGDzG2FD8ISPvn7I .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EGDzG2FD8ISPvn7I .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-EGDzG2FD8ISPvn7I .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-EGDzG2FD8ISPvn7I .cluster text{fill:#333;}#mermaid-svg-EGDzG2FD8ISPvn7I .cluster span{color:#333;}#mermaid-svg-EGDzG2FD8ISPvn7I div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-EGDzG2FD8ISPvn7I .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-EGDzG2FD8ISPvn7I rect.text{fill:none;stroke-width:0;}#mermaid-svg-EGDzG2FD8ISPvn7I .icon-shape,#mermaid-svg-EGDzG2FD8ISPvn7I .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EGDzG2FD8ISPvn7I .icon-shape p,#mermaid-svg-EGDzG2FD8ISPvn7I .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-EGDzG2FD8ISPvn7I .icon-shape .label rect,#mermaid-svg-EGDzG2FD8ISPvn7I .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EGDzG2FD8ISPvn7I .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-EGDzG2FD8ISPvn7I .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-EGDzG2FD8ISPvn7I :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
是
否
是
否
记忆池
年龄 > TTL?
归档到冷存储
重要性 < 阈值?
删除
相似度 > 0.85?
合并到已有记忆
保留
- 时间衰减:指数函数 importance_now = original * e^(-λ * days)。λ 按记忆类型配置:用户偏好 λ=0.01(衰减慢),对话印象 λ=0.1(衰减快)。
- 重要性评分:写入时 LLM 打分(1-10 分制,低价值如"用户打了个招呼"2 分,优先淘汰)。
- 相似度合并:新记忆与已有记忆余弦相似度 >0.85 时触发 LLM 驱动的增量合并,避免同一事实的冗余副本。
不同遗忘策略的存储影响数据
| 无遗忘 | 100%(基准) | 500ms-2s | 呈下降趋势 |
| 仅 TTL 过期 | 40-60% | 120-300ms | 可能误删有用信息 |
| TTL + 重要性评分 | 25-40% | 80-150ms | 高价值信息保留 |
| TTL + 重要性 + 合并去重 | 15-30% | 60-100ms | 无冗余,精炼 |
从第一天就设计遗忘机制,不要等到存储爆炸再补。没有遗忘的记忆系统最终会淹没在信息噪声中,检索质量随记忆量增长逆向下降。

![[特殊字符]DeepSeek‑Harness(DSH)小白保姆教程-171主机测评](https://www.171host.com/wp-content/uploads/2026/08/20260816085112-6a817a009aabf-220x150.png)
