中 困难
长期记忆治理与多租户隔离#
一句话答案#
长期记忆治理核心是「写入评判→噪声控制→合规删除」三道关:写入时评判记忆价值(是否值得记住)、存储后定期清洗噪声(过时/矛盾/低质)、删除时确保彻底(向量+缓存+索引全清);多租户场景下记忆必须按 tenant_id 严格隔离,防止跨租户记忆污染。
核心要点
一、三层记忆模型回顾
| 层次 | 生命周期 | 存储 | 治理重点 |
|---|---|---|---|
| 工作记忆 | 单次对话 | 上下文窗口 | Token 预算管理 |
| 短期记忆 | 多轮会话 | Redis/DB | 会话超时清理 |
| 长期记忆 | 跨会话持久 | 向量库+DB | 写入/清洗/删除治理 |
二、记忆写入评判
什么值得记住:
| 类别 | 示例 | 优先级 |
|---|---|---|
| 用户偏好 | ”我喜欢简洁的回答”/“用中文回答” | 高 |
| 事实知识 | ”我们的API版本是v3”/“数据库用的PostgreSQL” | 高 |
| 历史决策 | ”上次选了方案A因为成本低” | 中 |
| 对话摘要 | ”讨论了部署架构,决定用K8s” | 中 |
| 临时信息 | ”今天天气不错” / 寒暄 | 不记 |
写入评判机制:
对话结束/关键节点
→ 记忆提取器(LLM/规则)识别候选记忆
→ 评判维度:
1. 持久价值:未来对话是否可能用到?
2. 具体性:是否有明确的事实/偏好?("不错"不值得记)
3. 唯一性:是否与已有记忆重复?
4. 可靠性:是否来自可信源?(用户自述 vs Agent推测)
→ 通过评判 → 写入长期记忆
→ 未通过 → 丢弃plaintext三、噪声控制与清洗
噪声类型:
| 类型 | 示例 | 检测方法 |
|---|---|---|
| 过时记忆 | ”我们用Java 8”(已升级到17) | 定期确认 / 时效标签 |
| 矛盾记忆 | 记忆A说”用MySQL”,记忆B说”用PostgreSQL” | 写入时冲突检测 |
| 低质记忆 | 模糊/泛化的记忆,无实际参考价值 | 使用频率统计 |
| 错误记忆 | Agent 错误推断写入的记忆 | 来源标记 + 置信度 |
| 隐私敏感 | 无意中记录了密码/token | PII 检测 |
清洗策略:
定期清洗任务(每天/每周)
│
├─ 过时检测:
│ ├─ 超过TTL的记忆 → 标记待确认 → 下次对话时向用户确认
│ └─ 被新记忆覆盖的旧记忆 → 自动归档/删除
│
├─ 冲突检测:
│ ├─ 新写入与已有记忆语义矛盾 → 保留最新 + 通知用户
│ └─ 同一主题多条记忆 → 合并去重
│
├─ 质量评估:
│ ├─ 最近N次对话未被检索命中 → 降低权重/归档
│ └─ 置信度低的记忆 → 标记为"待确认"
│
└─ 合规扫描:
└─ PII 检测 → 发现敏感信息 → 脱敏或删除plaintext四、合规删除(“被遗忘权”)
删除范围:
用户请求删除记忆/注销账号
→ 必须删除的:
├─ 向量库中该用户的所有 embedding
├─ 关系数据库中的记忆记录
├─ Redis 缓存中的记忆条目
├─ 搜索索引中的记忆文档
└─ 对象存储中的记忆附件
→ 保留的(审计需要):
├─ 脱敏后的操作审计日志
└─ 聚合统计数据(不含个人信息)plaintext删除确认清单:
-- 1. 向量库删除
DELETE FROM memory_vectors WHERE user_id = ? AND tenant_id = ?;
-- 2. 关系库删除
DELETE FROM user_memories WHERE user_id = ? AND tenant_id = ?;
-- 3. Redis 缓存清除
DEL memory:tenant:{tid}:user:{uid}:*
-- 4. 验证删除完成
SELECT COUNT(*) FROM memory_vectors WHERE user_id = ?; -- 应为0
-- 5. 记录删除审计日志
INSERT INTO deletion_audit (user_id, tenant_id, deleted_at, items_count);sql五、多租户记忆隔离
| 隔离层 | 实现 | 风险 |
|---|---|---|
| 存储隔离 | 向量库 per-tenant collection / 共享+tenant_id过滤 | 查询忘加filter=泄露 |
| 检索隔离 | 记忆检索时 WHERE tenant_id=X 强制注入 | ORM拦截器/中间件保证 |
| 上下文隔离 | 记忆加载到context时只加载本租户 | system prompt不能包含其他租户记忆 |
| 缓存隔离 | Redis key 带 tenant 前缀 | 缓存穿透可能跨租户 |
防止跨租户记忆污染的技术手段:
- 数据库层:Row-Level Security 策略 + 应用层拦截器双保险
- 向量检索层:metadata filter 强制包含 tenant_id
- 缓存层:key 格式
memory:{tenant_id}:{user_id}:{memory_id} - 测试层:跨租户访问测试用例(租户A不能检索到租户B的记忆)
六、记忆容量治理
| 维度 | 策略 |
|---|---|
| 每用户记忆上限 | 如 1000 条,超出时淘汰最旧/最少使用 |
| 记忆大小限制 | 单条记忆不超过 500 tokens |
| 总租户记忆上限 | 按付费等级分配(免费100条/用户,企业10000条) |
| 清理策略 | LRU + TTL + 手动管理 |
面试回答(2分钟版)
长期记忆治理我分三道关。第一道是写入评判:不是所有对话内容都值得记住,记忆提取器从对话中识别候选记忆,按持久价值、具体性、唯一性和可靠性四个维度评判,寒暄和临时信息不记,用户偏好和事实知识优先记。第二道是噪声控制:定期清洗过时记忆比如技术栈升级了旧记忆还在、检测矛盾记忆两条说法冲突时保留最新、统计使用频率淘汰从未命中的低质记忆。第三道是合规删除:用户注销时必须彻底删除向量库、数据库、缓存、索引中的所有记忆,不能遗漏任何存储。多租户场景下记忆隔离是安全底线:向量检索必须 filter tenant_id、缓存 key 带租户前缀、数据库层 Row-Level Security 加应用层拦截器双保险。容量治理按用户和租户设上限,超出用 LRU 淘汰。这套治理的核心目标是保证记忆「有用、准确、安全、可删」。
追问与易错
追问方向:
- “记忆冲突怎么解决?”→ 时间戳优先保留最新版本 + 检测到矛盾时通知用户确认(如”您之前说喜欢 Java,现在说喜欢 Go,以哪个为准?”)+ 同主题记忆自动合并去重
- “记忆对生成质量有多大影响?”→ 正确的记忆提升个性化体验(记住用户偏好/背景),但错误记忆会导致持续幻觉——成为”幻觉放大器”,每次对话都基于错误前提生成错误内容
- “怎么让用户管理自己的记忆?”→ 提供记忆列表页面,支持查看所有已记录的记忆条目、手动编辑修正错误记忆、删除不想保留的记忆、确认待确认的记忆;类似 ChatGPT 的 Memory 管理界面
- “记忆检索和 RAG 检索什么关系?”→ 记忆是关于”用户”的个性化知识(偏好/背景/历史),RAG 是关于”领域”的通用知识(文档/FAQ);检索机制(向量相似度+关键词)可复用,但内容源和更新策略不同
易错点:
- ❌ “记住越多越好”——噪声记忆会导致持续幻觉,比忘记更危险
- ❌ “删除数据库记录就够了”——向量库/缓存/索引都要删,一个都不能漏
- ❌ “共享表加 tenant_id 就能隔离”——必须有强制拦截器,不能依赖业务代码不忘记加 filter
- ✅ 记忆治理核心:宁可少记不要错记,错误记忆是持久化的幻觉