# moomem 产品需求文档 PRD v1.1

> v1.1（2026-10-01）：决议开放问题 Q1（允许注入嵌入模型）/ Q2（不做本地小模型兜底），见第 22 章。适用场景：2026 MoonBit 黑客松十月赛（申报 + 开发执行依据）。

## 0. 文档信息

产品名称| moomem —— MoonBit 嵌入式 Agent 记忆层  
---|---  
文档版本| v1.1(2026-10-01:决议开放问题 Q1/Q2,见第 22 章)  
文档状态| 待评审 → 通过后进入开发  
适用场景| 2026 MoonBit 黑客松十月赛(申报 + 开发执行依据)  
上游依据| 《MoonBit 黑客松选题调研报告 v1.0》《生态复核报告 v2.0》及九轮生态查重结论  
  
## 1. 背景与问题

### 1.1 背景

LLM 是无状态函数:每次推理只依赖本轮输入的上下文窗口,进程结束、窗口关闭后一切归零。AI Agent 要成为可长期使用的数字员工,必须跨越"每次都失忆"这道坎。行业已给出验证:mem0、Letta、腾讯 TencentDB-Agent-Memory(1.8 万星)、OceanBase PowerMem(2026 年 9 月发文)均将"记忆层"作为 Agent 基础设施的核心投资方向。

MoonBit 生态侧:经九轮查重确认,mooncakes 上已有向量库(trkbt10/vcdb)、BM25 检索(MoonRetrieve)、LLM 调用(mizchi/llm)、RAG 框架(moon-agent)、多 Agent 编排(官方 workflow),唯独没有任何持久化记忆实现——moon-agent 的 BufferMemory/SummaryMemory 仅存在于进程内,重启即失忆。

### 1.2 问题定义

**核心问题:MoonBit 生态的 AI Agent 无法跨会话、跨进程记住用户事实与偏好,导致每次交互都从零开始。**

问题拆解:

  * P1 记忆不可持久:现有记忆组件存于内存,重启丢失。
  * P2 记忆不可检索:历史对话即便保存,也无法按语义相关性精准召回(上下文窗口装不下全部历史)。
  * P3 记忆不可共享:同一程序内不同用户的事实混在一起,存在隐私与正确性双重风险。
  * P4 记忆不可信:LLM 生成的记忆若不管理冲突(如用户搬家),"新事实覆盖旧事实"无从谈起。

立项判断(Evidence 标注)

生态空位(九轮查重,GitHub + mooncakes 双通道验证)为 **Fact** ;"行业方向被大厂验证"为 **Evidence** ;"一个月可完成 MVP"基于三块底层积木已就绪的现状推断,为 **Inference** ,W1 结束时验证。

## 2. 目标与非目标

### 2.1 产品目标

目标层级| 目标描述| 衡量方式  
---|---|---  
业务目标(赛事)| 通过十月赛验收,争取月度支持与季度评奖入场| 赛事验收六条逐条达标  
生态目标| 成为 mooncakes 上第一个也是事实标准的 Agent 记忆库| 发布 v0.1 抢占时间戳;被至少一个第三方项目引用  
用户目标| MoonBit 开发者用两行代码让 Agent 获得跨会话记忆| 接入耗时 ≤ 15 分钟;API 表面 ≤ 6 个公开方法  
  
### 2.2 非目标(Non-goals)

  * 不做服务端/网络部署形态(PowerMem 已占,且与嵌入式定位冲突)。
  * 不做多模态记忆(图片/音频)。
  * 不做记忆的自动遗忘调度(衰减、TTL),仅提供手动删除 API。
  * 不做基于记忆的推理改写(记忆层只做存取,不改变事实内容)。
  * 不做分布式/多副本一致性,单机单写者为设计边界。

## 3. 用户 / 角色 / 任务 / 场景

### 3.1 角色定义

