🎭 SillyTavern
角色扮演系統
📥 放什麼、放多少
🎯 什麼情境該想到我
當你「手上的設定/產品知識多到塞不進 prompt,但每一輪其實只用得到其中幾條」的時候。
⚙️ 怎麼用(步驟 / 公式)
核心想法:每條知識綁一組關鍵詞;只有最近的對話字面上提到這些詞,這條內容才被注入這一輪的 prompt。幾百條設定,每輪只付真正用到的那幾條的 token。它是「用字串比對當檢索條件的極簡 RAG」:沒有 embedding,換來的是可預測、可除錯——寫關鍵詞的人就知道它什麼時候會出現。
- 切條目:一個概念一條(一個地點、一個組織、一個產品),每條寫
key[](主關鍵詞,任一命中即觸發)+content。同義詞、暱稱都列進key[]。 - 定掃描範圍:只看最近 N 則訊息(
scanDepth),不是整段歷史——否則很久以前提過一次的東西會永遠常駐。 - 加條件,擋誤觸:主鍵命中後再看次要鍵——
AND_ANY(「龍」+「火」或「巢穴」)、NOT_ANY(「國王」但不是在講「棋局」)。 - 允許連鎖,但要設閘:被激活條目的內容也加進掃描範圍再掃一次(「睡龍酒館」的內容提到「龍」→ 帶出「龍」的條目),直到沒有新激活。「總綱」型條目關掉遞迴,避免一條帶出一串。
- 同類互斥:天氣「晴/雨/雪」放同一組,同時命中只留一條。
- 時間效果:
sticky(提到後持續 N 輪,事件不會下一句就忘)、cooldown(激活後休息 N 輪,防洗版)、delay(前 N 則訊息不檢測,劇情設定別太早冒出來)。 - 給獨立預算:
知識預算 = max_context × 百分比(SillyTavern 預設 25%,8192 × 25% = 2048 tokens)。逐條累計,超過就不再激活。不設上限的話,知識會直接吃掉聊天記錄的空間(見 工具-長對話的Token預算分配)。 - 決定放哪:背景知識放 prompt 前段(穩定但離生成點遠);會改變行為的指引放聊天歷史的指定深度(離生成點近、影響大,見 工具-用深度注入讓指令不被遺忘)。
和向量 RAG 怎麼選
| 關鍵字觸發 | 向量召回(工具-RAG檢索增強生成) | |
|---|---|---|
| 命中條件 | 真的出現那個詞 | 意思相近就會命中 |
| 可預測性 | 高,作者可控 | 低,要調門檻 |
| 漏觸發 | 換個說法就漏(「會噴火的大蜥蜴」不會命中「龍」) | 少 |
| 誤觸發 | 字面巧合(要靠次要鍵擋) | 語意相近但不相干 |
| 成本 | 字串比對,幾乎免費 | 要 embedding、索引 |
實務上兩者疊用:關鍵字當主力,重要條目再加語意觸發補漏(SillyTavern 的 vectorized=true 就是這樣做)。
機制細節(六層過濾、掃描狀態機、8 種注入位置)→ World Info世界書
🧪 我實際套用的紀錄
- (尚無)
⚠️ 注意 / 什麼時候不適用
(以下為經驗推論,原文只描述機制)
- 不懂語意:使用者換個說法就漏;同義詞要自己列,或疊一層向量召回。
- 遞迴會連鎖爆量:寫得太廣的條目會帶出一大串,把預算吃光。
- 機率激活、加權隨機會讓輸出不可重現,除錯時先關掉。
- 知識量小到整份放進 prompt 也不貴時,不需要這套——每一層條件都是之後要維護的規則。
- 條目數極多時每輪都要全掃一遍,掃描成本不可忽略。
🔗 相關工具
- World Info世界書 —— 這套模式在 SillyTavern 的完整實作
- 工具-RAG檢索增強生成 —— 語意版的按需載入;分工:字面觸發求可控,向量召回求不漏
- 工具-長對話的Token預算分配 —— 注入的知識要跟聊天記錄搶同一個 context,預算要一起規劃
🎯 什麼情境該想到我
當你「要把系統提示、角色設定、檢索資料、聊天記錄全塞進一個固定大小的 context,又不想讓任何一塊被擠爆」的時候。
⚙️ 怎麼用(步驟 / 公式)
先算箱子多大:
可用空間 = max_context − 回應長度上限
例:8192 − 300 = 7892
原則:固定的先放、可伸縮的後放、必須出現在特定位置的先預留。
- Reserve(先佔位):之後一定要出現、而且位置固定的東西(格式標記、「只以某角色身份回覆」這類控制訊息、工具定義),先只扣額度、不放內容。否則聊天記錄會把空間吃光,它們就放不進去了。
- Add(放固定內容):主提示、角色描述、場景、檢索到的知識……依序加入。任何一項超額就直接報錯,不要默默裁切——固定內容壞掉比聊天少幾句嚴重。
- Fill(從最新往舊填聊天):最新一則先放,逐則往前,遇到第一則放不下的就停。
- Free + Insert(歸位):釋放第 1 步的佔位,把真內容插到正確位置。這一步淨值為零——預留時已經扣過了。
算一次帳(SillyTavern 文件範例):
| 階段 | 扣除 | 剩餘 |
|---|---|---|
| 可用 | 7892 | |
| Reserve:標記 3+控制 130+分隔 9+群組引導 15+工具 200 | 357 | 7535 |
| Add:main 150+兩段知識 800+800+角色 200+個性 100+場景 80+人設 50+jailbreak 100 | 2280 | 5225 |
| Fill:最新 6 則聊天,第 7 則(500)放不下就停 | 4831 | 394 |
驗算:7892 − 394 = 7498 已用;7498 + 300(回應)+ 394(剩餘)= 8192 ✓。
★ 帳上看得出:兩段知識 1600 tokens 就佔了固定內容 2280 的七成——檢索知識一定要有自己的上限,否則直接擠掉聊天記憶。
另一種寫法:全放再減(SillyTavern 的 Text Completion 路徑)
loop:
total <= max_context → 完成
還有對話範例 → 刪一條範例
還有聊天 → 刪最舊的一則
都沒了 → 強制送出
兩種做法的保護順序一樣:角色定義 > 近期聊天 > 範例/遠期聊天。
計數要用目標模型的 tokenizer:同一段字在不同 tokenizer 下差很多。粗估「每 3.35 字元 ≈ 1 token」對中文很不準,中文一個字常常就超過一個 token。計數是高頻操作,要加快取(key = tokenizer+字串 hash+模型)。
機制細節 → Token預算管理
🧪 我實際套用的紀錄
- (尚無)
⚠️ 注意 / 什麼時候不適用
- 從新往舊是硬切:放不下的那則整則丟掉、不截半;更舊但更短的也不會被撿回來。被切掉的遠期內容要靠 工具-對話型AI的長期記憶分層 補。
- 固定內容太肥會讓聊天只剩幾則:角色卡或檢索知識膨脹時,最先犧牲的是對話的連續性。
- 剩餘緩衝不是浪費:大小取決於訊息粒度(例子剩 394,是因為下一則有 500)。
- context 大到整段歷史都裝得下時,這套只是保險;但一旦上線長對話,遲早會撞到。
🔗 相關工具
- Token預算管理 —— 完整機制與兩條路徑的差異
- 工具-關鍵字觸發的設定注入 —— 按需注入的知識要有獨立預算
- 工具-對話型AI的長期記憶分層 —— 預算切掉的舊對話,用摘要與召回補回來
📍 放在哪
🎯 什麼情境該想到我
當你「寫在系統提示裡的規則,對話一長模型就不理了;或想臨時改變 AI 的走向,又不想改掉整份設定」的時候。
⚙️ 怎麼用(步驟 / 公式)
為什麼會忘:模型對離生成點越近的內容越在意。系統提示放在最前面,對話一長就跟生成點隔了幾千 token,還落在 prompt 中段的低注意力區。
解法:把指令跟著聊天的尾巴走——插在「從最新一則往上數第 N 則」的位置,讓它跟生成點永遠只隔固定幾則訊息。
Message 1 (最舊)
Message 2
Message 3
← 注入點 (depth=4:之後還有 4 則)
Message 4
Message 5
Message 6
Message 7 (最新)
- 判斷該放哪:「是什麼」(角色定義、世界觀)放固定位置;「現在要怎樣」(氛圍、節奏、這段劇情的行為指引)才用深度注入。
- 選深度:從 depth 3–5 開始試(經驗推論,原文預設 depth=4)。depth=0(貼在最後一則之後)影響最強,但也最容易讓每句回覆都在呼應它(經驗推論)。
- 選頻率:
interval決定每幾則使用者訊息插一次,不必每輪都插。 - 選角色:用 system 最中性。用 user/assistant 時,模型可能把它當成真對話來回應或模仿(經驗推論)。另外,有些 API 對聊天中段的 system 訊息支援度不同,要實測。
- 疊加規則要明確:全域指令和角色專屬指令同時存在時,先決定是取代、放前面還是放後面(SillyTavern 的 replace / before / after)。
★ 把它做成通用框架:摘要、向量記憶、人設、臨時指引,其實都是「某個來源想往 prompt 塞一段字」。SillyTavern 讓每個來源用一個 key 註冊內容,並宣告位置(prompt 內/聊天中某深度/整個 prompt 之前/不自動放、由模板取用),統一交給組裝器處理。「誰要注入」和「注入到哪」解耦,新增一種記憶來源就不用改組裝流程。
同一深度有多筆時的做法:把聊天反轉(最新在前,陣列索引剛好等於 depth),同深度依 system → user → assistant 排好插入,再反轉回來。
機制細節 → Authors Note與深度注入
🧪 我實際套用的紀錄
- (尚無)
⚠️ 注意 / 什麼時候不適用
- 深度注入會跟著聊天被裁切(推論):預算不夠、從舊的砍起時,注入點的位置會移動;聊天全放不下時,它也沒地方放。
- 多個來源擠在同一深度時,順序只看角色優先序,前後關係不一定是你要的。
- 指令太強會喧賓奪主(經驗推論):回覆變成在呼應指令,失去對話的自然感。
- 短對話用不到:系統提示離生成點還很近時,直接寫在系統提示就好。
🔗 相關工具
- Authors Note與深度注入 —— 參數、合成規則、Extension Prompts 全表
- Prompt設計哲學 —— 為什麼要避開 prompt 中段的低注意力區
- 工具-提示工程 —— 指令本身怎麼寫;這張只管「放在哪」
🧠 記住過去
🎯 什麼情境該想到我
當你「做的聊天機器人對話一長,就忘了前面發生的事或使用者講過的細節」的時候。
⚙️ 怎麼用(步驟 / 公式)
先認清問題:模型不是記性不好,是那段文字根本沒送進去——超過 context 上限的舊訊息被截掉了。「長期記憶」在工程上的意思是:用更便宜的形式,把放不下的過去重新塞回這一次的 prompt。
三層各治一種遺忘,互補不替代:
| 層 | 做法 | 治什麼 | 保真度 | token 成本 |
|---|---|---|---|---|
| 1. 滾動摘要 | 每 N 則用 LLM 把舊對話壓成摘要 | 整體脈絡丟失 | 低(有損) | 低 |
| 2. 向量召回 | 訊息做 embedding,生成前用語意找回原文 | 特定細節丟失(「我生日 3/15」) | 高(原文) | 中 |
| 3. 外部知識庫 | 上傳文件分塊向量化,生成前查詢 | 角色缺對話以外的背景知識 | 高 | 可能很高 |
1. 滾動摘要
- 觸發:距上次摘要滿 N 則(SillyTavern 預設 10)。
- ★ 要把上一次的摘要一起餵進去:摘要 A(1–10)→ 摘要 B(A+11–20)→ 摘要 C(B+21–30)。整段歷史就累積壓縮在一段固定長度的文字裡。只看最近 10 則的話,新摘要會忘掉更早的事。
- 摘要別存在最後一則訊息上:最後一則可能被重新生成,摘要會跟著被覆蓋。
2. 向量召回
- 寫入:用 hash 比對找出新增/刪除的訊息(不必全量重算),長訊息切成約 400 字元,再做 embedding。
- 查詢:拿最近 2 則當查詢文字,丟掉相似度低於門檻(0.25)的結果,最多取 3 則注入。
- ★ 最近 5 則永遠保留原位,不被召回結果取代,對話才連貫。
- 換 embedding 模型等於換一套索引,不同模型的向量不能混比。
3. 外部知識庫
- 約 2500 字元分塊,取前 5 塊。作用域分全域/角色/單一聊天三層。本質上是以角色為中心的 RAG(見 工具-RAG檢索增強生成)。
★ 寫入和讀出分開兩個時機:摘要、embedding 掛在「新訊息進來」時做(貴的先做掉),召回掛在「生成請求」時做(只查詢,便宜)。生成路徑因此不會被拖慢(推測)。
怎麼選:短對話都不用。長對話先上摘要(最便宜);使用者開始抱怨「忘了我講過的細節」再加向量;角色需要讀文件才加知識庫。三層都要跟 工具-長對話的Token預算分配 一起算帳。
機制細節 → 長期記憶三層架構
🧪 我實際套用的紀錄
- (尚無)
⚠️ 注意 / 什麼時候不適用
- 摘要會漂移(推論):每次都是舊摘要再壓一次,早期的錯誤會被一路繼承。重要事實不要只靠摘要,允許人工修正並凍結。
- 摘要要多花一次 LLM 呼叫:產品化時通常改成非同步、用便宜模型(我的判斷)。
- 向量只看語意、不看時序和真偽(推論):可能撈回已經被後續劇情推翻的舊話(「我不喜歡你」後來已經和好)。
- 查詢文字太短就撈不到東西(推論):最近兩句是「嗯」「然後呢」時,查詢語意太弱。
- 知識庫很吃 token:5 塊 × 2500 字元,一次就可能上萬字元。
🔗 相關工具
- 長期記憶三層架構 —— 參數、儲存位置、觸發時序的完整說明
- 工具-RAG檢索增強生成 —— 第 2、3 層的通用版;這張講的是「對話記憶」這個特定用途
- 工具-長對話的Token預算分配 —— 記憶是用來補預算切掉的部分,兩者要一起設計
- 工具-關鍵字觸發的設定注入 —— 另一種按需載入:用字面觸發,不用語意
📖 型錄:資料層
[[World Info世界書]]、[[宏系統]] [[長期記憶三層架構]]
📖 型錄:管線層
[[Token預算管理]]、[[Authors Note與深度注入]] [[提示覆蓋與系統提示預設]]、[[生成類型]]
📖 型錄:處理與設計
[[正則替換引擎]]、[[場景與故事走向控制]] [[Prompt設計哲學]]