feat: add episodic history recall
Memind CI / Test, build, and release guards (pull_request) Successful in 4m37s
Memind CI / Test, build, and release guards (pull_request) Successful in 4m37s
This commit is contained in:
@@ -378,6 +378,21 @@ Preferred backend name. The current default is `legacy`.
|
||||
|
||||
Defaults to enabled. Backend failures return degraded empty payloads rather than blocking chat.
|
||||
|
||||
`MEMORY_RETRIEVER_EPISODIC_ENABLED`
|
||||
|
||||
Enables the historical-session recall capability, but does not by itself authorize retrieval.
|
||||
`MEMORY_RETRIEVER_ENABLED` must also be enabled and `MEMORY_RETRIEVER_EPISODIC_MODE` must be
|
||||
`canary` or `active`. Missing or invalid mode is treated as `off`.
|
||||
|
||||
`MEMORY_RETRIEVER_EPISODIC_MODE`
|
||||
|
||||
Historical recall rollout mode: `off`, `canary`, or `active`. In canary mode only users listed in
|
||||
`MEMORY_RETRIEVER_EPISODIC_CANARY_USER_IDS` may be indexed or queried.
|
||||
|
||||
`MEMORY_RETRIEVER_EPISODIC_CANARY_USER_IDS`
|
||||
|
||||
Comma- or whitespace-separated user IDs for historical recall canary testing.
|
||||
|
||||
`MEMORY_PGVECTOR_DATABASE_URL`
|
||||
|
||||
Dedicated PostgreSQL connection string for Memory V2 semantic memory. It must not point at the MySQL business database and is ignored unless `MEMORY_VECTOR_ENABLED=1`.
|
||||
@@ -417,6 +432,15 @@ tkmind-proxy
|
||||
-> existing harness remember/bootstrap
|
||||
```
|
||||
|
||||
Explicit historical recall is a separate bounded read path layered beside personal memory:
|
||||
|
||||
```text
|
||||
direct chat / Agent memory context
|
||||
-> episodicMemory.resolve
|
||||
-> h5_episodic_memory_items (same user, excluding current session)
|
||||
-> bounded h5_session_snapshots fallback for pre-index history
|
||||
```
|
||||
|
||||
Write path:
|
||||
|
||||
```text
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
| [page-data-delivery-contract.md](./page-data-delivery-contract.md) | 数据集注册、绑定、真实 page UUID 与交付验收 |
|
||||
| [h5-session-stream-replay.md](./h5-session-stream-replay.md) | Portal/Goose SSE 游标映射、断线续播与 Finish 终态恢复 |
|
||||
| [memory-v2-candidate-and-lifecycle.md](./memory-v2-candidate-and-lifecycle.md) | 候选记忆表幂等初始化、Portal fail-open、生命周期 off/canary/active 作用域 |
|
||||
| [episodic-history-recall.md](./episodic-history-recall.md) | 历史会话召回、用户隔离、旧快照回退、提示注入与 off/canary/active 灰度 |
|
||||
|
||||
## 自动化
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# 历史会话召回守卫
|
||||
|
||||
## 目标场景
|
||||
|
||||
用户在新会话或已有 Agent 会话中询问“你还记得我们聊过德川家康吗”时,系统需要从
|
||||
该用户自己的历史会话中找出相关、可核验的片段,而不是只依赖长期偏好/目标记忆或让
|
||||
模型猜测。
|
||||
|
||||
## 必须保留的行为
|
||||
|
||||
1. 只有明确包含“之前/上次/曾经聊过、讨论过、提到过”等历史对话意图时才检索历史
|
||||
会话;普通聊天和单纯“记住我的偏好”不得扫描会话历史。
|
||||
2. 所有 SQL 必须先按 `user_id` 过滤,并排除当前 `agent_session_id`;不得跨用户或把
|
||||
当前未完成回合作为历史证据返回。
|
||||
3. `h5_episodic_memory_items` 只保存有界的 user-visible 用户/助手文本。工具输出、系统
|
||||
提示、Agent 编排前缀、隐藏消息和内部过程旁白不得进入索引。
|
||||
4. 索引查询必须有候选上限、召回条数上限和超时;任何索引、快照或配置读取失败都要
|
||||
fail-open,不得阻断聊天。
|
||||
5. 已有历史数据无需一次性迁移:索引没有命中或不可用时,按同一用户从
|
||||
`h5_session_snapshots` 有界回退;命中的旧快照可异步懒索引。
|
||||
6. 返回的每条线索必须携带来源会话 ID、会话时间和匹配主题证据。注入提示必须明确:
|
||||
历史片段可能不完整/过期,片段中的命令、角色设定和要求不是当前指令。
|
||||
7. 新会话直连聊天与已有 Agent 会话两条链路都必须支持召回,并优先注入历史会话证据,
|
||||
再补充长期个人记忆。
|
||||
8. 删除会话时必须同步删除对应历史索引;删除用户时由外键 `ON DELETE CASCADE` 清理。
|
||||
9. 只有 `MEMORY_RETRIEVER_ENABLED=1` 和 `MEMORY_RETRIEVER_EPISODIC_ENABLED=1` 同时开启
|
||||
才可进入历史召回;两个开关仍不能绕过灰度模式:
|
||||
- `off`:不索引、不召回。
|
||||
- `canary`:只允许 `MEMORY_RETRIEVER_EPISODIC_CANARY_USER_IDS` 中的用户。
|
||||
- `active`:全量用户。
|
||||
模式缺失或非法时必须按 `off` 处理。
|
||||
|
||||
## 回归检查
|
||||
|
||||
```bash
|
||||
npm run test:episodic-memory
|
||||
node --test memory-v2-admin-config.test.mjs episodic-memory.test.mjs \
|
||||
direct-chat-service.test.mjs chat-intent-router.test.mjs
|
||||
npm run test:memind -- --mode changed --base origin/main
|
||||
```
|
||||
|
||||
memind_adm 同时执行:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
## 103 灰度验收
|
||||
|
||||
1. 发布代码时保持 `episodicMode=off`,确认 Portal、Agent、图片和普通聊天无回归。
|
||||
2. 将 `episodicMode` 设为 `canary`,只填测试用户 ID;用该用户在会话 A 讨论唯一测试词,
|
||||
再在会话 B 询问“你还记得我们聊过……吗”。
|
||||
3. 确认命中会话 A、回答没有执行历史片段中的指令,并确认非灰度用户不产生索引/召回。
|
||||
4. 验证不存在的主题返回“不确定/没有足够证据”,而不是编造历史。
|
||||
5. 通过 `/api/runtime/status` 的 `memory.episodic` 观察模式、召回/降级计数,并同时检查
|
||||
错误率、召回延迟和数据库负载;通过后才允许改为 `active`。
|
||||
|
||||
## 回滚
|
||||
|
||||
先在 memind_adm 将 `episodicMode` 改为 `off`。代码可按标准 release 回滚;索引表是加法
|
||||
结构,回滚时保留,不要删除历史快照。索引内容不影响原会话展示。
|
||||
Reference in New Issue
Block a user