角色| 描述| 核心诉求| 使用频率  
---|---|---|---  
主用户:MoonBit Agent 开发者| 在 MoonBit 生态内构建 AI 应用/Agent 的开发者,含黑客松参赛者| 最低成本接入持久记忆;行为可预期、可调试| 开发期高频调用  
终用户:Agent 的使用者| 通过宿主应用间接使用记忆能力的非开发者| Agent 记得住我;我的数据不被别人看到| 每次交互间接受益  
评审者:黑客松评委| 按验收六条评估项目| 边界清晰、测试完备、AI 使用可解释| 评审期一次  
  
### 3.2 核心场景(As-Is / To-Be)

**场景 A:个人助理 Agent 记住用户偏好**

  * As-Is:用户第一天告知"我对花生过敏",第二天 Agent 推荐花生酱三明治;用户每天重复自我介绍。
  * To-Be:add() 存入事实;recall() 在每次生成前自动注入,回答自动避开过敏原。

**场景 B:事实变更的覆盖**

  * As-Is:用户说"我搬到深圳了",旧记忆"用户住北京"仍在,Agent 行为摇摆。
  * To-Be:提取阶段识别新旧事实冲突,旧条目进入 superseded 状态,检索不再返回。

**场景 C:多用户隔离**

  * As-Is:多个用户的对话塞进同一个上下文,A 的秘密泄露给 B。
  * To-Be:user_id 作为一等隔离边界,任何检索物理上不可能跨用户返回。

## 4. 范围(Scope)

范围| 内容  
---|---  
In(v1.0)| 嵌入式记忆库核心 API(open/add/recall/forget/stats);LLM 事实提取;冲突覆盖(supersede);向量+BM25 双路混合检索与 RRF 融合;磁盘持久化与崩溃恢复;多用户隔离;CLI 工具;JSONL 导入导出;wasm/js/native 后端验证;LoCoMo 子集评测报告  
Out(v1.0 明确不做)| 服务端形态;自动遗忘调度;多模态;分布式;记忆改写式推理;嵌入模型训练(依赖 vcdb 提供的现成嵌入)  
  
## 5. 产品模型 / 对象关系

### 5.1 核心对象

对象| 类型| 关键字段| 说明  
---|---|---|---  
MemoryStore| 聚合根| path、config、索引句柄| 一个磁盘目录即一套记忆库,持有全部子对象的唯一入口  
Namespace| 实体| user_id| 用户隔离边界,记忆条目必须归属且仅归属一个 Namespace  
MemoryEntry| 实体| id、content、kind、embedding、keywords、status、created_at、superseded_by| 最小记忆单元,一条可复用事实  
RetrievalQuery| 值对象| user_id、text、top_k、filters| 只读,描述一次召回请求  
  
### 5.2 关系与规则

  * MemoryStore 1 — N Namespace;Namespace 1 — N MemoryEntry;MemoryEntry 0..1 — 1 MemoryEntry(superseded_by 指向覆盖者)。
  * 数据归属:所有对象存储于 MemoryStore.path 指向的目录,不触碰目录外任何文件。
  * Ubiquitous Language 约定:add = 写入并提取;recall = 混合检索;forget = 软删除;supersede = 冲突覆盖。

## 6. 信息与功能架构

架构层| 模块| 职责  
---|---|---  
API 层| store.mbt| 公开 6 个方法:open/add/recall/forget/stats/close  
提取层| extractor.mbt| 调用 LLM 将对话片段提炼为结构化事实;冲突检测  
索引层| index_vector.mbt / index_keyword.mbt| 向量写入与近邻检索(委托 vcdb);BM25 写入与检索(委托 MoonRetrieve 组件)  
存储层| persist.mbt| JSONL 追加日志 + 快照;启动时重建索引  
融合层| ranker.mbt| RRF 融合两路召回结果并截断 top_k  
工具层| cli.mbt| 命令行:add/recall/list/stats/export  
  
## 7. 用户流程(开发者接入)

