Files
ST-Bionic-Memory-Ecology/docs/algorithms/consolidation-and-compression.md
2026-05-31 17:02:21 +00:00

100 lines
5.2 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.

# 整合、压缩与分层总结
提取后处理链路里的三个维护算法:记忆整合/去重、压缩遗忘、分层总结。它们让图谱长期保持精简、不无限膨胀。
实现:`maintenance/consolidator.js``maintenance/compressor.js``maintenance/hierarchical-summary.js`
## 整合 / 去重Mem0 式)
分两层:自动整合门 + 整合执行。
### 自动整合门(`analyzeAutoConsolidationGate`
决定要不要触发整合。默认 `conflictThreshold = 0.85`。对每个新节点:
- 候选 = 活跃、未归档、非自身、且 scope/故事时间兼容(`canMergeTemporalScopedMemories`)的节点
- 若类型是 `latestOnly`:对 `name`/`title` 做规范化精确匹配(去空白、折叠空格、小写),命中则触发,分数 1
- 否则:对 scoped 候选做向量 top-1 相似度,分数 ≥ 阈值则触发
更高层门控:候选数 ≥ `consolidationAutoMinNewNodes`(默认 2则无条件运行不足且分析触发则运行。
### 整合执行(`consolidateMemories`
需要有效向量配置,否则跳过。
- **Phase 0**:收集有向量文本的活跃新节点。少于 2 个则全保留。
- **Phase 1/2**:直连模式一次 `embedBatch()` 嵌入所有新节点;从有 embedding 的活跃节点建候选池;本地余弦 `searchSimilar()` 找邻居(默认 `neighborCount=5`)。
- **Phase 3**LLM 批量决策,每个新节点返回 `action: keep|merge|skip``merge_target_id``merged_fields``evolution`
- **Phase 4** 应用:
- `skip`:新节点归档
- `merge`(目标活跃且兼容):用 `merged_fields` 或用新节点填补目标缺失字段;更新 `seq`/`seqRange`;复制缺失的 storyTime清空目标 embedding归档新节点
- `keep`:保留;并对 evolution 建 `related`strength 0.7)、更新邻居 state/summary、记录 `_evolutionHistory`
> Mem0 式精确匹配主要体现在 `latestOnly` 类型的同名即时更新和整合门的精确匹配;更广的去重/合并是"LLM 在向量邻居上决策",不是纯确定性精确匹配。
| 参数 | 默认 |
| --- | --- |
| `enableConsolidation` | true |
| `consolidationNeighborCount` | 5 |
| `consolidationThreshold` | 0.85 |
| `consolidationAutoMinNewNodes` | 2 |
## 压缩(分层)
`compressAll()` 对每个 `compression.mode === "hierarchical"` 的 schema 类型运行 `compressType()`
自动调度:`enableAutoCompression`(默认 true`compressionEveryN`(默认 10夹 1..500),当 `extractionCount % everyN === 0` 时调度。
压缩窗口参数来自各 schema 类型的 `compression` 配置:
- `fanIn`min 2缺省 2每组压缩多少个子节点
- `threshold`(缺省 = fanIn组多大才压缩
- `keepRecentLeaves`(缺省 0保留最近 N 个叶子不压缩
- `maxDepth`(缺省 1最大压缩层级
压缩流程:取某类型某层级的活跃节点按 seq 排序 → 按 POV owner / 客观区域分组 → 跳过太小的组 → 对 `fanIn` 个一批 LLM 总结成一个压缩节点(`level + 1`importance 取子节点最大seqRange 覆盖首末)→ 子节点归档并设 `parentId` → 外部边迁移到压缩节点(内部边忽略)。
## 遗忘 / 睡眠周期
`sleepCycle()``compressor.js`)。自动触发:`enableSleepCycle`(默认 false`extractionCount % sleepEveryN === 0`(默认 10
跳过:`synopsis`/`rule`/`thread` 类型、`importance >= 8`、创建不足 1 小时的节点。
保留价值计算:
```
ageHours = (now - createdTime) / 3600000
recency = 1 / (1 + log10(1 + ageHours))
accessFreq = accessCount / max(1, ageHours / 24)
retentionValue = (importance / 10) × recency × (1 + accessFreq)
```
`retentionValue < forgetThreshold`(默认 0.5)的节点归档(不物理删除)。
> 已知边界:`sleepCycle` 直接用 `node.accessCount`,若未初始化会算出 NaN使该节点不被遗忘NaN < threshold 为 false
## 分层总结
`runHierarchicalSummaryPostProcess()``hierarchical-summary.js`)。默认启用(`enableHierarchicalSummary !== false`)。
### 小总结small summary
`generateSmallSummary()`:阈值 `smallSummaryEveryNExtractions`(默认 3夹 1..100)。当 `currentExtractionCount - lastSummarizedExtractionCount >= 阈值` 时,把自上次以来的提取切片(含当前批次)总结成一条 `synopsis`80-220 字),记为 `level:0, kind:"small", status:"active"`,带 extractionRange/messageRange/sourceBatchIds 等。
### 卷积/折叠总结rollup
`rollupSummaryFrontier()`fan-in `summaryRollupFanIn`(默认 3夹 2..10)。当同层活跃总结条目数 > fanIn 时,取前 fanIn 条 LLM 卷成一条更高层总结120-260 字),源总结标记为 folded新总结记为 `level + 1, kind:"rollup"`。循环直到没有可折叠的组。
这形成一个"小总结 → 折叠总结 → 更高层折叠"的金字塔,让久远的剧情用越来越浓缩的形式保留。
| 参数 | 默认 |
| --- | --- |
| `enableHierarchicalSummary` | true |
| `smallSummaryEveryNExtractions` | 3 |
| `summaryRollupFanIn` | 3 |
| `enableAutoCompression` | true |
| `compressionEveryN` | 10 |
| `enableSleepCycle` | false |
| `forgetThreshold` | 0.5 |
| `sleepEveryN` | 10 |