# Thread Memory 手动测试清单 日期:`2026-05-08` 测试人:`__________` --- ## 0. 前置检查 - [ ] 已拉取包含以下修复的最新代码并重启后端进程 - `memory.enabled=false` 时仍允许 `thread_memory` 更新 - `thread_prompt` 的 JSON 模板转义修复(避免 `KeyError: "profile"`) - `thread_updater` 使用非流式安全参数(避免 `stream_options` 400) - [ ] `config.yaml` 中已启用 `thread_memory.enabled: true` - [ ] 确认使用的是预期配置文件(当前项目根目录 `config.yaml`) --- ## 1. 基础写入与读取 前置条件: - 选择一个新的 `thread_id`(例:`1f571481-e3ae-42b5-a513-945bf8f1cbef`) 步骤: 1. 在该线程发送 2-3 轮消息,包含姓名、角色、偏好语气等信息 2. 等待 `debounce_seconds`(默认 30 秒) 3. 查询 `thread_memory` 表 期望: - 出现该 `thread_id` 记录 - `profile/preferences/facts` 有对应内容 结果: - [1] 通过 - [ ] 失败(备注:`________________`) --- ## 2. Per-Thread 隔离 前置条件: - 准备两个线程 `thread_A`、`thread_B` 步骤: 1. 在 A 中输入“前端背景”信息 2. 在 B 中输入“后端背景”信息 3. 分别等待写入完成后查看两条记录 期望: - A 仅保存 A 的画像,B 仅保存 B 的画像 - 两个线程不串数据 结果: - [1] 通过 - [ ] 失败(备注:`________________`) --- ## 3. 全局记忆 Fallback 前置条件: - 全局 memory 有内容 - 新建一个尚无 per-thread 记录的线程 步骤: 1. 先在该新线程发一轮普通消息 2. 观察回复是否体现全局记忆 3. 再继续对话触发 per-thread 写入后观察注入变化 期望: - 无 per-thread 时可 fallback 到全局 - 有 per-thread 后优先使用 per-thread 结果: - [ ] 通过 - [ ] 失败(备注:`未执行(N/A):当前环境 memory.enabled=false,全局记忆关闭,本用例不适用`) --- ## 4. 注入裁剪优先级(Profile > Preferences > Facts) 前置条件: - 某线程已有大量 facts 步骤: 1. 人为积累 facts 到接近/超过注入预算 2. 保持 profile/preferences 有值 3. 观察注入后的表现 期望: - 超预算时保留 profile + preferences - 优先裁剪 facts 结果: - [1 ] 通过 - [ ] 失败(备注:`________________`) --- ## 5. 敏感信息过滤 步骤: 1. 在对话中输入邮箱、手机号、token/password 等敏感样例 2. 等待写入后查库 期望: - 敏感信息不应落入 `profile/preferences/facts` 结果: - [1] 通过 - [ ] 失败(备注:`________________`) --- ## 6. 并发覆盖保护(CAS + version) 步骤: 1. 同一 `thread_id` 短时间内触发两次更新(尽量并发) 2. 观察最终数据与日志 期望: - 不出现明显“旧数据覆盖新数据” - 冲突时可见重试行为(日志) 结果: - [1] 通过 - [ ] 失败(备注:`________________`) --- ## 7. Debounce 生效 步骤: 1. 在 30 秒内连续发送多条消息 2. 观察写库频率 期望: - 多条输入被合并处理,不是每条都立即写库 结果: - [1] 通过 - [ ] 失败(备注:`________________`) --- ## 8. 线程删除联动清理 步骤: 1. 对已有 per-thread 记录的线程调用 `DELETE /api/threads/{thread_id}` 2. 查询 `thread_memory` 表 期望: - 对应 `thread_id` 记录被删除 结果: - [ ] 通过 - [ ] 失败(备注:`未执行:当前产品决策不接受“删线程即删记忆”,需改为用户显式触发清除后再复测`) --- ## 9. SQLite 自动建表与路径 步骤: 1. 删除现有 `thread_memory.db`(测试环境) 2. 重启服务并触发一轮写入 3. 检查 DB 文件和表结构 期望: - 自动创建 DB 文件与 `thread_memory` 表 - 索引 `idx_thread_memory_owner_id` 存在 结果: - [1] 通过 - [ ] 失败(备注:`________________`) --- ## 10. 配置开关验证 步骤: 1. 关闭 `thread_memory.enabled`,重启并测试写入 2. 开启 `thread_memory.enabled`,关闭 `thread_memory.injection_enabled`,重启并测试注入 期望: - `enabled=false`:不更新 per-thread - `injection_enabled=false`:不注入 per-thread(可 fallback) 结果: - [1] 通过 - [ ] 失败(备注:`________________`) --- ## 11. 已知错误回归验证 ### 11.1 `KeyError: "profile"` 回归 - [ 1] 未再出现 `thread_prompt.py` 的 `KeyError` 报错 ### 11.2 `stream_options` 400 回归 - [ 1] 未再出现 `"'stream_options' only set this when you set stream: true"` 报错 备注:`________________` --- ## 测试总结 - 总用例数:`11` - 通过数:`____` - 失败数:`____` - 结论: - [ ] 可上线 - [ ] 需修复后复测