目标流程(To-Be):

  * 步骤 1:mooncakes 安装 moomem 依赖,moon.mod.json 声明。
  * 步骤 2:调用 open 初始化(或创建)记忆库目录。
  * 步骤 3:在对话结束后调用 add 传入原始文本;moomem 内部完成提取、去重、冲突覆盖、双索引、落盘。
  * 步骤 4:在 LLM 调用前调用 recall,取回相关事实,拼接进系统提示词。
  * 步骤 5:程序退出;下次启动 open 同一目录,记忆完整恢复。

## 8. 功能需求(FR 表)

ID| 需求| 触发/前置| 行为要点| 验收要点  
---|---|---|---|---  
FR-01| 打开/初始化记忆库| open(path)| 目录不存在则创建;存在则加载索引与元数据;文件损坏时报错并指引恢复| 空目录可初始化;重启后数据完整  
FR-02| 写入记忆(add)| user_id、文本| LLM 提取事实 → 去重 → 冲突检测 → 双索引写入 → 落盘;全程同步返回提取结果摘要| 闲聊被过滤;重复事实不重复存储  
FR-03| 召回记忆(recall)| user_id、query、top_k| 向量近邻 + BM25 并行检索 → RRF 融合 → 返回排序事实列表;只返回 active 状态| 语义相关事实命中率达标(见 17 章)  
FR-04| 多用户隔离| 任意读写| user_id 强制传入;索引与存储按 user 分片;无"全库检索"接口| 跨用户检索结构上不可能发生  
FR-05| 持久化与恢复| add 后任意时刻| 追加写 JSONL;进程被杀后 open 能恢复到最后一次完整写入| 崩溃注入测试通过  
FR-06| 删除记忆(forget)| entry id 或条件| 软删除:状态置 deleted,索引摘除,文件保留标记| 删除后 recall 不再返回  
FR-07| CLI 工具| 命令行调用| add/recall/list/stats/export 五个子命令,便于调试与演示| 无 API 也能完整走通场景 A  
FR-08| 导入导出| export/import| JSONL 全量导出;支持导入重建| 导出再导入,记忆等价  
FR-09| 多后端验证| 构建矩阵| wasm-gc、js、native 三后端编译通过且行为一致(存储路径按后端适配)| CI 三后端测试绿  
FR-10| 运行统计(stats)| 任意时刻| 返回条目数、各状态计数、存储体积、最近写入时间| 数字与文件系统实况一致  
  
## 9. 业务规则矩阵

条件| 规则| 系统行为| 例外  
---|---|---|---  
提取结果为空(纯闲聊)| 不入库| add 返回"提取 0 条"并原文丢弃| 调用方可选 raw 模式强制入库  
新事实与既有 active 事实语义冲突| 新覆盖旧| 旧条目置 superseded 并记录 superseded_by;新条目入库| 冲突置信度低于阈值时两条并存并标记 conflict  
新事实与既有事实完全重复| 不重复入库| 跳过,返回已存在条目 id| 无  
user_id 含路径穿越字符| 拒绝| 启动时校验,非法字符直接报错| 无  
LLM 提取调用失败| 降级| 原文以 unstructured 类型入库,标记待重提取;不阻塞调用方| 连续失败 3 次返回错误  
检索无结果| 返回空列表| 不做任何"编造记忆"兜底;由上层决定提示语| 无  
  
## 10. 状态机(MemoryEntry 生命周期)

当前状态| 可执行动作| 触发| 下一状态| 可回退  
---|---|---|---|---  
(不存在)| 创建| add 提取成功| active| —  
active| 覆盖| 冲突检测命中且置信度达标| superseded| 是(撤销覆盖,恢复 active)  
active| 删除| forget(id)| deleted| 是(恢复 active)  
superseded| 删除 / 恢复| 显式操作;恢复时若覆盖者仍 active 则需先处理冲突| deleted / active| —  
deleted| 恢复 / 物理清除| 显式操作| active / (移除)| —  
unstructured| 重提取| LLM 恢复可用后批量任务| active 或丢弃| —  
  
