2026-04-04 02:56:04 +08:00
2026-04-04 02:56:04 +08:00
2026-04-04 02:56:04 +08:00
2026-04-04 02:56:04 +08:00
2026-04-03 22:16:23 +08:00
2026-03-23 22:18:36 +08:00

🧠 ST-BME — SillyTavern 图谱记忆插件

让 AI 真正记住你们的故事。

ST-BME 把对话中散落的角色、事件、地点、关系自动提取为记忆图谱,在下一轮生成前精准召回,让长期 RP 的角色不再"失忆"。


它能做什么

  • 🧩 自动提取 — 每次 AI 回复后,从上下文中抽取角色状态、事件、地点、规则、主线等结构化记忆
  • 🔍 智能召回 — 生成前根据当前对话自动检索最相关的记忆,注入 prompt
  • 🌐 图谱可视化 — 内置力导向图谱面板,直观查看记忆节点之间的关系
  • 🎨 4 套配色主题 — Crimson Synth / Neon Cyan / Amber Console / Violet Haze
  • 📱 手机端适配 — 底部 Tab Bar + 精简布局,手机也能用
  • 🔄 历史安全 — 删楼、编辑、切 swipe 时自动回滚恢复,不留脏记忆
  • 📦 不改酒馆本体 — 纯第三方扩展,即装即用

🧭 它是怎么工作的

