Skip to content

記憶圖

記憶圖(Memory Graph)解決長跑 RP 裡最常見的一個痛點:角色失憶

LLM 的上下文視窗是有限的。聊到幾百輪以後,早期的重要資訊——人物關係、關鍵事件、世界規則——會被截斷丟掉。角色就「忘了」之前發生的事。記憶圖把對話裡的關鍵資訊自動抽成結構化的知識節點,需要時再召回注入回 prompt——讓角色能像你一樣,記住 500 輪前發生的事情。

它不是簡單的關鍵詞搜尋或純向量檢索。記憶圖用圖結構和多層演算法,讓召回既語意相關覆蓋全面——不會出現「只把最相似的五條拉出來,其他都丟了」的情況。

它怎麼工作

記憶圖後台跑三件事:自動提取智慧召回分層壓縮

自動提取

每次 AI 回覆後,記憶圖分析對話內容,把值得記住的東西提取出來,產出結構化的知識節點。提取可以走兩條通道:

內建提取 —— 當記憶面板裡的 自動抽取 開關打開時,記憶圖在每次 AI 回覆後自己跑一次 LLM 呼叫,把 schema 裡的結構化欄位填出來。這是預設方式,不依賴任何其他擴展。

編排器驅動的提取 —— 當編排器擴展已安裝,且導演模式使用預設配置時,主 agent 在每次起草回覆後會調度一個 memory_curator 子 agent。memory_curator 跑多輪「觀察—執行」迴圈,先用記憶圖的唯讀工具確認現狀,再寫入。對像角色這類穩定事實節點,品質通常更高 —— agent 會先查是否已有同名角色,而不是直接新建出重複節點。

兩條通道可以同時開,它們彼此並不協調,等於用額外的 LLM 成本換取一層兜底。多數使用者只會留一條。

只走編排器驅動的提取:

  1. 打開記憶面板,把 自動抽取 關掉。
  2. 在編排器配置編輯器裡確認 memory_curator 已啟用,並且由主 agent 調度(新裝預設就是這樣)。

節點分兩層。預設 schema 自帶下面這三種類型,但 schema 是完全可定制的。你可以新增節點類型(奇幻題材加 magic_system,政治題材加 faction,生存題材加 inventory_item,看你的卡需要什麼),也可以移除任何預設類型。下面欄位也是預設值,每種類型的欄位可以在 Schema 編輯器裡改(下面會講到)。

語意層節點(持久化結構化知識,合併和更新):

類型說明例子
character_sheet角色的姓名、身份、性格、目標、隨身物品「Eileen 是治癒師,認下了對主角的一份恩情」
location_state地點的名稱、控制者、危險度、資源「黑暗森林由精靈控制,危險度高」

事件層節點(情節記錄,每次提取新建,從不合併):

類型說明例子
event發生過的重要事件「主角在森林中遭遇伏擊」

事件節點不一樣

事件節點和其他類型有本質區別:

  • 每次提取都新建節點。 標題自動遞增。事件是時間軸上獨立的點,不像角色狀態那樣合併到現有節點
  • 最高層時間線總是注入。 事件節點是核心劇情上下文——最高層級的總結永遠在 prompt 裡,確保 AI 始終把握劇情走向
  • 被壓縮的低層事件隱藏。 事件累積太多時,舊事件向上壓縮成更高層的總結。低層事件依然在圖裡,需要時召回機制能再發現它們,但預設不持久注入

簡單說:AI 始終能看到「大事」(最高層總結),具體細節只在對話需要時召回補充。

可以透過 提取間隔 控制提取頻率——比如設為 2 表示每 2 次 AI 回覆才觸發一次提取,LLM 呼叫成本減半。

智慧召回

你發新訊息觸發 AI 生成時,記憶圖根據當前對話上下文,從累積的記憶中召回最相關的節點,注入 prompt 供 AI 參考。

召回方式說明
LLM 召回讓 LLM 直接從記憶庫裡挑相關節點,支援多輪深度探索
Hybrid 召回結合向量檢索、圖擴散、詞法匹配等多維信號綜合打分
Hybrid + Reranking在 Hybrid 基礎上用重排模型進一步最佳化
Hybrid + LLM在 Hybrid 候選基礎上讓 LLM 二次過濾

選哪個?

LLM 召回是預設的,因為最容易配 —— 你的主對話已經有 LLM API,這就夠用了。