不变量:recall 只返回 active;superseded/deleted 条目在物理文件中保留(可审计),在检索中不可见。

## 11. 权限与数据隔离矩阵

主体| 资源| 动作| 数据范围| 说明  
---|---|---|---|---  
宿主程序(开发者)| 整个 MemoryStore| 全读写| 全部 Namespace| 库形态:信任边界在宿主进程,库不做角色鉴权  
某个 user_id 的调用| MemoryEntry| 读| 仅本 user_id| recall/add 均强制隔离,无跨用户 API  
某个 user_id 的调用| MemoryEntry| 写/删| 仅本 user_id| 同上  
LLM 提取服务| 待提取文本| 只读转发| 单次调用载荷| 密钥由宿主注入,库不持久化密钥  
  
边界说明

嵌入式库不提供网络访问控制;若宿主将记忆库目录置于共享存储,隔离责任归宿主。此约束写入 README 的安全章节。

## 12. 交互与 API 设计(AI UX)

### 12.1 公开 API(6 个方法)

调用| 签名语义| 返回  
---|---|---  
open(path, config)| 打开或创建记忆库| MemoryStore 句柄  
add(user_id, text)| 写入:提取+去重+冲突+索引+落盘| 提取摘要(条数、状态变更)  
recall(user_id, query, top_k)| 混合检索融合排序| MemoryEntry 列表(含内容与时间戳)  
forget(user_id, 条件)| 软删除| 受影响条目数  
stats()| 运行统计| 计数与体积结构体  
close()| 安全关闭,刷盘| 无  
  
### 12.2 使用示例(场景 A 完整走通)

步骤| 调用| 效果  
---|---|---  
1| let mem = Memory.open("./memory")| 初始化(首次)或恢复(二次)  
2| mem.add("user-42", "我对花生过敏")| 提取 1 条事实入库  
3| mem.recall("user-42", "推荐午餐", 5)| 返回含"花生过敏"的事实列表  
4| mem.add("user-42", "我最近搬到深圳了")| 旧事实"住北京"自动 superseded  
5| 程序退出,次日重启 open 同一目录| 记忆完整,recall 行为一致  
  
### 12.3 可信交互设计

  * add 返回提取摘要,让开发者看见"AI 理解了什么"——不展示伪置信度数值,以提取原文对照方式呈现。
  * recall 结果带来源时间戳,供上层向用户展示"我记得这个是因为你 3 天前说过"。
  * 所有 AI 参与环节(提取、冲突判定)在 stats/export 中留有标记,满足赛事"AI 可解释"验收。

## 13. AI 行为规范

### 13.1 事实提取(prompt 行为契约)

  * 输入:对话原文 + 系统指令;输出:结构化事实列表(JSON,含 kind:fact/preference/event 与原文依据 span)。
  * 提取纪律:只保留可复用信息;丢弃寒暄、情绪表达、与用户无关的第三方内容;不改写事实本身(忠实原文)。
  * 补问策略:库层不发起交互;提取歧义时按"宁少勿错"丢弃并在摘要中说明。

### 13.2 冲突判定

  * 新事实入库前,先经"同用户同主题检索"召回邻近事实,由 LLM 判定 replace/merge/ignore。
  * 判定为 replace 才触发 supersede;判定结果与依据写入条目元数据。
  * Stop Condition:单次 add 的提取+判定链路最多 2 次 LLM 调用,超限降级为 unstructured 入库。

### 13.3 降级与兜底

  * LLM 不可用:原文 unstructured 入库,检索按关键词路由,不阻塞主流程。
  * 嵌入服务不可用:仅 BM25 单路检索,结果标记 degraded。
  * 任何 AI 环节失败均不影响既有记忆的读取——记忆可用性优先于智能化程度。

## 14. Context 与数据依赖

