跳转至

用 LanceDB 重构 OpenClaw 记忆系统(讨论结论完整版)

状态:草稿(来自本次群聊讨论的整理稿)

目标

回答问题:

我们应该如何利用 LanceDB 来重构 OpenClaw 的记忆系统?

本文记录本次讨论的最终结论:推荐架构、数据模型、失败模式与防护、迁移计划、验收指标与运维边界。


一句话结论

SQLite 作为事实真源(Source of Truth),承载所有不可变事件与可演进记忆单元;用 LanceDB 作为可重建的检索层(向量 + 可选全文 + 过滤排序),通过 SQLite 的变更流增量 upsert 到 LanceDB;LanceDB 写挂/损坏可随时全量重建,绝不作为真源。


1) 领域抽象(Domain Model)

1.1 MemoryEvent(不可变原子事实)

定义:一条不可变、可审计的原子记录。

示例:

  • 用户消息
  • 助手消息
  • tool 调用与结果
  • 外部文档片段导入

建议字段:

  • event_id(uuid/ulid)
  • ts(int64)
  • actor(user|assistant|system|tool)
  • source(channel/session/project)
  • content(text)
  • content_hash(sha256)
  • tags(list)
  • visibility(tenant/scope)
  • trace_id / request_id

1.2 MemoryUnit(可演进知识块/画像/总结)

定义:由多个 Event 聚合得到的“可演进”单元,可被重写/升级,但需保留可追溯来源。

示例:

  • 用户画像与偏好
  • 周/月总结
  • 决策记录
  • runbook / skill note

建议字段:

  • unit_id(uuid/ulid)
  • type(profile|summary|skill|plan)
  • scope(user|session|global)
  • text(text)
  • facts(json)
  • event_refs(list[event_id])
  • confidence(float)
  • updated_at(int64)

版本策略:

  • 推荐“追加新版本”而非原地覆盖
  • 查询默认返回最新 active;旧版本标记 deprecated

2) 分层架构:SQLite 真源 + LanceDB 检索层

2.1 SQLite(Core / Source of Truth)负责什么

SQLite 负责:

  • 事务一致性
  • 权限与可见性(visibility)
  • 引用关系(event ↔ unit)
  • 当前版本指针(若采用 unit 多版本)
  • 作业队列(embedding 生成、summary 生成、重放/回填)
  • 审计(谁在何时写入/删除/回填)

2.2 LanceDB(Retrieval / 可重建索引层)负责什么

原则:

  • LanceDB 不是 真源
  • LanceDB 是“派生索引”,可以 drop 并从 SQLite 全量重建

建议两张表:

  • events
  • units

events(示意 schema):

  • 主键:event_id
  • ts(int64)、actorsource
  • content(text)
  • tags(list[string])
  • meta(json)
  • embedding(vector)对 content 向量化
  • 可选:fts(对 content 的全文检索字段/索引)

units(示意 schema):

  • 主键:unit_id
  • typescope
  • textfacts(json)
  • event_refs(list[string])
  • embedding(vector)对 text 向量化
  • versionstatus、可选 parent_unit_id
  • 可选:全文检索

3) 主键、去重与一致性

  • event_id 永不变
  • 去重:content_hash + source + ts_window(窗口可配置)
  • 幂等写:LanceDB upsert 必须以 event_id(或 doc_id+version)为幂等键
  • 读一致性:必要时以 SQLite 的“主库版本号/更新时间”做读时校验,发现漂移则回填/重放

4) 失败模式与防护点(红队视角)

1) 删除/破坏

  • 风险:误 drop/compact/vacuum 导致不可逆;挂载点错误清空目录
  • 防护:最小权限账号 + 变更审批;目录/表快照(对象存储版本化);关键操作双人复核;发布前校验挂载点指纹
  • 监控:行数/文件数突降;inode/容量异常;drop/compact 审计事件
  • 回滚:按快照恢复;禁用自动 vacuum

2) 审计缺失

  • 风险:无法追溯写入/删除/重建索引的操作者与时间
  • 防护:所有写接口走服务层;强制记录 request_id、操作者、影响行数;集中日志/不可篡改审计(WORM)

3) 注入/投毒

  • 风险:过滤表达式注入;metadata 超长/NaN/Inf/维度不一致;内容注入影响下游 RAG
  • 防护:过滤字段白名单 + 参数化;入库校验(dim/range/NaN/长度/schema);内容安全与去重;租户隔离

4) 并发/一致性

  • 风险:多写者竞争;部分写成功部分失败;索引与数据不同步;共享文件系统锁失效
  • 防护:单写者/写入队列;批次原子性(stage→切指针);避免不支持的共享 FS;幂等写(request_id 去重)

5) 运维与容量

  • 风险:索引膨胀/碎片化导致 P99 抖动;OOM/磁盘满引发损坏;升级不兼容
  • 防护:水位线与配额;低峰 compact(可回滚);压测基线;升级前全量备份与兼容验证

5) 迁移路线(并行期)

Phase 0 - 准备

  • 统一 doc_id/event_id 规范与版本字段(如 source_updated_at 或单调 version
  • 定义 embedding 标准:embedding_model_iddim、normalize、chunking
  • 写入协议:upsert 幂等、失败可重放、可回填

Phase 1 - 双写(dual write)

  • 主流程写旧系统 + LanceDB
  • LanceDB 写失败不阻断主链路(旁路降级),但必须告警并入重放队列
  • 全量 backfill:扫描历史数据补齐向量表,并记录 checksum/version

Phase 2 - 双读(shadow read)

  • 线上仍以旧系统返回为准
  • LanceDB 后台查询并对比:topK overlap、失败样本回放、人审抽检、代理 NDCG

Phase 3 - 灰度切流

  • 按租户/% 切换读到 LanceDB
  • 保留秒级回退开关

Phase 4 - 收敛/下线

  • 指标稳定达标后下线旧读路径
  • 保留旧索引一段时间作为回滚备份

验收指标(建议)

  • 质量:TopK overlap、关键 query 回归不下降、人审通过率
  • 稳定:写失败率 < 0.1% 且可重放接近 100%;查询错误率 < 0.01%;一致性校验失败可定位
  • 性能/成本:P95 延迟不劣于旧系统 +10%;存储增长可控

6) 三层纳入方式与保留策略

三层纳入方式(从轻到重):

  1. 旁路检索层(最轻):LanceDB 只做候选召回,最终排序仍由旧系统负责
  2. 主检索层(中等):LanceDB 成为主召回来源,旧系统回退
  3. 检索+存储一体(最重):LanceDB 承担更多元数据/版本管理(要求更严格)

剪枝/去重/TTL/归档:

  • 去重:doc_id+version 幂等;chunk 用 content_hash 去重
  • TTL:session 7–30 天;daily 90–180 天;长期摘要季度复审
  • 归档:热/温/冷分层;冷数据只保离线回放能力;保留审计索引以便追溯

关联页面

  • LanceDB 失败模式与迁移页:lancedb-failure-modes-and-migration.md
  • 讨论过程(发布与排障):../chat-logs/2026-02-24-lancedb-discussion.md