记忆与 Sleep
记忆引擎
Riverse 不是 RAG 系统。它不存储原始对话片段再做相似度检索,而是在每次对话结束后运行结构化提取流水线(Sleep),构建一个持续自我修正的个人画像。
提取了什么
每次对话被处理成三种独立的数据结构,各有自己的生命周期:
| 类型 | 捕获内容 | 生命周期 |
|---|---|---|
| 画像事实 | 持久属性:工作、城市、偏好、健康规律等 | 置信度驱动,时间衰减,更新时被取代 |
| 人际关系 | 提到的人:姓名、关系、细节、提及次数 | 每次提及时更新,追踪状态变化 |
| 事件 | 有时效的事件:换工作、搬家、手术等 | 通过 decay_days 自动过期 |
事实的生命周期
每条画像事实经历明确的生命周期:
- suspected — 已提取但尚未跨多次会话验证
- confirmed — 在 2 次以上会话中一致出现,LLM 已交叉验证
- established — 长期存在、证据充分,不会被单次对话轻易推翻
- rejected — 标记为错误(手动或 LLM 仲裁)
- closed — 事实已变化,旧记录保留
end_time,新事实接替
时间衰减
每条事实携带 decay_days 值——该类信息的预估有效期。接近过期的事实在上下文注入时权重降低,过期后从活跃画像中移除,但在时间线中永久保留。
矛盾仲裁
当 Sleep 检测到冲突事实(如"住在东京"vs"搬去大阪")时:
- 将两条事实标记为争议对
- 携带完整上下文(轨迹、时间线、近期对话)进行 LLM 仲裁
- 接受新事实并关闭旧事实,或否定新陈述
证据链
每条事实存储产生它的证据——来自特定对话的观察列表。这意味着:
- 任何事实都可以追溯到创建它的对话
- 矛盾仲裁时 LLM 拥有完整上下文
- 置信度反映支持该事实的观察数量和质量
知识图谱
Sleep 提取事实之间的有类型边,构建个人知识图谱:
causes— "压力"导致"睡眠问题"related_to— "换工作"关联"搬迁"supports/contradicts— 事实之间的证据关系
在上下文注入时,知识图谱用于当相关话题出现时,主动关联因果相关的事实。
Sleep — 离线记忆整合
Sleep 是 Riverse 消化对话、更新画像的过程。支持自动触发和手动触发:
| 触发方式 | 说明 |
|---|---|
| Telegram | 发送 /new — 重置会话并在后台运行 Sleep |
| CLI | 退出时自动执行(quit 或 Ctrl+C) |
| REST API | POST /sleep |
| 定时任务(推荐) | 用 cron 设定每晚定时跑,整合一天的对话 |
cron 示例
每天凌晨 0 点运行 Sleep:
# crontab -e
0 0 * * * cd /path/to/JKRiver && /path/to/python -c "from agent.sleep import run; run()"
14 步流水线
整条流水线在单个数据库事务中原子执行。任何步骤失败,全部回滚——相同的对话会在下次运行时重新处理(至少一次语义)。
阶段一:提取
步骤 1 — 加载初始数据 加载现有用户画像(排除已被取代的事实)和最新的人生轨迹摘要,为后续所有步骤提供上下文。
步骤 2 — 提取会话 对每段未处理的对话,LLM 提取:
- 观察 — 事实陈述、矛盾、偏好和行为信号。每条观察标记类型和主题。关于第三方(用户提到的人)的观察单独存储。
- 标签 — 会话级别的主题标签
- 人际关系 — 提到的人、与用户的关系、细节。已有的关系会合并(提及次数递增,细节更新)。
- 事件 — 有时效的事件(换工作、搬家、手术等),含重要度和衰减天数
仅包含工具/外包意图的会话会被跳过——不含个人信息。
阶段二:分析
步骤 3 — 行为分析
LLM 结合所有观察、当前画像和轨迹推断行为模式。例如,多次深夜发消息可能意味着用户是夜猫子。推断出的事实以 source_type=inferred 存储。当证据数达到 3 条以上时,生成 clarify 策略,在未来对话中主动求证。
步骤 4 — 分类与整合 核心步骤。LLM 将每条观察与现有画像进行比对分类:
support— 支持已有事实 → 追加证据,提及次数递增contradict— 与已有事实矛盾 → 创建新事实并标记supersedes链接,形成争议对evidence_against— 削弱已有事实但不主张替代值new— 无匹配事实 → 创建新的画像事实
未被分类的 statement/contradiction 类型观察自动补为 new。整合完成后,为新创建或矛盾的事实生成变更策略(probe 类型)。
步骤 5 — 交叉验证 对猜测事实进行验证:
- 规则快速通道:
source_type=stated且mention_count ≥ 2的事实自动确认 - LLM 验证:其余猜测事实(按提及次数降序,最多 80 条)结合时间线历史、相关对话摘要(近 3 个月)和轨迹上下文进行交叉验证
通过验证的事实从 suspected 升级为 confirmed。
步骤 6 — 矛盾仲裁
争议事实对(新事实 supersedes 旧事实但两者均未关闭)连同完整上下文送给 LLM 仲裁。LLM 裁决 accept_new(接受新事实)或 reject_new(驳回新事实)。败诉方被关闭(设置 end_time),其知识图谱边被清理。
阶段三:维护
步骤 7 — 提取边 对本轮所有受影响的事实,LLM 提取有类型的边(因果、时序、层级),构建个人知识图谱。
步骤 8 — 过期处理
超过 expires_at 的事实被关闭。对每条过期事实生成 verify 策略,使 AI 在下次相关对话中自然地询问确认。
步骤 9 — 成熟度衰减 长期存在且证据充分的事实获得更长的生命周期。衰减梯度:
| 事实年龄 | 证据数 | 新 decay_days |
|---|---|---|
| ≥ 730 天 | ≥ 10 | 730(2 年) |
| ≥ 365 天 | ≥ 6 | 365(1 年) |
| ≥ 90 天 | ≥ 3 | 180(半年) |
被轨迹识别为关键锚点的事实(如母语、长期职业)门槛降低 40%——它们成熟得更快。
阶段四:输出
步骤 10 — 用户模型
LLM 从对话中分析沟通风格维度(如直接 vs 委婉、正式 vs 随意、幽默风格)。结果存入 user_model 表,用于调整回复语气。
步骤 11 — 轨迹 当检测到重大变化(事实确认、争议解决、重要类别的矛盾)且距上次更新至少 2 个 session 时,重新生成人生轨迹。轨迹包含:人生阶段、方向、稳定性、关键锚点、不稳定领域和近期势头。
步骤 12 — 整合去重 清理提取和整合过程中产生的重复条目。
步骤 13 — 快照 预编译完整的记忆快照:画像事实 + 用户模型 + 活跃事件 + 人际关系 + 知识图谱边。下次对话直接使用快照,省去从多个表重新拼装上下文的开销。
步骤 14 — 完成 标记所有已处理的对话。这是最后一步——如果流水线在此之前崩溃,事务回滚,相同的对话会被重新处理。
事务后处理
原子事务完成后,两个非关键任务在事务之外运行:
- 向量嵌入 — 对所有记忆做 embedding,支持语义搜索
- 记忆聚类 — KMeans 聚类并生成主题标签
知识网络
Sleep 还会构建知识网络 — 用类型化的边连接相关的画像事实(如 causes、related_to、contradicts、supports)。让 AI 看到事实之间的结构关系,而不只是孤立的条目。
当事实被关闭或取代时,相关的边会自动清理。
记忆聚类
开启向量嵌入后,Sleep 还可以对记忆向量做 KMeans 聚类,并为每个簇生成主题标签,提供"鸟瞰"视角了解 AI 对你的认知全貌。
语义搜索
开启向量嵌入(BGE-M3)后,Riverse 可以按语义而非关键词检索相关记忆。
会话记忆(Session Memory)
会话记忆通过三层结构管理单次对话中的上下文:
- 滑动摘要 — 旧对话被 LLM 压缩为滚动摘要,保留历史不超 token 限制
- 向量召回 — 开启向量嵌入后,根据当前消息的语义相似度召回早期相关对话
- 最近轮次 — 最近几轮对话完整保留,提供即时上下文
三层系统让对话可以无限进行而不丢失重要上下文。在 settings.yaml 中配置:
session_memory:
char_budget: 3000 # 会话上下文总字符预算
keep_recent: 5 # 保留完整的最近轮次数
summary_ratio: 0.4 # 摘要占预算的比例
recall_max: 3 # 向量召回最大条数
recall_min_score: 0.45 # 召回最低相似度
pgvector 加速
默认情况下,向量以 JSONB 存储,余弦相似度在 Python 中计算。对于大数据集,安装 pgvector 扩展可显著提升性能:
然后运行迁移脚本:
这会创建原生 vector(1024) 列和 IVFFlat 索引,实现快速近似最近邻搜索。应用会自动检测 pgvector 并在可用时使用,无需修改配置。
记忆准确性
Info
目前没有任何 LLM 是专门为个人画像提取训练的,提取结果可能偶尔出现偏差。你可以在 Web 面板中将错误的记忆标记为错误,或手动关闭过期的记忆 — 但记忆不能被删除或直接修改。这是有意为之:河流算法将记忆视为审计记录,错误的记忆就像河流中的泥沙,应该被水流冲走,而不是人工雕刻河床。
如果错误率较高,根本原因通常是 LLM 的理解能力,而非系统 Bug。建议切换更强的模型 — 记忆提取流程本身也是评估你的 LLM 是否适合此场景的实用基准。随着对话积累,算法会通过多轮验证和矛盾检测持续自我修正,画像会越来越准确。
算法先行的设计理念
Riverse 的记忆流水线在架构设计上超前于当前通用 LLM 的能力。14 步 Sleep 整合流程在每一步都需要精确的结构化判断——观察提取、事实分类、交叉验证、矛盾仲裁——且每一步的输出直接驱动下一步。目前准确率的瓶颈是 LLM 在每个环节的输出精度,而非算法本身。
考虑这个级联效应:如果每步 LLM 准确率为 90%(对某些任务已属乐观),六步串联后端到端准确率约 53%。如果换成专用训练的模型达到每步 99%,同样的流水线准确率可达 94%——同一套代码,质的飞跃。
目前没有任何 LLM 是专门为个人记忆整合训练的。理想路径是训练一个专用的记忆 LLM,针对以下能力进行优化:
- 观察提取精度 — 区分"我住在东京"(陈述)和"我要是住在东京就好了"(假设)
- 多事实联合推理 — 将一条新观察与 30+ 条现有画像事实进行比对判断(本质是一个受约束的自然语言推理任务,fine-tune 空间很大)
- 校准的置信度 — 输出可靠的概率分数,让流水线可以按阈值做决策,而不是简单的二元分类
作者对这个模型应该长什么样有清晰的设计,但训练它需要个人开发者无法获得的算力和数据资源。
如果你的公司正在做记忆相关的模型,或者在做个人 AI 方向,有合适的岗位的话,欢迎联系我:mailwangjk@gmail.com
在此之前,算法运行在通用模型之上,并随着每一代更强模型的出现自动提升,无需改动一行代码。流水线的上下文输入(时间线、轨迹、对话摘要、证据链)已经为未来的模型准备了最丰富的信号。
这是一个有意为之的设计选择:先把架构做对,让模型来追赶算法,而不是为了迁就今天的模型能力而简化架构。