Files
memind/docs/architecture/experience-schema-v1.md
T
john 908db04b67 Document Experience schema and JKRiver read-only references.
Map Mi-Memory Structure/Expansion into h5_experience V1 fields and record JKRiver Sleep design lessons under AGPL constraints, plus post-fix MemFuseBench numbers.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 10:04:44 +08:00

202 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Experience Schema V1Mi-Memory Structure / Expansion 映射)
日期: 2026-09-02
状态: 设计草案。依据 Mi-Memory 论文(arXiv:2607.18975**Structure + Expansion** 段与 Memind 现有 `h5_experience` / Agent Memory 定位。**不含 Evolution / Deployment 实现**——那些需等 MemFuseBench 基线与 `memory-v2-product-events` 指标就绪后再做。
## 0. 定位
Mi-Memory 把 Memory 分成四层角色(Structure / Expansion / Evolution / Deployment),用统一 **Audit Contract** 连接。Memind 上一轮架构判断里,**Personal Memory**`h5_user_memory_items`)与 **Agent Memory**`h5_experience`)生命周期不同;Experience Schema V1 只服务后者。
| Mi-Memory 概念 | Memind 落点 | V1 范围 |
|---|---|---|
| MemStack L0 Facts | `h5_user_memory_items` | 已有,不在本文 |
| MemStack L1 Summaries | `conversation-memory` / episodic | 已有,不在本文 |
| MemStack L2 Profile | `user-memory-profile` | 已有,不在本文 |
| **MemStack Skills / 可复用行为** | **`h5_experience` 扩展** | **本文** |
| MemSense / MemFuse 来源标注 | Experience 的 `evidence_json` | **本文** |
| D²ACCI / E²MEND Gate | `memory-v2-product-events` + 未来 gate 表 | 后置 |
| LiteMem 部署变体 | 不在 V1 | 后置 |
论文核心句(§3.1):**memory item ≠ evidence ≠ strategy**。存对了 memory 不够——检索、过滤、打包仍可能丢 evidence。Experience V1 因此必须同时存 **结构化 memory item****可追溯 evidence 链**,而不是一行 `title + body` 摘要。
## 1. 动机:现有 `h5_experience` 缺什么
当前 schema`schema.sql`):
```sql
h5_experience (
id, scope, kind, title, body, tags_json,
source_session_id, source_user_id, use_count,
embedding, created_at, updated_at
)
```
写入点(`mindspace-agent-runner.mjs`)只填 `kind: 'task_outcome'` + `title` + `body` 一行摘要。`reflect()``experience-service.mjs` 仍为 `not_implemented`
这无法支撑用户描述的 SSE 场景:
```
problem: SSE connection instability
environment: goosed + Docker + PG
hypothesis: connection lifecycle issue
action: modified server.rs
result: success
confidence: 0.86
```
也无法对接 Mi-Memory 的 **Typed Evidence Payload**source id / time / device / confidence / provenance)。
## 2. V1 字段定义
### 2.1 表级:`h5_experience` 扩展列
在现有列上**加列**,不新建表。保持 `record()` / `search()` 契约向后兼容:旧行新列为 NULL,读路径用 fallback。
| 列 | 类型 | 必填 | 来源 / 含义 |
|---|---|---|---|
| `problem` | `VARCHAR(512)` | 否 | 触发本次执行的问题陈述(Mi-Memory: 诊断起点) |
| `environment_json` | `JSON` | 否 | 运行环境:`{ runtime, components[], version?, region? }` |
| `hypothesis` | `VARCHAR(512)` | 否 | 执行前的假设(**可空**;见 JKRiver 反面经验) |
| `action_json` | `JSON` | 否 | `{ executor, steps[], artifacts[], diff_ref? }` |
| `result` | `ENUM('success','partial','failure','unknown')` | 否 | 终态 |
| `confidence` | `DECIMAL(4,3)` | 否 | 0–1,写入时对 result 的确信度 |
| `evidence_json` | `JSON` | 否 | **Mi-Memory Typed Evidence**(见 §2.2 |
| `parent_experience_id` | `CHAR(36)` NULL | 否 | 同类问题复发时的链接 |
| `supersedes_id` | `CHAR(36)` NULL | 否 | 新经验取代旧经验 |
| `status` | `ENUM('active','archived','deleted')` | 是 | 默认 `active` |
保留现有 `title` / `body``title` = 短标题(列表 / 注入),`body` = 人类可读摘要(LLM 注入块)。结构化字段供检索、reflect、skill 晋升,不替代 `body`
### 2.2 `evidence_json`Mi-Memory Typed Evidence 最小契约
对应论文 Table 3 **Typed evidence payload**source id, time, device, confidence, provenance)。
```json
{
"sources": [
{
"source_id": "run:abc123",
"source_type": "agent_run",
"actor": "goose",
"device": null,
"timestamp_ms": 1756780800000,
"modality": "tool_result",
"snippet_ref": "event:tool_sse_error_1",
"confidence": 0.86
}
],
"provenance": {
"run_id": "abc123",
"session_id": "sess-xyz",
"user_id": "user-1",
"causal_event_ids": ["evt-1", "evt-2"]
},
"checklist": [
{ "point": "SSE error in goosed logs", "source_ids": ["evt-1"] }
]
}
```
与 MemFuseBench 对齐:`checklist` + `source_ids` 可直接对接 `memory-v2-memfuse-bench.mjs``checklistCoverage` 指标,作为 Experience 召回质量的离线代理。
**V1 不存原始 Event Stream**——只存引用(`run_id` / `causal_event_ids`)。原始事件留在 `h5_agent_run_events`Experience 是 **derived memory item**,不是 Event Kernel 本身。
### 2.3 `kind` 枚举扩展
| `kind` | Mi-Memory 对应 | 用途 |
|---|---|---|
| `lesson` | L0 fact / 教训 | 默认,兼容现有 |
| `task_outcome` | L1 summary | 现有 mindspace-agent-runner |
| `execution_pattern` | procedural hook | 可复用执行模式 |
| `skill_candidate` | Skill 候选 | `reflect()` 晋升前 |
V1 写入仍用 `task_outcome``reflect()` 实现后再产出 `skill_candidate`
### 2.4 `environment_json` 示例
```json
{
"runtime": "goosed",
"components": ["docker", "postgres-session", "portal-proxy"],
"versions": { "goosed": "1.4.1", "portal": "61eebb44" },
"region": "103-canary"
}
```
## 3. 写入契约(Expansion 段)
执行器**不直接写 Experience 表**。对齐 Event Kernel 方向(论文 §5 + Memind 架构共识):
```
Goose / OpenHands / Aider / Browser
h5_agent_run_events (已有)
Experience Extractor V1 新增:agent-run 完成钩子)
h5_experience
```
V1 Extractor 触发点(按优先级):
1. `agent-run-gateway.mjs` — run 终态 `completed` / `failed`
2. `mindspace-agent-runner.mjs` — 已有 `recordExperience()`,扩字段
3. OpenHands / Aider — 仅当 `tool-gateway` 返回结构化 outcome 时
Extractor 必填:`problem`(从 user_message + run 摘要)、`result``evidence_json.provenance.run_id`。其余可 best-effort。
## 4. 读取契约(Structure 段)
`experience-service.search()` V1 不改签名;排序层后续可叠加:
1. 关键词(现有)
2. `environment_json` 组件匹配(如 query 含 "goose" / "sse"
3. `problem` 向量相似度(接 pgvector 后)
注入格式(`retrieveExperience()`V1 扩展为:
```
# 相关经验(供参考,来自历史任务)
- [2026-09] SSE 连接不稳定 (success, conf=0.86)
环境: goosed + Docker + PG
处理: 修改 server.rs 连接生命周期
摘要: ...
```
## 5. 与 Personal Memory 的边界
| 维度 | Personal (`h5_user_memory_items`) | Agent (`h5_experience`) |
|---|---|---|
| 关于 | 这个人是谁 | 怎么做事 |
| 典型字段 | preference, goal, relationship | problem, action, result |
| 生命周期 | JKRiver 式 consolidation**仅参考,不移植代码** | 执行 → reflect → skill |
| Mi-Memory 段 | Structure + Expansion(用户态) | StructureSkills+ Expansiontool/run evidence |
**禁止**把 `hypothesis` 做成一级必填字段。JKRiver `008_drop_hypotheses.sql` 记录:独立 hypotheses 表建后废弃,改由 `user_profile.layer ∈ {suspected, confirmed}` + `supersedes` 表达。Experience 里 `hypothesis` 保持可空;不确定时用 `confidence < 0.5` + `result: 'unknown'`
## 6. V1 实施顺序
1. **Migration**`h5_experience` 加列(上表),默认值 NULL
2. **Extractor**:扩 `recordExperience()` + agent-run 完成路径
3. **`reflect()` 最小实现**:把 N 条 `task_outcome` 聚合为 1 条 `execution_pattern`(规则版,无 LLM
4. **指标**:复用 `memory-v2-product-events``experience_saved` / `experience_recalled`
5. **MemFuseBench 对照**Experience 召回不参与 MemFuse(语料不同),但 `checklistCoverage` 格式保持一致以便将来统一 audit
## 7. 明确不做(V1
- E²MEND 自动策略搜索
- Gate / Rollback 表(Evolution 段)
- LiteMem 文件-native 部署
- 把 Experience 写进 goosed 会话内
- JKRiver Sleep Pipeline 代码移植(AGPL-3.0,见 `jkriver-sleep-reference.md`
## 8. 参考
- Mi-Memory 论文: https://arxiv.org/abs/2607.18975
- MemFuseBench 基线: `docs/architecture/memfuse-bench-baseline.md`
- 现有实现: `experience-service.mjs`, `schema.sql` `h5_experience`