Hybrid 召回更快、更貼近生產級檢索系統的玩法(向量檢索 + 圖擴散),但需要先在 Vector Storage 擴展裡配好嵌入(embedding)模型。想要更好的效果,可以疊一個重排模型(Hybrid+Rerank),或者再疊一道 LLM 過濾(Hybrid+LLM)。

經驗法則:剛開始用就 LLM 召回,等碰到成本或延遲瓶頸、或者想讓召回結果在換模型後保持穩定時,再切到 Hybrid。

分層壓縮

隨著對話推進,事件記憶持續累積。記憶圖自動對老事件做向上壓縮——多個相關事件合併為更高層的總結節點,既保留核心資訊又控制總記憶體積。

壓縮是遞迴的。某層的總結節點也超閾值時,繼續向上壓縮,直到節點數降到閾值以下。例如多個戰鬥事件先壓成「森林戰役」,多場戰役再壓成「北征之戰」。壓縮後的總結節點仍可展開看原始子事件。

和提取類似,壓縮也有兩條通道:

內建壓縮 —— 當記憶面板裡的 自動壓縮 開關打開時,葉子層事件累積到閾值後,記憶圖跑一次性的 LLM 總結呼叫。

編排器驅動的壓縮 —— memory_curator 在提取之後會評估 memory_compaction_candidates,然後用 KEEP/FOLD/DROP 風格的總結呼叫 memory_compact_nodes。多輪 agent 可以一個 rollup 一個 rollup 反覆迭代,而內建路徑是一次性的。

它實際長什麼樣

讀到這兒大多數讀者都想知道一個具體問題:節點到底長什麼樣?來個真實例子。

假設你和 Eileen(一個治癒師 NPC)有這樣三輪對話:

You: 我把找到的傷藥遞給 Eileen。

Eileen: ...謝謝。但你確定要給我?這種東西在外面很值錢。

You: 你傷得比我重。再說,我們是朋友吧。

Eileen: ...嗯。是朋友。這個恩情我會記著的。

這一輪後,記憶圖在後台跑一次提取,產生這樣的結構化節點:

json
{
  "id": "n_eileen",
  "type": "character_sheet",
  "level": "semantic",
  "title": "Eileen",
  "fields": {
    "aliases": "",
    "traits": "話不多,字斟句酌,即使道謝也很克制",
    "identity": "在北境遇到的旅行治癒師",
    "goal": "還這份恩情;傷好到能自己走路",
    "inventory": "傷藥(剛收下)、輕便行囊",
    "language_sample": "...謝謝。但你確定要給我?",
    "addressing_user": "稱呼用名字,中間常有停頓"
  },
  "floor": 12
}
json
{
  "id": "evt_20260505_001",
  "type": "event",
  "level": "semantic",
  "title": "Summary 1",
  "fields": {
    "summary": "时间:Day 12, late afternoon; 使用者把找到的傷藥遞給受傷的 Eileen,Eileen 接受並明確認下了朋友關係和這份恩情。"
  },
  "floor": 12
}

這就是預設 schema 的欄位

上面例子裡的欄位(character_sheet 用的 aliases / traits / identity / goal / inventory / language_sample / addressing_userevent 用的 summary)就是預設表的真實列。Schema 編輯器裡可以改名、刪除,或者乾脆加新類型。

記憶圖的面板裡你能看到所有節點,可以是圖,也可以是表格:

Memory graph 視圖

Memory 表格視圖

點任意節點看完整欄位:

單個節點詳情

50 輪後,你說「對了 Eileen,你之前說欠我一個人情......」。記憶圖召回機制把這兩個節點(以及其他相關的)挑出來,在主模型生成回覆之前注入 prompt 的 SYSTEM 部分:

Recent injection 視圖

這就是記憶圖在做的事——它不讓 AI 忘掉那種「50 輪前的小事到 50 輪後突然變成關鍵」。

5 分鐘跑起來

Step 1 — 啟用

打開 擴展 抽屜 → 記憶 → 把 啟用 開關打開。

Memory 開關與預設

Step 2 — 給提取和召回選模型

記憶圖的提取和召回都要 LLM 呼叫,但不必和主對話用同一個模型。在同一面板設:

設定說明
召回 API 預設召回的 API 連接
召回提示詞預設召回的 Chat Completion 預設
生成圖 API 預設提取的 API 連接
生成圖提示詞預設提取的 Chat Completion 預設

常見配法:主對話走 Claude Opus,記憶圖走 Haiku 或 Gemini Flash。提取做的是結構化欄位填充,不是寫文,小模型能處理,而且確實省錢。