整个插件可以拆成三件事:写入(把对话变成记忆)、读取(把记忆送回给 AI安全(出了问题能恢复)。

flowchart LR
    subgraph 写入["✏️ 写入:对话 → 记忆"]
        A["AI 回复了一条消息"] --> B["提取器读取最近几轮对话"]
        B --> C["让 LLM 识别出角色/事件/地点等"]
        C --> D["对比已有记忆,去重或更新"]
        D --> E["写入图谱 + 同步向量"]
    end

    subgraph 读取["🔍 读取:记忆 → 注入"]
        F["用户准备发送下一条"] --> G["用向量搜索找相关记忆"]
        G --> H["沿关系网络扩散,发现关联"]
        H --> I["综合打分排序"]
        I --> J["格式化后注入 prompt"]
    end

    subgraph 安全["🛡️ 安全:历史变动 → 恢复"]
        K["用户删楼/编辑/切 swipe"] --> L["检测到哪些楼层变了"]
        L --> M["回滚受影响的记忆和向量"]
        M --> N["从变动点重新提取"]
    end

    E -.-> F
    N -.-> E

写入阶段(对话 → 记忆)

每次 AI 回复后,插件会把最近几轮对话打包发给 LLM可以是你聊天用的同一个模型也可以单独配一个让它识别出"这段对话里出现了哪些角色、发生了什么事、在哪里、有什么新规则"等等。

识别出来的结果不是直接塞进去——插件会先跟已有记忆做对比(通过向量搜索找相似的),如果已经有了就更新,如果是真正的新内容才创建。

写入之后,还可能触发一些后续处理:

  • 压缩 — 太多类似的事件记忆会被合并
  • 进化 — 新信息会影响旧记忆的理解(比如"原来他当时是在演戏"
  • 概要 — 自动生成"之前发生了什么"的总结
  • 遗忘 — 很久没被用到的记忆降低优先级

读取阶段(记忆 → 注入)

当你准备发送下一条消息时,插件会抢在 AI 生成之前做一轮"召回"

  1. 向量搜索 — 根据当前对话内容,用 Embedding 找到语义最相关的记忆
  2. 图扩散 — 找到相关记忆后,沿着关系往外扩散(比如某个角色参与了某个事件,那个事件发生在某个地点...
  3. 混合评分 — 把向量相似度、图扩散能量、节点重要性、时间新旧综合排序
  4. 格式化注入 — 选出最终入围的记忆,分类整理后注入到 prompt 里

注入的内容分成两层:

  • 常驻层 — 规则、概要、主线这类始终需要的
  • 动态层 — 根据当前对话语境召回的

安全机制(历史变动 → 恢复)

这是很多记忆插件忽略的问题:如果用户删了某条消息、编辑了内容、或者切了 swipe已经基于那条消息提取的记忆就变成"脏"的了。

ST-BME 的处理方式是:

  1. 给每条已处理的消息计算 hash指纹
  2. 发现 hash 变了 → 找到最早受影响的位置
  3. 把那之后产生的记忆和向量全部回滚
  4. 从变动点重新走一遍提取流程

如果恢复日志损坏了,会退化为全量重建——慢一点但保证正确。


🚀 安装

方法一:通过 SillyTavern 扩展安装

  1. 打开 SillyTavern → 扩展 → 安装扩展
  2. 输入仓库地址:
    https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology
    
    注意:请粘贴仓库根地址,不要使用像 /graphs/code-frequency 这样的 GitHub 子页面地址。
  3. 刷新页面

方法二:手动安装

cd SillyTavern/data/default-user/extensions/third-party
git clone https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git st-bme

重启 SillyTavern 即可。


快速上手

  1. 打开面板 — 左上角 ≡ 菜单 →「🧠 记忆图谱」
  2. 启用插件 — 进入面板的「配置 → 功能开关」,打开 ST-BME 自动记忆
  3. 配置 Embedding — 进入「配置 → API 配置」,选择向量模式并填好模型
  4. 开始聊天 — 正常跟角色对话,插件会自动在后台提取和召回

最少配置: 只勾选"启用"就能跑起来。默认会复用你当前的聊天模型做提取。


📝 记忆类型

插件会把对话拆解成以下几种记忆节点:

类型 说明 举例
🧑 角色 角色的当前状态、性格、外貌变化 "小明因为淋雨感冒了"
事件 发生过的事 "河边的告白"
📍 地点 地点状态 "废弃实验室,门被锁上了"
📌 规则 世界观设定、约束 "魔法会消耗生命力"
🧵 主线 任务线/剧情线 "寻找失踪的项链"
📜 概要 自动生成的前情提要
💭 反思 长期规律总结 "他们经常在夕阳下聊天"

这些节点之间还会建立关系(参与、发生在、推动、矛盾、更新等),形成一张完整的记忆网络。


🔧 设置说明

记忆 LLM

用来做提取、压缩、进化、概要等任务的模型。

  • 留空 → 复用当前 SillyTavern 的聊天模型(最简配置)
  • 填写 → 你可以指定一个独立的 OpenAI-compatible 模型专门处理记忆

Embedding向量搜索

向量搜索是"智能召回"的关键。支持两种模式:

后端模式(推荐)

走 SillyTavern 后端的向量 API最稳定

  • 支持 OpenAI / Cohere / Mistral / Ollama / LlamaCpp / vLLM 等
  • 在设置面板选择「后端向量源」,填好模型名即可
  • 不需要单独填 API Key复用酒馆已有的

直连模式

如果你需要完全独立的 Embedding 服务(比如酒馆后端不支持的源):

  • 填入 Embedding API 地址、Key、Model
  • 插件直接请求你的 Embedding 服务
  • 注意浏览器跨域问题CORS

切换向量模式/模型后,建议点一次"重建向量"。

提取设置

设置 默认 说明
每 N 条回复提取 1 每几条 AI 回复做一次提取
提取上下文轮数 2 提取时向前看几轮对话
启用近邻对照 写入前对比现有记忆,避免重复
启用记忆进化 新记忆会影响旧记忆理解
启用自动概要 定期生成前情提要
启用反思 让 AI 总结长期模式
启用主动遗忘 太久没用的记忆降低优先级

召回设置

设置 默认 说明
提取上下文轮数 2 按轮计的提取上下文,通常约等于向前补 4 层普通消息
向量预筛 Top-K 20 向量预筛阶段最多保留多少个候选
LLM 精排候选池 30 进入 LLM 精排阶段前的候选池大小
LLM 最终选择上限 8 LLM 精排后最多保留多少条记忆
图扩散 Top-K 100 图扩散阶段最多保留多少个候选
注入深度 9999 当前走 IN_CHAT@Depth数值越大越靠前插入
Token 估算 注入内容的 token 估算(仅用于展示,当前版本不强制裁剪)

🖥️ 操控面板

从左上角 ≡ 菜单点「🧠 记忆图谱」打开面板。

总览 Tab

  • 统计数据(活跃节点、边、归档数、碎片率)
  • 运行状态(聊天 ID、向量状态、历史状态
  • 最近提取 / 召回的记忆

记忆 Tab

  • 搜索和筛选记忆节点
  • 点击节点查看详情
  • 支持按类型过滤

注入 Tab

  • 预览当前注入内容
  • 查看 token 消耗

操作 Tab

  • 手动提取 — 立即从当前对话提取
  • 手动压缩 — 合并重复/过时记忆
  • 执行遗忘 — 主动降级低价值记忆
  • 更新概要 — 重新生成前情提要
  • 导出 / 导入图谱
  • 重建图谱 — 从当前聊天重新提取全部记忆
  • 重建向量 — 重建全部向量索引
  • 强制进化 — 让新记忆影响旧记忆

配置 Tab

配置页现在是一个完整的工作区,分成 5 个子页:

  • API 配置
  • 功能开关
  • 详细参数
  • 系统提示词
  • 面板外观

桌面端会显示左侧竖向子导航,右侧显示宽版配置表单;移动端则改成顶部横向子页切换。 检索流水线现在可以分别配置向量预筛、图扩散、混合评分和 LLM 精排。 注入深度使用 IN_CHAT@Depth 语义,默认 9999 表示尽量靠前插入,减少对最近几层对话的直接控制感。

图谱可视化

桌面端右侧大区域显示力导向图谱,节点可拖拽、缩放、点击查看详情。支持 4 套配色主题切换。


🔄 历史安全

这是最重要的功能之一。

当你在 SillyTavern 里做以下操作时:

  • 删除某条消息
  • 编辑某条消息
  • 切换 swipe

插件会自动检测到历史发生了变化,然后:

  1. 止损 — 停止当前推进,清空可能失效的注入
  2. 回滚 — 找到受影响的批次,删除相关记忆和向量
  3. 恢复 — 从变动点重新提取

这样你就不用担心"改了历史但记忆还留着错的内容"的问题。


📋 手动操作速查

操作 说明
手动提取 不等自动触发,立刻提取当前对话
手动压缩 把重复/冗余的事件合并
执行遗忘 降低长期未使用记忆的优先级
更新概要 重新生成全局前情提要
导出图谱 下载当前图谱 JSON不含向量
导入图谱 导入图谱文件(导入后需重建向量)
重建图谱 ⚠️ 清空现有图谱,从聊天记录重新提取
重建向量 重建全部节点的向量索引
范围重建向量 只重建指定楼层范围内的向量
强制进化 让新记忆深度影响旧记忆认知

🏗️ 开发者参考

文件结构

ST-BME/
├── index.js           # 主入口:事件绑定、流程调度、历史恢复
├── bme-db.js          # IndexedDB(Dexie) 持久化层(本地主存储)
├── bme-sync.js        # 跨设备同步(/user/files/ 镜像 + 合并)
├── bme-chat-manager.js# chatId -> BmeDatabase 生命周期管理
├── lib/dexie.min.js   # vendored Dexie浏览器端动态注入加载
├── graph.js           # 图数据模型、序列化、版本迁移
├── extractor.js       # 记忆提取、概要、反思
├── retriever.js       # 向量候选、图扩散、混合评分、召回
├── injector.js        # 召回结果格式化注入
├── runtime-state.js   # 运行时状态:楼层 hash、dirty 标记、恢复日志
├── recall-persistence.js # 持久召回记录message.extra.bme_recall不变
├── recall-message-ui.js # 消息级召回卡片 UI子图渲染 + 侧边栏编辑,不变)
├── vector-index.js    # 向量索引管理backend / direct 双模式)
├── embedding.js       # 直连 Embedding API 封装
├── llm.js             # 记忆 LLM 请求封装
├── compressor.js      # 层级压缩与遗忘
├── diffusion.js       # 图扩散算法
├── dynamics.js        # 动态调节(重要度衰减等)
├── schema.js          # 节点类型定义
├── themes.js          # 4 套主题配色
├── graph-renderer.js  # Canvas 力导向图谱渲染器
├── panel.js           # 操控面板交互逻辑
├── panel.html         # 面板 HTML 模板
├── style.css          # 全部样式
├── manifest.json      # SillyTavern 扩展清单
└── tests/             # 测试脚本

数据存储

  • 图谱主存储(本地优先)IndexedDBDexie
    • DB 名固定:STBME_{chatId}
    • 运行时主读取路径:优先 IndexedDB
  • 跨设备同步镜像 → SillyTavern 文件 API /user/files/
    • 文件名固定:ST-BME_sync_{sanitizedChatId}.json
    • 冲突合并:updatedAt 新者胜tombstone deletedAt 优先;lastProcessedFloor/extractionCountmax
    • meta 为同步 JSON 顶层首字段,revision 全程单调递增
  • 兼容兜底(迁移窗口)chat_metadata.st_bme_graph
    • 仅用于 legacy 兼容与迁移,不再是主路径
  • 墓碑tombstones → 保留期固定 30 天
  • 插件设置 → SillyTavern 的 extension_settings.st_bme
  • 向量索引 → 后端模式走酒馆 API直连模式存在节点内
  • 召回持久注入(不变)chat[x].extra.bme_recall(消息级)

兼容迁移策略legacy metadata → IndexedDB

  • 触发:聊天加载/切换后,若目标 STBME_{chatId} 为空且存在 legacy chat_metadata 图谱
  • 行为:自动一次性迁移到 IndexedDB并立即尝试同步到 /user/files/
  • 幂等:
    • migrationCompletedAt > 0,跳过
    • 若 IndexedDB 已非空,跳过
  • 迁移记录:
    • migrationCompletedAt
    • migrationSource(默认 chat_metadata
    • legacyRetentionUntil30 天)

事件挂载

SillyTavern 事件 做什么
CHAT_CHANGED IndexedDB 优先加载 + 自动同步
GENERATION_AFTER_COMMANDS AI 回复后提取记忆
GENERATE_BEFORE_COMBINE_PROMPTS 生成前召回并注入
MESSAGE_RECEIVED 触发图谱持久化IndexedDB 主写)
删除 / 编辑 / Swipe 触发历史变动检测与恢复

召回流水线

用户输入 → 向量预筛 → 图扩散 → 混合评分 → [可选 LLM 精排] → 场景重构 → 分桶注入

注入格式

召回结果分成两层注入:

  • Core(常驻):规则、概要、主线
  • Recalled(动态):根据当前对话召回

每层内进一步按用途分桶:当前状态 / 情景事件 / 反思锚点 / 规则约束。

持久召回注入(message.extra.bme_recall

从本版本开始,召回注入支持消息级持久化,存放在对应用户楼层:

  • 路径:chat[x].extra.bme_recall
  • 主要字段:
    • version
    • injectionText
    • selectedNodeIds
    • recallInput
    • recallSource
    • hookName
    • tokenEstimate
    • createdAt / updatedAt
    • generationCount在该持久注入被实际用作生成回退时递增)
    • manuallyEdited(仅表示来源是否为人工编辑)

注入优先级(避免双重注入):

  1. 本轮有新召回成功:仅使用新召回注入(临时注入),并覆盖写入目标用户楼层的 bme_recall
  2. 本轮无新召回结果:仅从“当前生成对应的用户楼层”读取 bme_recall 作为回退注入。
  3. 两者都无:清空注入。

manuallyEdited 不参与优先级判断,不会强制覆盖系统召回。

消息级 UI

  • 带有 bme_recall 的用户消息会显示内联卡片(含用户消息 + 🧠 召回条 + 记忆数 badge
  • 显示前提:必须同时满足 用户楼层message.extra.bme_recall 存在、且 injectionText 为非空字符串。
  • 点击召回条展开,显示力导向子图(仅渲染被召回的节点和它们之间的边,复用 GraphRenderer)。
  • 子图中节点可拖拽/缩放,点击节点打开右侧边栏查看节点详情。
  • 操作按钮(展开态底部):
    • ✏️ 编辑:打开侧边栏编辑注入文本(实时 token 计数),保存后标记 manuallyEdited=true
    • 🗑 删除:二次确认(按钮变红 3s 超时重置),确认后移除持久召回记录。
    • 🔄 重新召回:重新执行召回并覆盖记录,manuallyEdited 重置为 false
  • 不再使用 prompt() / alert() / confirm() 浏览器原生对话框。
  • 当聊天 DOM 延迟插入时,插件会执行有界重试 + 短生命周期 MutationObserver 补偿,避免单次刷新错过挂载。

兼容性说明:

  • 旧聊天(无 extra 或无 bme_recall)会自动按“无持久记录”处理,不会报错。
  • Recall Card 依赖消息楼层存在稳定索引属性(如 mesid / data-mesid / data-message-id),不会再回退到 DOM 顺序猜测,以避免误挂载到错误楼层。
  • 第三方主题至少需要保留 #chat .mes 外层消息节点;卡片会优先尝试挂载到 .mes_block,其次 .mes_text 的父节点,最后回退到 .mes 根节点。
  • 若第三方主题完全移除了这些锚点或稳定索引属性,插件会选择跳过挂载并输出 [ST-BME] 调试日志,而不是静默挂到错误位置。

排障建议(数据存在但 UI 不显示时):

  1. 打开浏览器控制台,搜索 [ST-BME] Recall Card UI[ST-BME] Recall Card persist 调试日志。
  2. 确认目标楼层是否为用户消息,并检查 message.extra.bme_recall.injectionText 是否非空。
  3. 检查消息 DOM 是否仍带有稳定楼层索引属性(mesiddata-mesiddata-message-id 等)。
  4. 若使用第三方主题,确认消息节点仍包含 #chat .mes,且消息内容区域未完全移除 .mes_block / .mes_text 相关结构。
  5. 如果聊天是异步渲染的,等待一小段时间后再次观察;插件会在短时间内自动补偿重试,而不是只尝试一次。

⚠️ 已知限制

  1. 记忆质量取决于 LLM — 模型提取不准,记忆也会不准
  2. 直连模式有跨域风险 — 浏览器的 CORS 限制可能导致请求失败
  3. 后端向量仅支持酒馆已有 provider — 不在列表里的需要用直连
  4. 恢复优先正确性 — 批次日志缺失时会退化为全量重建,可能较慢

📄 License

AGPLv3 — 详见 LICENSE

Description
ST-BME(Bionic Memory Ecology)是一个 SillyTavern 第三方前端扩展。它会把长期聊天中出现的角色、事件、地点、规则、主线、反思和总结抽取成一张可视化记忆图谱,并在下一轮生成前自动召回最相关的记忆注入 prompt。
Readme AGPL-3.0 6.1 MiB
Languages
JavaScript 93.3%
HTML 3.1%
CSS 3%
Rust 0.6%