# Memory Agents Lab 测试文档 本文档用于判断配套 Web 项目的记忆链路是否“能运行”,以及是否体现了对应范式的设计效果。**当前只对 Text2Mem 和 ReMe 执行实测验收**;Mem0、Letta 和 memU 的章节是后续实现时的验收清单。 测试对象: - Text2Mem:IR 操作契约与治理; - Mem0:自动提取、更新、冲突处理和检索; - Letta:有状态 Agent、Core / Archival / Recall; - ReMe:文件可读、可审阅和混合检索; - memU:异步摄入、候选记忆和主动式整理。 ## 一、先明确当前项目的测试边界 本项目目前是一个可扩展的 Web 适配器项目,不等同于五个框架全部功能的完整复刻。 | 系统 | 当前状态 | 本阶段可验证边界 | |---|---|---| | Text2Mem | 已完成当前闭环 | Encode / Retrieve、四类记忆标注、去重、混合检索、删除、审计和 PostgreSQL 优先持久化 | | ReMe | 已完成当前闭环 | 官方 `reme-ai 0.4.x` SDK、Markdown 记忆、多查询 BM25 + 可选 Qwen/pgvector 向量召回、文件删除与重建索引 | | Mem0 | 未启用适配器骨架 | 当前不做功能验收;需先补齐记忆投影、删除、重置、冲突和隔离闭环 | | Letta | 未启用适配器骨架 | 当前不做功能验收;需先补齐 Agent ID 恢复、Core / Archival / Recall 投影与删除 | | memU | 未启用适配器骨架 | 当前不做功能验收;需先补齐队列、预算、审批与停止开关 | 因此,测试结果应分为: 1. **基础可用**:系统能否启动、调用和返回结果; 2. **范式效果**:是否体现该系统的核心设计价值; 3. **生产质量**:准确率、延迟、成本、隔离、恢复和治理是否达标。 ## 二、测试前准备 ### 1. 启动基础设施 ```bash cd "/Users/marssheep/Desktop/miaoa/课件文档/AI/记忆系统实战项目/memory-agents-web" docker compose up -d docker compose ps ``` 确认 PostgreSQL 和 Redis 都正常运行。 ### 2. 配置模型 根目录 `.env` 至少应包含: ```dotenv LLM_BASE_URL=https://api.deepseek.com/v1 LLM_API_KEY=你的DeepSeek-Key LLM_MODEL=deepseek-chat DATABASE_URL=postgresql://memory:memory@localhost:54329/memory_agents REDIS_URL=redis://localhost:6379/0 ``` 需要 Embedding 的框架还必须配置独立的 Embedding 服务: ```dotenv EMBEDDING_BASE_URL=你的Embedding服务地址 EMBEDDING_API_KEY=你的Embedding-Key EMBEDDING_MODEL=你的Embedding模型名 EMBEDDING_DIMENSIONS=1536 EMBEDDING_MIN_SCORE=0.35 ``` 不要默认认为 DeepSeek Chat API 同时提供 Embedding API。 ### 3. 启动后端和前端 后端: ```bash cd backend source .venv-reme/bin/activate uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 ``` 前端: ```bash cd frontend npm run dev ``` 打开 。 ### 4. 检查系统状态 ```bash curl http://localhost:8000/api/health curl http://localhost:8000/api/systems ``` 基础要求: - `health.status` 为 `ok`; - `health.storage` 为 `postgres`; - 响应中不存在 `storage_error`; - `llm_configured` 为 `true`; - 若要验收 Qwen + pgvector 二路召回,`embedding_configured` 必须为 `true`; - Text2Mem 的 `available` 为 `true`; - ReMe 的 `available` 为 `true`; - Mem0、Letta 和 memU 在当前阶段应为 `false`。 ## 三、统一测试数据 当前先让 Text2Mem 和 ReMe 使用同一套对话;未来补齐其他三种适配器时继续复用这套数据,避免因为测试数据不同而误判。 ### 场景 A:稳定偏好 ```text 记住:我偏好使用 Python 和 FastAPI,代码要求有严格类型注解。 ``` ### 场景 B:项目事实 ```text 我正在开发一个企业内部智能知识库问答项目,使用通义千问和 RAG,数据库选择 PostgreSQL。 ``` ### 场景 C:状态变化 ```text 项目目前完成了文档解析和向量化模块,正在开发检索重排功能。 ``` ```text 更新一下:检索重排功能已经完成 75%,下一步是补充效果评测集和集成测试。 ``` ### 场景 D:历史事件 ```text 上次部署测试环境时遇到向量索引构建超时,最后通过分批导入文档并调整批次大小解决。 ``` ### 场景 E:程序性记忆 ```text 以后修复代码时按这个流程:先复现问题,再定位原因,修改后运行测试,最后记录验证结果。 ``` ### 场景 F:相似但不应混淆的内容 ```text 我喜欢 Python,但这个项目的前端使用 TypeScript 和 React。 ``` ## 四、通用测试流程 对 Text2Mem 和 ReMe 执行以下流程,并分别记录结果。不要在当前版本强行开启其他三个骨架。 ### 测试 1:启动与配置 检查: - Web 页面能加载; - 系统状态显示正确; - 未配置的系统显示不可用原因,而不是假装成功; - 后端日志没有未处理异常。 通过标准:系统状态与实际 SDK / 服务状态一致。 ### 测试 2:写入记忆 依次发送场景 A、B、D、E。 检查: - 是否写入了持久记忆; - 是否保留来源、时间和记忆类型; - 是否生成了审计事件; - 重启后端后记忆是否仍然存在。 通过标准:重启后仍能读取重要记忆,且记忆不依赖当前页面状态。 ### 测试 3:精准检索 依次提问: ```text 我的后端技术栈是什么? 上次部署遇到什么问题? 我要求的代码修复流程是什么? ``` 检查: - 返回的是相关记忆; - 没有把无关内容大量塞入上下文; - 历史事件和程序流程没有混淆; - 回答能够区分事实、历史和推断。 ### 测试 4:状态变化和冲突 先写入: ```text 前端使用 React。 ``` 再写入: ```text 更新一下,前端已经改成 Vue 3。 ``` 再提问: ```text 我当前的前端技术栈是什么?历史上用过什么? ``` 通过标准: - 当前值为 Vue 3; - React 可以作为历史值保留,或明确标记为失效; - 不应无来源地同时回答“当前是 React 和 Vue 3”; - 结果最好包含更新时间、来源和冲突处理方式。 > 这项是诊断性测试,不是当前 Text2Mem L2 的通过前提。Text2Mem 尚未实现 Update 和通用冲突消解;如果新旧值只是并存,应如实记录为当前限制,不能判为通过。 ### 测试 5:清空和恢复 > 本测试会删除数据,只在专用测试工作区或确认不需要现有记忆后执行。 1. 在 Web 页面清空当前系统记忆; 2. 调用 `/api/memories` 确认记忆为空; 3. 重启后端; 4. 再次检查记忆是否仍为空; 5. 重新写入一条记忆,确认系统可以恢复工作。 ## 五、Text2Mem 测试 ### 目标 验证“先定义受限记忆操作,再由执行层校验和审计”的效果。 ### 基础测试 在 Web 中选择 Text2Mem,发送: ```text 记住:我偏好使用 Python 和 FastAPI,代码要求有严格类型注解。 ``` 检查返回结果: - `mode` 为 `llm` 或 `local-fallback`; - `memory_events` 中出现 `ENC/Encode`; - 记忆面板出现一条新记忆; - 审计中出现 `ENC/Encode` 和 `RET/Retrieve`; - 数据库中能够查到记录。 再依次发送场景 B、C 的最新进度、D、E,应当总共得到 5 条记忆,其中: - A、B 为 `semantic`; - D 为 `episodic`; - E 为 `procedural`; - C 为 `task-state`。 然后发送“上次部署遇到了什么问题?”:记忆总数不应增加,召回上下文应包含“向量索引构建超时”。 数据库检查: ```bash docker compose exec postgres psql -U memory -d memory_agents \ -c "SELECT system, content, source, confidence FROM memory_items WHERE workspace_id='local-workspace' AND system='text2mem';" ``` ### 范式效果验收 | 验收项 | 通过标准 | |---|---| | 操作可见 | 能看到 Encode / Retrieve 等操作 | | 来源可追溯 | 记忆含来源、置信度和时间 | | 审计完整 | 写入和读取都有审计事件 | | 受限写入 | 问句不写入;稳定偏好、项目事实、历史故障和长期流程可写入 | | 分类检索 | 历史问题优先召回 episodic,流程问题优先召回 procedural | | 去重 | 完全相同的陈述重复发送后不新建记忆 | | 可恢复 | 后端重启后记忆仍在 | ### 当前限制 当前 Web 适配器实现了 Encode / Retrieve、记忆分类、去重、关键词 + 类型 + 可选 Embedding 检索、公共删除与审计路径。Lock、Expire、Merge、Split、Update 等完整 IR 处理器仍是后续扩展项,不要把当前 Web 版本误判为完整 Text2Mem 引擎。 ## 六、Mem0 后续验收清单(当前不执行) > 当前适配器未完成公共记忆投影、单条删除、重置和冲突验收闭环,应保持 `MEM0_ENABLED=false`。本章只供后续开发。 ### 前置条件 ```bash cd backend source .venv-reme/bin/activate uv pip install mem0ai ``` 后续实现完成后才允许修改 `.env`: ```dotenv MEM0_ENABLED=false # 当前保持关闭 ``` 后续需同时配置可用的 Embedding 服务,并且只有在下方验收全部通过后才能把 Mem0 标记为可用。 ### 测试步骤 1. 发送场景 A、B; 2. 发送场景 C 的进度更新; 3. 发送 React → Vue 3 的冲突测试; 4. 提问“当前前端技术栈是什么”; 5. 检查返回中的 Mem0 add / search 结果; 6. 重启后端,再次检索。 ### 范式效果验收 | 验收项 | 通过标准 | |---|---| | 自动提取 | 用户只聊天,系统能提取稳定事实 | | 冲突处理 | 新旧值有明确更新、失效或冲突标记 | | 相关检索 | 查询只返回相关记忆 | | 持久化 | 重启后记忆仍可检索 | | 范围隔离 | 使用固定 `WORKSPACE_ID`,不能读到其他命名空间 | 右侧公共记忆列表、单条删除和 `/api/reset` 必须与 Mem0 内部存储一致;不能再以“只看 Mem0 检索结果”规避投影不完整问题。 ## 七、Letta 后续验收清单(当前不执行) > 当前适配器没有持久化 Agent ID,也没有完成 Core / Archival / Recall 投影与删除闭环,应保持 `LETTA_ENABLED=false`。 ### 前置条件 ```bash cd backend source .venv-reme/bin/activate uv pip install letta-client ``` 启动目标版本的 Letta 服务端,并设置: ```dotenv LETTA_BASE_URL=http://localhost:8283 LETTA_API_KEY= ``` 确认服务端和 Python 客户端版本匹配。 ### 测试步骤 1. 选择 Letta; 2. 发送项目名、技术栈和项目进度; 3. 继续发送一条代码问题; 4. 再提问“我的项目名和技术栈是什么”; 5. 重启 FastAPI,但不要删除 Letta 服务端数据; 6. 再次发送消息,确认 Agent 状态仍然存在。 ### 范式效果验收 | 验收项 | 通过标准 | |---|---| | Core Memory | 高频项目上下文能持续出现在 Agent 状态中 | | Archival Memory | 长期内容需要搜索时能被召回 | | Recall Memory | 历史对话可以回溯 | | Agent 状态 | 不是每次请求都创建全新 Agent | | 工具权限 | Agent 只能访问当前工作区允许的记忆 | 如果每次 Web 请求都创建新的 Letta Agent,说明状态复用逻辑没有通过,应记录为失败。 ## 八、ReMe 测试 ### 前置条件 使用项目已约束的 `reme-ai[core]>=0.4,<0.5` 依赖: ```bash cd backend source .venv-reme/bin/activate uv pip install -e '.[reme]' python -c "from importlib.metadata import version; print(version('reme-ai'))" ``` 启用: ```dotenv REME_ENABLED=true ``` ### 测试步骤 1. 发送场景 A、B、D、E; 2. 检查 `DATA_DIR` 下是否生成文件型记忆; 3. 使用 `find DATA_DIR/reme/daily -name '*.md' -print` 找到并打开 ReMe 记忆文件;文件可能是 `daily/YYYY-MM-DD.md` 日期索引,也可能位于日期子目录; 4. 在 Web 对话框中分别提问“上次部署遇到了什么问题?”“我要求的代码修复流程是什么?”“我的后端技术偏好是什么?”; 5. 确认上述问句本身没有被 `auto_memory` 写入新的 Markdown 记忆; 6. 修改一个可审阅文件后发送下一条查询,让适配器自动执行 `reindex` 和向量同步;也可以通过 Web 删除整个记忆文件,删除接口会立即重建 ReMe 索引; 7. 检查检索结果是否与文件内容一致。 > **数量口径:** ReMe 的右侧面板按 Markdown 文件计数,不按原子事实计数。A、B、D、E 四段陈述可能被合并到少量文件,也可能按主题拆分;文件数量本身不能判断是否丢失。必须打开文件检查四类信息是否都存在,再通过三类查询验证召回。 ### 范式效果验收 | 验收项 | 通过标准 | |---|---| | 文件可读 | 人可以直接打开并理解记忆内容 | | 文件可编辑 | 修改文件后系统能够重新读取或索引 | | 任务记忆 | 失败经验和成功流程能够再次召回 | | 混合检索 | ReMe 多查询 BM25 有效;配置项目 Embedding 后,pgvector 向量召回也有命中证据 | | 查询不污染 | 提问只触发检索,不新建长期记忆文件 | | 一致性 | 文件内容与索引结果没有明显不一致 | ## 九、memU 后续验收清单(当前不执行) > 当前适配器没有完成后台队列、重试、预算、用户同意与停止开关,应保持 `MEMU_ENABLED=false`。本章只供后续开发。 ### 前置条件 建议 Python 3.13: ```bash cd backend uv venv --python 3.13 .venv-memu source .venv-memu/bin/activate uv pip install -e . git clone https://github.com/NevaMind-AI/memU.git /tmp/memU cd /tmp/memU git rev-parse HEAD uv pip install -e . ``` 当前配置: ```dotenv MEMU_ENABLED=false # 当前保持关闭 ``` ### 测试步骤 连续三天或模拟三组活动: ```text 第 1 组:我在研究 RAG 的文档分块策略。 第 2 组:我想了解向量检索与关键词检索的融合方法。 第 3 组:我正在设计知识库问答的重排序与效果评测。 ``` 检查: - 对话被摄入为活动记录; - retrieve 能返回当前问题相关的上下文; - 系统生成的是候选兴趣或候选记忆,而不是未经确认的用户事实; - 后台处理不会阻塞主对话; - 关闭主动策略后不会继续主动触达。 ### 范式效果验收 | 验收项 | 通过标准 | |---|---| | 异步摄入 | 记忆整理与主对话解耦 | | 候选记忆 | 推断带有候选或置信度标记 | | 相关上下文 | 只返回当前任务需要的信息 | | 预算控制 | 有任务数量、Token 或时间上限 | | 主动边界 | 默认不推送、不自动执行高风险动作 | ## 十、统一指标记录 当前对 Text2Mem 和 ReMe 各至少记录 10 次同类查询;其他适配器实现后使用相同口径: | 指标 | 记录方式 | |---|---| | 写入成功率 | 成功写入次数 / 写入总次数 | | 检索命中率 | 返回正确记忆的查询数 / 查询总数 | | 冲突正确率 | 正确识别新旧值的次数 / 冲突测试次数 | | 无关召回率 | 返回无关记忆的次数 / 查询总数 | | p50 延迟 | 50% 请求低于该耗时 | | p95 延迟 | 95% 请求低于该耗时 | | Token 消耗 | 记录模型请求的输入和输出 Token | | 持久化恢复率 | 重启后仍能找回的记忆数 / 写入数 | | 审计完整率 | 有审计记录的操作数 / 总操作数 | | 失败率 | 失败请求数 / 总请求数 | 建议记录到 CSV 或表格,不要只凭页面感觉判断“效果好”。 ## 十一、最终验收等级 ### L0:能启动 - Docker 服务健康; - 后端 `/api/health` 正常; - 前端页面可打开; - 系统状态与实际配置一致。 ### L1:能记住 - 能写入一条稳定记忆; - 能检索同一条记忆; - 重启后记忆还在; - 能看到基本审计记录。 ### L2:体现范式 - 当前版本必须通过:Text2Mem 的操作、分类、去重和检索可见;ReMe 的文件可读、可审阅、可检索; - 后续版本才验收:Mem0 的自动提取与冲突处理、Letta 的持久 Agent 状态、memU 的后台整理与候选记忆边界。 ### L3:接近生产 - 有真实数据集上的召回评测; - 有 p50 / p95、Token 和成本记录; - 有权限、删除、留存和审计策略; - 有失败重试和服务降级; - 有并发、重启、备份和恢复测试; - 有敏感信息和提示注入测试。 只有达到 L2,才可以说“实现了对应的记忆范式效果”;达到 L0 或 L1,只能说“项目可以运行”。 ## 十二、故障排查 ### 系统显示未配置 ```bash curl http://localhost:8000/api/systems ``` 检查: - Text2Mem 应始终可用; - ReMe 是否在 `.venv-reme` 中安装,并设置 `REME_ENABLED=true`; - Mem0、Letta 和 memU 当前应保持不可用; - 修改 `.env` 后是否重启后端。 ### 存储显示 `local-json` 说明 PostgreSQL 连接失败。检查: ```bash docker compose ps docker compose logs postgres ``` 同时查看 `/api/health` 的 `storage_error`。如果更换了 `EMBEDDING_DIMENSIONS`,现有 `memory_embeddings` 表的向量维度与新配置不一致也会导致降级;应先迁移或重建向量表。 ### 模型调用失败 检查: - `LLM_BASE_URL` 是否包含正确的 `/v1`; - API Key 是否有效; - 模型名是否可用; - Embedding 是否使用了独立且兼容的服务; - 是否被网络、代理或区域限制阻断。 ### 清理单个系统 ```bash curl -X POST http://localhost:8000/api/reset \ -H 'content-type: application/json' \ -d '{"system":"text2mem"}' ``` 清理全部系统: ```bash curl -X POST http://localhost:8000/api/reset \ -H 'content-type: application/json' \ -d '{}' ``` 全局清理会调用每个适配器自己的重置逻辑,因此会同时删除 Text2Mem 的公共存储和 ReMe 的 Markdown 文件/派生向量。Mem0、Letta、memU 当前未启用;后续启用后必须另行验证其外部存储是否也被清理。