依赖| 用途| 权威性| 风险与对策  
---|---|---|---  
vcdb| 向量存储与近邻检索;内置 Embedder 缺省实现来源| 生态第三方包| 锁版本;API 变更时以适配层隔离  
Embedder 接口| 嵌入计算(库内一等注入点)| moomem 自有抽象| 缺省委托 vcdb;宿主可注入自定义实现(决议 Q1)  
MoonRetrieve BM25 组件| 关键词检索| 生态第三方包| 同上;必要时内置精简 BM25 实现  
mizchi/llm| LLM 调用(提取/判定)| 生态第三方包| 提取层设计为可替换接口,支持注入 mock 供测试  
宿主提供的 LLM API Key| 提取时使用| 调用方持有| 库不存储密钥;默认关闭 AI 功能的 raw 模式可零密钥运行  
LoCoMo 数据集| 评测基准| 学术公开数据| 选用子集控制工程量  
  
## 15. 异常与边缘场景矩阵

场景| 行为| 用户可见反馈  
---|---|---  
记忆库目录被外部删除| open 重新初始化空库,给出警告| CLI 警告"记忆已清空"  
JSONL 半行损坏(进程被杀)| 启动时截断至最后完整行,丢弃尾部| stats 显示恢复截断计数  
单条事实超长(长于嵌入上限)| 截断入库并标记 truncated| 导出可见标记  
同一 user 大量写入(万级条目)| 检索性能分级测试并给出 top_k 上限建议| README 性能章节  
并发写(同进程异步)| v1.0 单写者模型,文档明示;提供显式 close 刷盘| 错误信息指引  
wasm 后端无本地文件系统| 存储路径映射到持久化 API(浏览器 IndexedDB 适配)| 后端适配表  
LLM 返回非法 JSON| 重试一次;仍失败按降级规则处理| 提取摘要含失败计数  
  
## 16. Eval 与产品指标

### 16.1 AI 能力评测(Offline)

评测项| 方法| Baseline| 目标(v1.0)  
---|---|---|---  
检索质量| LoCoMo 子集:多轮对话建库后问询,统计相关事实召回| 纯 BM25 单路| 混合检索 Recall@5 高于单路 ≥ 15%  
提取质量| 人工标注 100 条对话的"应提取事实"金标准集| 全文存入| 提取 Precision ≥ 0.8(宁少勿错)  
冲突处理| 构造 30 组事实变更用例| 无处理(两条并存)| supersede 正确率 ≥ 80%  
持久化| 崩溃注入 + 重启一致性| —| 100% 通过  
隔离| 跨用户检索渗透测试| —| 0 渗透  
  
### 16.2 产品指标(轻量,契合赛事阶段)

  * Activation:README 快速上手可在 15 分钟内跑通场景 A(以新手实测为准)。
  * Adoption:mooncakes 下载量、第三方仓库引用数。
  * Task Success:LoCoMo 端到端问答准确率对比无记忆基线的提升幅度。
  * Guardrail:内存占用与库体积不超过生态同级包的合理范围。

## 17. 验收标准(节选,Given/When/Then)

  * AC-01 持久化:Given 已 add 并落盘,When 进程终止后重新 open 同一目录,Then recall 返回的结果集与终止前一致。
  * AC-02 隔离:Given user-A 与 user-B 各有事实,When 以 user-A 身份 recall 任意 query,Then 结果中不出现任何 user-B 条目。
  * AC-03 提取:Given 输入 20 句闲聊 + 1 句"我对花生过敏",When add,Then 入库事实仅含过敏信息,闲聊 0 条。
  * AC-04 冲突:Given 已有 active 条目"用户住北京",When add"我搬到深圳了",Then 北京条目状态为 superseded 且 recall 不再返回。
  * AC-05 降级:Given LLM 服务不可用,When add 原文,Then 以 unstructured 入库成功且 recall 正常工作。
  * AC-06 后端:Given 同一测试集,When 分别在 wasm-gc/js/native 运行,Then 行为一致(测试全绿)。
  * AC-07 赛事:Given 评委按验收六条检查,Then 逐条有对应证据(见 20 章映射表)。

