refactor(terminology): 层级总结为主路径,synopsis 标记为旧式全局概要

- README: 明确 summaryState 为主总结体系,legacy synopsis 为兼容兜底
- prompt-profiles: synopsis 任务标签改为「小总结」
- schema/task-graph-stats/panel: synopsis 节点显示为「全局概要(旧)」
- index.js: fallback 状态文案改为「旧式全局概要生成/更新中」
- p0-regressions: 同步更新断言字符串
This commit is contained in:
Youzini-afk
2026-04-12 17:57:49 +08:00
parent 2646dc0962
commit 47ffd5413d
8 changed files with 51 additions and 39 deletions

View File

@@ -67,7 +67,7 @@ flowchart LR
- **整合** — 相似记忆合并Mem0 精确对照 + A-MEM 进化) - **整合** — 相似记忆合并Mem0 精确对照 + A-MEM 进化)
- **压缩** — 太多类似的事件记忆会被层级合并 - **压缩** — 太多类似的事件记忆会被层级合并
- **概要** — 自动生成"之前发生了什么"的总结(含层级摘要折叠 - **层级总结** — 基于近期原文窗口生成小总结,并在前沿过厚时继续做总结折叠
- **反思** — 长期模式总结,生成叙事指导原则 - **反思** — 长期模式总结,生成叙事指导原则
- **遗忘** — 很久没被用到的记忆降低优先级 - **遗忘** — 很久没被用到的记忆降低优先级
@@ -88,7 +88,7 @@ flowchart LR
注入的内容分成两层: 注入的内容分成两层:
- **Core常驻层** — 规则、概要、主线这类始终需要的 - **Core常驻层** — 规则、主线,以及在没有活跃总结前沿时兜底的旧式全局概要
- **Recalled动态层** — 根据当前对话语境召回的 - **Recalled动态层** — 根据当前对话语境召回的
每层内进一步按用途分桶:当前状态 / 情景事件 / 反思锚点 / 规则约束。 每层内进一步按用途分桶:当前状态 / 情景事件 / 反思锚点 / 规则约束。
@@ -121,12 +121,15 @@ ST-BME 的处理方式是:
### 方法一:通过 SillyTavern 扩展安装 ### 方法一:通过 SillyTavern 扩展安装
1. 打开 SillyTavern → 扩展 → 安装扩展 1. 打开 SillyTavern → 扩展 → 安装扩展
2. 输入仓库地址: 1. 输入仓库地址:
```text
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology ```text
``` https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology
注意:请粘贴仓库根地址,不要使用像 `/graphs/code-frequency` 这样的 GitHub 子页面地址。 ```
3. 刷新页面
注意:请粘贴仓库根地址,不要使用像 `/graphs/code-frequency` 这样的 GitHub 子页面地址。
1. 刷新页面
### 方法二:手动安装 ### 方法二:手动安装
@@ -161,7 +164,7 @@ git clone https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git st-bme
| 📍 地点 | 地点状态 | "废弃实验室,门被锁上了" | | 📍 地点 | 地点状态 | "废弃实验室,门被锁上了" |
| 📌 规则 | 世界观设定、约束 | "魔法会消耗生命力" | | 📌 规则 | 世界观设定、约束 | "魔法会消耗生命力" |
| 🧵 主线 | 任务线/剧情线 | "寻找失踪的项链" | | 🧵 主线 | 任务线/剧情线 | "寻找失踪的项链" |
| 📜 概要 | 自动生成的前情提要 | — | | 📜 全局概要(旧) | 单条全局前情提要,现主要用于兼容 / 迁移兜底 | — |
| 💭 反思 | 长期规律总结 | "他们经常在夕阳下聊天" | | 💭 反思 | 长期规律总结 | "他们经常在夕阳下聊天" |
| 👁️ 主观记忆 | 角色视角下的记忆,含误解和情绪 | "她以为他离开了,其实他躲起来了" | | 👁️ 主观记忆 | 角色视角下的记忆,含误解和情绪 | "她以为他离开了,其实他躲起来了" |
@@ -187,13 +190,17 @@ ST-BME 的记忆不是扁平的——它模拟了真实的认知分层:
- 时间线上下文可注入 prompt帮助模型保持时间感知 - 时间线上下文可注入 prompt帮助模型保持时间感知
- 支持软引导(`storyTimeSoftDirecting`),不强制但提示模型注意时间流 - 支持软引导(`storyTimeSoftDirecting`),不强制但提示模型注意时间流
### 总结状态
当前主用的总结体系不是 `synopsis` 节点,而是 `summaryState` 中持续演化的「小总结 + 总结折叠」活跃前沿。
--- ---
## 🔧 设置说明 ## 🔧 设置说明
### 记忆 LLM ### 记忆 LLM
用来做提取、压缩、整合、概要、反思等任务的模型。 用来做提取、压缩、整合、小总结、总结折叠、反思等任务的模型。
- **留空** → 复用当前 SillyTavern 的聊天模型(最简配置) - **留空** → 复用当前 SillyTavern 的聊天模型(最简配置)
- **填写** → 你可以指定一个独立的 OpenAI-compatible 模型专门处理记忆 - **填写** → 你可以指定一个独立的 OpenAI-compatible 模型专门处理记忆
@@ -261,11 +268,12 @@ ST-BME 的记忆不是扁平的——它模拟了真实的认知分层:
| ------ | ------ | ------ | | ------ | ------ | ------ |
| 启用整合 | 开 | 相似记忆自动合并 | | 启用整合 | 开 | 相似记忆自动合并 |
| 整合阈值 | 0.85 | 向量相似度高于此值时触发合并 | | 整合阈值 | 0.85 | 向量相似度高于此值时触发合并 |
| 启用概要 | 开 | 定期生成前情提要 | | 启用层级总结 | 开 | 启用「小总结 + 总结折叠」主路径(兼容旧 `enableSynopsis` 命名) |
| 启用层级摘要 | 开 | 摘要自动折叠合并 | | 小总结频率 | 3 次提取 | 每累计多少次提取生成一条新的小总结 |
| 折叠扇入 | 3 | 同层活跃总结达到多少条时触发一次折叠 |
| 启用反思 | 开 | 让 AI 总结长期模式 | | 启用反思 | 开 | 让 AI 总结长期模式 |
| 启用自动压缩 | 开 | 事件/主线节点过多时自动层级合并 | | 启用自动压缩 | 开 | 事件/主线节点过多时自动层级合并 |
| 启用主动遗忘 | 开 | 太久没的记忆降低优先级 | | 启用主动遗忘 | 开 | 太久没被用到的记忆降低优先级 |
| 启用智能触发 | 关 | 仅在检测到关键内容时才提取 | | 启用智能触发 | 关 | 仅在检测到关键内容时才提取 |
| 启用概率召回 | 关 | 以一定概率触发召回,减少 token 消耗 | | 启用概率召回 | 关 | 以一定概率触发召回,减少 token 消耗 |
@@ -307,9 +315,11 @@ ST-BME 的记忆不是扁平的——它模拟了真实的认知分层:
### 操作 Tab ### 操作 Tab
- 手动提取 — 立即从当前对话提取(模式选择跨会话记忆) - 手动提取 — 立即从当前对话提取(模式选择跨会话记忆)
- 手动压缩 — 合并重复/过时记忆 - 手动压缩 — 合并重复/冗余的事件
- 执行遗忘 — 主动降级低价值记忆 - 执行遗忘 — 降低长期未使用记忆的优先级
- 更新概要 — 重新生成前情提要 - 生成小总结 — 基于近期原文窗口生成阶段性总结
- 执行总结折叠 — 折叠当前活跃总结前沿
- 重建总结状态 — 从提取批次重建小总结与折叠总结
- 导出 / 导入图谱 - 导出 / 导入图谱
- 重建图谱 — 从当前聊天重新提取全部记忆 - 重建图谱 — 从当前聊天重新提取全部记忆
- 重建向量 — 重建全部向量索引 - 重建向量 — 重建全部向量索引
@@ -318,6 +328,7 @@ ST-BME 的记忆不是扁平的——它模拟了真实的认知分层:
### 配置 Tab ### 配置 Tab
配置页是一个完整的工作区,分成 5 个子页: 配置页是一个完整的工作区,分成 5 个子页:
- **API 配置** — 记忆 LLM、Embedding 向量源 - **API 配置** — 记忆 LLM、Embedding 向量源
- **功能开关** — 提取/召回/维护各项功能的启用开关 - **功能开关** — 提取/召回/维护各项功能的启用开关
- **详细参数** — 检索流水线、认知架构、维护阈值等细粒度参数 - **详细参数** — 检索流水线、认知架构、维护阈值等细粒度参数
@@ -328,7 +339,7 @@ ST-BME 的记忆不是扁平的——它模拟了真实的认知分层:
### 图谱可视化 ### 图谱可视化
桌面端右侧大区域显示力导向图谱,节点可拖拽、缩放、点击查看详情。支持 4 套配色主题切换。 桌面端右侧大区域显示力导向图谱,节点可拖拽、缩放、点击查看详情。支持 4 套主题配色切换。
--- ---
@@ -359,7 +370,9 @@ ST-BME 的记忆不是扁平的——它模拟了真实的认知分层:
| 手动提取 | 不等自动触发,立刻提取当前对话 | | 手动提取 | 不等自动触发,立刻提取当前对话 |
| 手动压缩 | 把重复/冗余的事件合并 | | 手动压缩 | 把重复/冗余的事件合并 |
| 执行遗忘 | 降低长期未使用记忆的优先级 | | 执行遗忘 | 降低长期未使用记忆的优先级 |
| 更新概要 | 重新生成全局前情提要 | | 生成小总结 | 基于近期原文窗口生成一条新的阶段性总结 |
| 执行总结折叠 | 将多条同层活跃总结折叠成更高层总结 |
| 重建总结状态 | 从提取批次重建小总结与折叠总结 |
| 导出图谱 | 下载当前图谱 JSON不含向量 | | 导出图谱 | 下载当前图谱 JSON不含向量 |
| 导入图谱 | 导入图谱文件(导入后需重建向量) | | 导入图谱 | 导入图谱文件(导入后需重建向量) |
| 重建图谱 | ⚠️ 清空现有图谱,从聊天记录重新提取 | | 重建图谱 | ⚠️ 清空现有图谱,从聊天记录重新提取 |
@@ -566,7 +579,7 @@ AI 回复 → 结构化消息预处理
→ [可选世界书扫描] → [可选世界书扫描]
→ LLM 提取 → 近邻对照 → 认知归属判定 → LLM 提取 → 近邻对照 → 认知归属判定
→ 写入图谱 + 同步向量 + 故事时间线 → 写入图谱 + 同步向量 + 故事时间线
→ [后续维护:整合/压缩/概要/反思/遗忘] → [后续维护:整合/压缩/层级总结/反思/遗忘]
``` ```
### Prompt 构建架构 ### Prompt 构建架构

View File

@@ -149,15 +149,15 @@ export const DEFAULT_NODE_SCHEMA = [
// ====== v2 新增节点类型 ====== // ====== v2 新增节点类型 ======
{ {
id: "synopsis", id: "synopsis",
label: "全局概要", label: "全局概要(旧)",
tableName: "synopsis_table", tableName: "synopsis_table",
columns: [ columns: [
{ {
name: "summary", name: "summary",
hint: "当前故事的全局概要(前情提要", hint: "旧式单条全局前情提要(兼容 / 迁移兜底",
required: true, required: true,
}, },
{ name: "scope", hint: "概要覆盖的楼层范围", required: false }, { name: "scope", hint: "该旧式概要覆盖的楼层范围", required: false },
], ],
alwaysInject: true, // 常驻注入MemoRAG 启发) alwaysInject: true, // 常驻注入MemoRAG 启发)
latestOnly: true, // 只保留最新版本 latestOnly: true, // 只保留最新版本

View File

@@ -11041,7 +11041,7 @@ async function handleExtractionSuccess(
typeof runHierarchicalSummaryPostProcess === "function" typeof runHierarchicalSummaryPostProcess === "function"
? "层级总结" ? "层级总结"
: typeof generateSynopsis === "function" : typeof generateSynopsis === "function"
? "概要生成" ? "旧式全局概要生成"
: "层级总结"; : "层级总结";
const cloneMaintenanceSnapshot = const cloneMaintenanceSnapshot =
typeof cloneGraphSnapshot === "function" typeof cloneGraphSnapshot === "function"
@@ -11163,9 +11163,9 @@ async function handleExtractionSuccess(
? getContext().chat ? getContext().chat
: []; : [];
updateExtractionPostProcessStatus( updateExtractionPostProcessStatus(
summaryStageLabel === "概要生成" ? "概要更新中" : "层级总结处理中", summaryStageLabel === "旧式全局概要生成" ? "旧式全局概要更新中" : "层级总结处理中",
summaryStageLabel === "概要生成" summaryStageLabel === "旧式全局概要生成"
? `${extractionCount} 次提取,正在生成全局概要` ? `${extractionCount} 次提取,正在生成旧式全局概要`
: `${extractionCount} 次提取,正在检查小总结与折叠总结`, : `${extractionCount} 次提取,正在检查小总结与折叠总结`,
); );
const summaryResult = await runSummaryPostProcess({ const summaryResult = await runSummaryPostProcess({

View File

@@ -8,7 +8,7 @@ const DEFAULT_TYPE_LABELS = Object.freeze({
location: "地点", location: "地点",
rule: "规则", rule: "规则",
thread: "主线", thread: "主线",
synopsis: "全局概要", synopsis: "全局概要(旧)",
reflection: "反思", reflection: "反思",
pov_memory: "主观记忆", pov_memory: "主观记忆",
}); });

View File

@@ -26,8 +26,8 @@ const TASK_TYPE_META = {
description: "合并并压缩高层节点内容。", description: "合并并压缩高层节点内容。",
}, },
synopsis: { synopsis: {
label: "概要", label: "小总结",
description: "生成阶段性的全局剧情提要。", description: "基于近期原文窗口生成阶段性小总结。",
}, },
summary_rollup: { summary_rollup: {
label: "总结折叠", label: "总结折叠",

View File

@@ -225,7 +225,7 @@ const schema = [
}, },
{ {
id: "synopsis", id: "synopsis",
label: "概要", label: "全局概要(旧)",
columns: [{ name: "summary" }, { name: "scope" }], columns: [{ name: "summary" }, { name: "scope" }],
}, },
]; ];
@@ -2108,10 +2108,10 @@ async function testConsolidatorMergeFallbackKeepsNodeWhenTargetMissing() {
const restoreOverrides = pushTestOverrides({ const restoreOverrides = pushTestOverrides({
embedding: { embedding: {
async embedBatch() { async embedBatch() {
return [[0.2, 0.3]]; return [[0.4, 0.5]];
}, },
async embedText() { async embedText() {
return [0.2, 0.3]; return [0.4, 0.5];
}, },
searchSimilar() { searchSimilar() {
return [{ nodeId: target.id, score: 0.99 }]; return [{ nodeId: target.id, score: 0.99 }];
@@ -2600,7 +2600,7 @@ async function testReverseJournalRollbackStateFormsReplayClosure() {
const journal = createBatchJournalEntry(before, after, { const journal = createBatchJournalEntry(before, after, {
processedRange: [4, 6], processedRange: [4, 6],
extractionCountBefore: before.historyState.extractionCount, vectorHashesInserted: ["hash_added"],
}); });
const runtimeGraph = normalizeGraphRuntimeState( const runtimeGraph = normalizeGraphRuntimeState(
@@ -2818,7 +2818,7 @@ async function testBatchStatusSemanticFailureDoesNotHideCoreSuccess() {
assert.equal(effects.batchStatus.stages.finalize.outcome, "success"); assert.equal(effects.batchStatus.stages.finalize.outcome, "success");
assert.equal(effects.batchStatus.outcome, "failed"); assert.equal(effects.batchStatus.outcome, "failed");
assert.equal(effects.batchStatus.completed, true); assert.equal(effects.batchStatus.completed, true);
assert.match(effects.batchStatus.errors[0], /概要生成失败/); assert.match(effects.batchStatus.errors[0], /旧式全局概要生成失败/);
} }
async function testExtractionPostProcessStatusesExposeMaintenancePhases() { async function testExtractionPostProcessStatusesExposeMaintenancePhases() {
@@ -2881,7 +2881,7 @@ async function testExtractionPostProcessStatusesExposeMaintenancePhases() {
const statusTexts = harness.extractionStatuses.map((entry) => entry[0]); const statusTexts = harness.extractionStatuses.map((entry) => entry[0]);
assert.ok(statusTexts.includes("提取收尾中")); assert.ok(statusTexts.includes("提取收尾中"));
assert.ok(statusTexts.includes("整合/进化中")); assert.ok(statusTexts.includes("整合/进化中"));
assert.ok(statusTexts.includes("概要更新中")); assert.ok(statusTexts.includes("旧式全局概要更新中"));
assert.ok(statusTexts.includes("反思生成中")); assert.ok(statusTexts.includes("反思生成中"));
assert.ok(statusTexts.includes("主动遗忘中")); assert.ok(statusTexts.includes("主动遗忘中"));
assert.ok(statusTexts.includes("自动压缩中")); assert.ok(statusTexts.includes("自动压缩中"));

View File

@@ -291,12 +291,11 @@
<option value="scope:characterPov">角色 POV</option> <option value="scope:characterPov">角色 POV</option>
<option value="scope:userPov">用户 POV</option> <option value="scope:userPov">用户 POV</option>
<option value="pov_memory">主观记忆</option> <option value="pov_memory">主观记忆</option>
<option value="character">角色</option>
<option value="event">事件</option> <option value="event">事件</option>
<option value="location">地点</option> <option value="location">地点</option>
<option value="thread">线索</option> <option value="thread">线索</option>
<option value="rule">规则</option> <option value="rule">规则</option>
<option value="synopsis">概要</option> <option value="synopsis">全局概要(旧)</option>
<option value="reflection">反思</option> <option value="reflection">反思</option>
</select> </select>
</div> </div>

View File

@@ -3163,7 +3163,7 @@ function _buildLegend() {
{ key: "location", label: "地点" }, { key: "location", label: "地点" },
{ key: "thread", label: "主线" }, { key: "thread", label: "主线" },
{ key: "rule", label: "规则" }, { key: "rule", label: "规则" },
{ key: "synopsis", label: "概要" }, { key: "synopsis", label: "全局概要(旧)" },
{ key: "reflection", label: "反思" }, { key: "reflection", label: "反思" },
{ key: "pov_memory", label: "主观记忆" }, { key: "pov_memory", label: "主观记忆" },
]; ];
@@ -10783,7 +10783,7 @@ function _typeLabel(type) {
location: "地点", location: "地点",
thread: "主线", thread: "主线",
rule: "规则", rule: "规则",
synopsis: "概要", synopsis: "全局概要(旧)",
reflection: "反思", reflection: "反思",
pov_memory: "主观记忆", pov_memory: "主观记忆",
}; };