Step 3 — 正常聊天

記憶圖自動運行。聊幾輪,內容裡包含一些值得記住的角色 / 事件 / 地點。

Step 4 — 看效果

3-5 輪後打開 Memory 面板:

  • Graph 視圖——節點關係圖
  • Nodes 表格——按類型展示節點結構化欄位
  • Recall 視圖——最近一次注入到 prompt 裡的內容

如果什麼都沒看到,在聊天裡多帶幾個角色或事件——提取需要具體的東西可抓。

我想要……

常見問題,從「普遍」到「小眾」:

我想讓我的奇幻卡記住魔法體系 / 派系

記憶圖的節點類型可以自定義。在 Memory 面板點 打開 Schema 編輯器 加新類型:

Schema 編輯器

例如加一個 magic_system 類型(欄位:name / source / restrictions),或一個 faction 類型(欄位:name / leader / goals)。自定義類型保存在角色卡裡,匯出時隨卡走——你的奇幻世界詞彙隨卡傳遞。

每種類型還帶兩個提取控制欄位:

  • 提取指令 —— 一段自由文本,僅當本類型本輪啟用時才會附加到提取系統提示詞。類型專屬規則(如「每批次最多一個 event」、「角色一定填 aliases」)寫在這裡,而不是塞進 base prompt。留空 = 無類型專屬附加段。
  • 每 N 層提取一次 —— 節奏控制。1(預設)表示每次提取都包含該類型。設為 2/3/5 等,僅當 currentSeq % N == 0 時啟用,適合 location_state 這種慢變化表,降低提取頻率、省 LLM 呼叫。某類型本輪未啟用時,其 create/edit/delete 工具不會暴露給模型,指令也不會附加 —— 模型這輪根本無法產出該表。

我想讓某些記憶 始終 在 prompt 裡(不等召回)

那是 持久注入。把某些節點類型設為持久注入——它們無論召回觸發與否都出現在 prompt 裡。常見用法:如果你加一個 rule_constraintworld_law 類型來表達不可違反的世界規則,把它標為持久——主模型就永遠不會忘掉這些規則。

持久注入和召回是互斥的(節點級)

持久注入的節點會從召回池裡完全排除——它已經每回合都在 prompt 裡了,運行時直接 bypass 掉它的召回。

我編輯 / 刪除訊息——記憶會怎麼變?

記憶圖有完整的變更回滾機制。你編輯、刪除訊息或 swipe 時,記憶自動回滾到受影響訊息之前的狀態,保持記憶和聊天歷史一致。

我想換電腦用 / 分享給別人

JSON 匯入匯出。

模式作用
Restore 還原保留匯出時的樓層號——同一聊天恢復資料用
綁定到最新樓層所有匯入節點綁到當前最新 AI 回覆樓層。

實用技巧:開一個全新的聊天,把過去某段長跑的記憶匯入進來,從 0 樓重新開始。等於「開新檔,但之前長跑裡累積的世界觀、角色、故事全在你腦子裡」——你可以續寫、換主線、換設定再玩一遍。
綁定到指定樓層你手動輸入目標樓層

記憶怎麼進 prompt

兩條通道,節點級互斥

持久注入——某些節點類型總在 prompt 裡。適合基線資訊:世界規則、人設核心設定、那種永遠不該忘的東西。在 Schema 編輯器裡按類型配置(alwaysInject 旗標)。持久節點會被從召回池裡排除——它每回合都在,不需要再被「召回」一遍。

召回注入——其他節點類型由召回機制動態注入,只有和當前對話相關的記憶才進 prompt,不浪費上下文空間。

底層實作:世界書投射

這兩條通道實際上都是把節點投射成世界書條目的方式工作的。持久注入寫持久世界書條目;召回注入寫臨時條目(生成完自動清理)。這意味著記憶條目會遵守世界書的關鍵詞掃描、深度排序等機制。這不是配置項,而是工作方式。

召回注入有自己的位置設定:

設定預設說明
召回注入位置atDepth注入位置
召回注入深度9999注入深度
召回注入角色SYSTEMSYSTEM / USER / ASSISTANT

結果複用

同一樓層 swipe 或重生成時,記憶圖會複用上次召回結果而不是重跑。省 LLM 成本,保證同一回合記憶上下文一致。

配置參考

完整配置列表

基礎配置

設定預設說明
啟用記憶圖false總開關
提取間隔1每 N 次 AI 回覆觸發一次提取
最大處理輪數900處理輪數硬上限