## 18. MVP 里程碑(4 周,对齐十月赛)

周次| 交付| 验证的假设  
---|---|---  
W1| 存储层 + 双索引读写闭环(原始文本,无 LLM)+ 持久化与崩溃恢复| 核心链路工程可行(Inference → Fact)  
W2| LLM 提取 + 去重 + 冲突 supersede;提取金标准集 v1| 提取质量达标(AC-03/04)  
W3| 混合检索 + RRF 融合 + 多用户隔离 + CLI + 导入导出| 隔离与可用性(AC-02/05)  
W4| LoCoMo 子集评测报告 + 三后端 CI + 文档 + README| 价值证明(16 章)与赛事验收  
  
关键动作

开赛后第一周发布 v0.1 到 mooncakes 抢占时间戳——空位只是"尚未发布",未发布项目不可见,时间戳即先发证据。

## 19. 风险登记册

ID| 风险| 概率| 影响| 对策  
---|---|---|---|---  
RK-01| 同期有人发布同定位记忆库| 中| 高| W1 即发 v0.1;差异化钉死"嵌入式零部署 + wasm 全后端"  
RK-02| 提取质量不达标(噪声/漏提)| 中| 中| 宁少勿错策略;raw 模式兜底;金标准集量化迭代  
RK-03| vcdb/MoonRetrieve API 破坏性变更| 中| 中| 锁版本 + 适配层隔离;必要时内置精简 BM25  
RK-04| LoCoMo 评测工程量超预期| 中| 低| 降级为"自建 200 条多轮对话评测集"并如实说明  
RK-05| 单人精力不足| 低| 中| 非目标已裁剪;W1 为纯工程无 LLM 依赖,可先行  
  
## 20. 赛事验收映射(六条)

验收条| moomem 对应证据  
---|---  
MoonBit 为主要实现语言| 全库纯 MoonBit,零 FFI  
公开仓库 + 连续提交| W1 起每日提交,v0.1 月内发布  
能运行(README+示例+测试)| 15 分钟上手文档 + 场景 A 示例 + moon test 全绿  
实质新增| 生态内无前例(九轮查重记录在案)  
开源合规| Apache-2.0;依赖均为生态内合规包  
AI 可解释| 提取摘要、冲突判定依据、degraded 标记全链路可见(12.3/13 章)  
  
## 21. 开放问题(Open Questions)

  * Q1:**已决议(见第 22 章)** ——嵌入模型采用"宿主可注入"设计。
  * Q2:**已决议(见第 22 章)** ——不做本地小模型兜底。
  * Q3:moon-agent 是否主动提 PR 集成?——保持开放,赛后评估。

## 22. v1.1 决议记录(2026-10-01)

Q1 决议:嵌入模型允许宿主注入

原开放问题:嵌入模型走 vcdb 内置还是允许宿主注入?**决议:采用"宿主可注入"设计。** Embedder 定义为库内一等注入接口(trait 形态),缺省实现委托 vcdb 内置;宿主可通过 config 注入自定义实现。理由:测试友好(注入确定性 mock,评测可复现)、后端友好(wasm 场景可替换为宿主环境嵌入服务)、锁定效应低。影响范围:第 6 章 API 层增加 embedder 配置项;第 14 章依赖表已更新;不影响 FR 验收标准。

Q2 决议:不做本地小模型兜底

原开放问题:冲突判定是否需要本地小模型兜底以省 LLM 调用?**决议:不做,且不列入 v0.2 候选。** 理由:与"零部署、依赖最小化"的嵌入式定位冲突,收益场景(无 LLM 密钥使用方)可由 raw 模式覆盖。冲突判定维持纯 LLM 路径 + unstructured 降级。
