# JKRiver Sleep Pipeline 只读参考 日期: 2026-09-02 状态: **架构级参考文档**。JKRiver(Riverse)源码位于 `~/Project/jkriver`,**AGPL-3.0 / 商业双授权**,禁止将其实现移植进 Memind 商业 SaaS。本文只记录可安全采用的**设计决策**与**反面教训**,供 `memory-v2-lifecycle.mjs` 未来填槽时对照。 ## 0. 授权边界(必读) JKRiver `LICENSE` 为 **Dual License**: - 开源:AGPL-3.0(网络服务需开源修改版) - 商业:需联系 mailwangjk@gmail.com Memind 103 生产为商业 SaaS → **不得复制** `agent/sleep/*.py` 或 `agent/storage/*.py` 的实现。允许: - 读源码理解事务边界、幂等策略、数据模型取舍 - 在 Memind 内**独立设计**语义等价的 JS 逻辑 - 引用公开概念(Sleep Consolidation、supersede、evidence linking) 禁止: - 逐行翻译 Python → JavaScript - 嵌入 JKRiver 代码片段 - 在未取得商业授权前声称「基于 JKRiver 移植」 Mi-Memory(MIT)无此限制;JKRiver 有。 ## 1. 忽略清单(与 Memind 重叠) JKRiver 下列模块**不建议**研究或集成——Memind 已有等价或更完整实现: | JKRiver 模块 | 原因 | |---|---| | Agent / Web Chat / Telegram | 重叠 `wechat-mp`, Portal chat | | Skills / Task Agent | 重叠 `skills-registry`, `chat-skills` | | MCP 集成 | 重叠 Goose MCP extension | | Proactive messaging | 重叠 `schedule-reminder-worker`, `notification-dispatcher` | | Finance / Health 领域 storage | 领域耦合,与 `h5_user_memory_items` 模型不兼容 | ## 2. 值得读的核心:`agent/sleep/`(2324 行) ### 2.1 14 步流水线(`orchestration.py`) ``` load_initial → extract_sessions → analyze_behavior → classify_and_integrate → cross_verify → resolve_disputes → extract_edges → expire_facts → maturity_decay → user_model → trajectory → consolidate → snapshot → finalize ``` 与 Memind 此前画的 Sleep 图相比,JKRiver **多五步**: | 步骤 | 作用 | Memind 对应空槽 | |---|---|---| | `cross_verify` | 交叉验证新 fact | 无 | | `resolve_disputes` | 争议 fact 仲裁(`disputes.py` 231 行) | 无 | | `user_model` | 用户模型更新 | `user-memory-profile` 部分覆盖 | | `trajectory` | 长期轨迹 / key_anchors | 无 | | `consolidate` + `snapshot` | 预编译快照 | `memory-v2-lifecycle.compact()` 占位 | Memind V1 只需关注后四个 maintenance 步映射到 lifecycle: | JKRiver 步骤 | `memory-v2-lifecycle.mjs` | 现状 | |---|---|---| | `expire_facts` | `expire()` | flag 关,逻辑有 | | `maturity_decay` | decay(无独立函数) | **未实现** | | `promote`(classify 隐含) | `promote()` | candidate→item INSERT IGNORE | | `consolidate` | `compact()` | `mode: 'candidate-only'` | | `reflect`(trajectory 隐含) | `reflect()` | `mode: 'observation-only'` | ### 2.2 事务与幂等(**可安全采用的设计**) `orchestration.py` 核心模式: ```python with transaction(): _run_sleep_pipeline_inner(...) # finalize 步才 mark_processed() # 崩溃 → 整批回滚 → 下次重跑(at-least-once) # embedding / clustering 在事务外,失败只 warning ``` Memind 现状:`expire` / `compact` / `promote` / `reflect` **各自独立调用**,无共同事务边界,无 processed 水位。 **可独立采用的设计决策**(不是代码): 1. Consolidation 批次必须在单 DB 事务内 2. `mark_processed` / 水位标记必须在流水线**最后一步** 3. 非关键后处理(embedding、聚类)放在事务外 4. `LLMPipelineError` 单独处理:LLM 不可用则 abort 整批,不部分提交 ### 2.3 Maturity Decay 语义(`_maturity.py`,17 行) ```python _MATURITY_TIERS = [(730, 10, 730), (365, 6, 365), (90, 3, 180)] # if new_decay > current_decay: update (只增不减) ``` 这是 **保留期延长**,不是置信度衰减: - 跨度 ≥730 天且 evidence ≥10 → `decay_days` 延到 730 - 命中 `key_anchors` 时门槛 ×0.6 与 Memind `experience-service.mjs` 的 **30 天半衰期指数衰减**相反。若 Personal Memory 填 decay 槽,必须先做语义选择,不能混用。 ### 2.4 Fact 模型(与 Memind 差距) JKRiver fact:`category`, `subject`, `value`, `start_time`, `supersedes`, `superseded_by`, `decay_days`, `evidence[]` Memind `h5_user_memory_items`:`label`, `memory_text`, `confidence`, `status`, `evidence_message_id` 这是**换模型**,不是加字段。JKRiver consolidation 算法 tied to 前者,不能直映射。 ## 3. 反面教训:`008_drop_hypotheses.sql` ```sql -- hypotheses 表一直是 0 行,无生产读写 -- 被 user_profile (layer 'suspected'/'confirmed' + supersedes) 完全取代 DROP TABLE IF EXISTS hypotheses CASCADE; ``` 对 Memind 的含义: 1. **不要把 `hypothesis` 做成独立表或必填字段**(Experience schema 已采纳:`hypothesis` 可空) 2. 未验证的推断应表达为 `layer=suspected` + `supersedes` 链,而不是平行 hypotheses 存储 3. 建表前先证明有读写路径,否则 0 行表最终被删 ## 4. Memind 填槽优先级(JKRiver 启发,自行实现) 在 `memory-v2-lifecycle` flag 打开 + MemFuseBench 基线稳定后: | 优先级 | 函数 | JKRiver 启发 | 自行实现要点 | |---|---|---|---| | P0 | 事务边界 + 水位 | `orchestration.transaction()` | MySQL 事务包裹 promote+expire | | P1 | `promote()` supersede | `classify_and_integrate` | candidate 冲突时 supersede 而非 INSERT IGNORE | | P2 | `expire()` + verify | `expire_facts` + verify strategy | 过期写 verify 候选,不静默删 | | P3 | decay 延长 | `maturity_decay` | 按 evidence 计数延长 retention,非指数衰减 | | P4 | `compact()` | `consolidate` + `snapshot` | 保守:只报告 eligible,不覆盖源 | | P5 | `reflect()` | `trajectory` + disputes | 需 Experience 结构化数据先就绪 | ## 5. 何时启动 JKRiver 填槽 三门(与 `memfuse-bench-baseline.md` 一致): 1. `h5_memory_v2_candidates` 有真实流量 2. lifecycle `rolloutMode` 至少 `canary` 3. MemFuseBench / recall benchmark 有**可对比的**前后基线 当前(2026-09-02):仅第 3 项部分满足(MemFuseBench 已可跑)。lifecycle 仍 `off` → **不启动填槽实现**。 ## 6. 本地材料 ```bash # 已 clone,不在 Memind 仓库内 ~/Project/jkriver ~/Project/mi-memory # MIT,含 MemFuseBench 数据集 ``` 关键路径: - `agent/sleep/orchestration.py` — 流水线入口 - `agent/sleep/steps_maintain.py` — expire / maturity - `agent/sleep/disputes.py` — 争议解决 - `migrations/008_drop_hypotheses.sql` — 反面教训