向量與擴散

設定預設說明
嵌入檔案(空)Connection Manager 裡的 embed-profile,記錄嵌入 Provider/模型/Endpoint/Key。可在記憶圖設定或向量儲存裡建立,多外掛共享。
向量 Top-K20向量檢索 Top-K
圖擴散步數2擴散步數
圖擴散衰減0.6衰減係數
圖擴散 Top-K100擴散後 Top-K
圖擴散傳送機率0.0傳送機率

重排

設定預設說明
啟用重排false是否重排
重排檔案(空)Connection Manager 裡的 rerank-profile,定義重排 Provider/模型/Endpoint/Key。與向量儲存共享。

其他

設定預設說明
RPM 限制0每分鐘請求數(0 = 不限)
LLM 可見最近訊息數5召回 LLM 能看到的最近訊息數
與預設一起包含世界書true用預設時是否包含世界書
覆寫世界書名稱(空)覆寫投射的世界書名
世界書條目排序基數9800投射條目的基礎排序值
工具呼叫最大重試2工具呼叫失敗重試次數
排除最近 N 輪的節點0召回時排除最近 N 輪的節點(0 = 不排除)

技術深入

給好奇的讀者和貢獻者

多階段混合召回管道

Hybrid 模式下,記憶圖跑一個 8 階段管道:

  1. 向量預篩——從向量庫取最相似的 Top-K 節點
  2. 實體錨定——在查詢裡匹配已知實體名和別名
  3. 建種子——合併向量命中和實體錨作為擴散起點
  4. 建鄰接表——構造圖的雙層鄰接表
  5. PEDSA 圖擴散——從種子節點出發,通過圖結構傳播能量,發現間接相關記憶
  6. 混合打分——融合向量分、擴散能量、詞法匹配、錨分、新近度加成等多維信號
  7. 認知層(NMF / FISTA / DPP)——三種演算法保證召回既全面又多樣
  8. 可選重排——外部重排器最終排序

認知層演算法

  • NMF 主題再平衡 —— 用非負矩陣分解識別欠覆蓋的主題方向,提升代表性節點的得分
  • FISTA 殘差發現 —— 用快速迭代收縮閾值演算法發現查詢中候選集未覆蓋的語意方向,補充檢索
  • DPP 多樣性採樣 —— 用行列式點過程從候選中選出高品質且互相多樣的子集,避免召回過於集中

PEDSA 圖擴散

PEDSA(Personalized Efficient Diffusion with Sparse Approximation)讓記憶圖能發現那些和查詢沒有直接語意關聯,但通過圖結構間接相關的重要記憶。能量從種子節點沿邊傳播多輪,支援傳送機率(類似 PageRank)和稀疏近似控制。

向量索引

記憶圖用增量更新策略管理向量嵌入——通過雜湊比對檢測節點內容變化,只有內容真的變了才重新生成嵌入向量。Hybrid 召回裡使用記憶圖設定中選定的嵌入檔案作為單一事實源,Provider/模型/Endpoint/Secret 全部從檔案讀取。向量儲存外掛從同一份 Connection-Manager 檔案庫讀取,兩個外掛可以共用一份檔案,也可以各自挑不同的檔案,不再依賴對方的私有 extension_settings

插入向量時,記憶圖把 nodeId 放在 metadata 欄位裡。後端原樣存 metadata。其他外掛也可以用 metadata 欄位存自定義資料,查詢結果會一併返回。這種設計讓 hash → nodeId 映射可以繞開前端索引快取——即使快取丟了,也能從查詢結果直接匹配節點。

如需手動控制,記憶圖設定面板提供重算向量索引按鈕。點擊後彈出對話框,提供兩種模式:增量補全僅對向量缺失或失效(如節點編輯後)的節點重新生成 embedding;全部重算清空集合並對所有可索引節點重新生成 embedding(更換嵌入模型或檔案後用此項)。如果嵌入設定已變更,增量補全會自動升級為全部重算,因為舊向量與新空間不相容。失敗的節點記錄到主控台,不阻斷整體流程。

自動 schema 遷移

載入聊天時,記憶圖運行遷移管道,把舊的持久化形態(v5 raw,v8 opLog)轉換為當前的 v2 樓層狀態佈局(graph payload + __floor_log 提交日誌 + __meta 狀態)。管道冪等,只在輸入形態不是 v2 時運行,任何步驟失敗時絕不修改 chat-state。

更多實作細節請看原始碼。

相關頁面

基於 SillyTavern 建構