Field guide · 跨平臺同步

同一張 Tavern 角色卡,丟進 Chub.ai RisuAI SillyTavern,行為絕不會 一模一樣:開場白順序變了、lorebook 觸發失靈、自訂提示直接消失。 這篇逐欄位拆給你看,並給出可落地的同步動作。

fol. i.r

同一張卡,三段人生

把你昨天剛寫好的卡,從 SillyTavern 匯出成 V2 PNG,上傳到 Chub.ai, 再把 Chub 給你的下載檔丟進 RisuAI。 三個地方看起來幾乎一樣 —— 同樣的立繪、同樣的名稱、同樣的 描述 —— 但實際對話時的行為卻悄悄地分了岔,往往要花上幾天 才能定位問題。

你會看到開場白變成第三個 alternate_greeting, 而不是原本的 first_mes; 一個在 SillyTavern 穩定觸發的 lorebook 條目,到了 RisuAI 卻安靜失效;你在 Tavern 設好的 extensions.depth_prompt,在第三個宿主裡乾脆不存在。這些都不是傳統意義上的 bug, 而是三個共享同一格式、但各做各的專案之間的實作漂移(implementation drift)

fol. ii.r

三個平臺,三種設計哲學

要預測欄位會不會在某個宿主存活,先記得它「本質上是什麼」。

  • SillyTavern 是本地客戶端。它把卡規格當作母語:V1、V2、以及 V3 的 大部分,都被聊天迴圈直接讀取;多數延伸功能會把自己的鍵 寫進 extensions,而不是去動 schema 本身。要看「正規行為」長什麼樣, 廣義上以 SillyTavern 為事實標準。
  • Chub.ai 是社群宿主。它的工作是儲存與呈現,而非推理:解析卡內容 用來驅動畫廊、版本管理、搜尋介面,再把 PNG 原樣丟回給 使用者的客戶端。Chub 會用自己的延伸命名空間(你會在 extensions 裡看到 chub_ 開頭的鍵),上傳時相對保守、傾向保留原始 payload,但畫廊只會凸顯特定欄位。
  • RisuAI 是跨平臺客戶端(網頁、桌面、行動端),歷來把 Tavern 格式 當作底層,再在上面長出自己的模組系統。它的 lorebook、 觸發器、模組綁定有 Risu 專屬的玩法,透過 extensions 來回流通;卡本身仍能在其它宿主開啟,但 Risu 特有的 行為不會跟著走。

三種設計都沒錯。它們各自押注了不同的位置 —— 客戶端、 宿主、可攜執行環境 —— 而創作者看到的漂移,就是這些選擇 投在同一份檔案格式上的影子。

fol. iii.r

欄位漂移:差異落在哪裡

漂移並非隨機,它集中在規格本身定義模糊、或被各平臺延伸過 的少數欄位。下表只是工作中的對照圖,不是契約 —— 各版本 之間行為一直在變,未來也會繼續變。

FieldSillyTavernChub.aiRisuAI
character_book原生支援,完整 V2 語意保留;透過 chub_lorebook 延伸呈現會讀取,但常被重投到 Risu 自家 lore 模組
alternate_greetings順序保留,使用者可選順序保留;畫廊可能重新排序顯示順序大致保留;選擇器外觀依版本而異
extensions.*多數保留,由對應延伸消化可往返保留,含 chub_ 鍵Risu 自家鍵會被尊重,其它鍵在重匯出時可能被丟棄
mes_example以「START」標記解析,作為 few-shot原樣儲存,宿主不解讀會解讀,空白與標記可能被正規化
system_prompt會生效,可能與全域 preset 合併原樣儲存會生效,可能被 Risu 模組重新包裝
assets(V3)支援持續完善,路徑解析規則仍在收斂會儲存,但僅部分類型在前端被呈現部分支援;表情立繪走另一條路徑
creator_notes_multilingual(V3)有就讀有時與 creator_notes 一併顯示不穩定地呈現

兩個模式不斷重演。第一,extensions 是最誠實的 命名空間:所有宿主想加的東西都丟在這裡,能不能 往返完全看下一棒認不認識這把鑰匙。第二,被解讀的欄位漂得比被 存檔的欄位更兇:只把 JSON 歸檔的宿主(Chub)保留 得多,會解析與重渲染的宿主(SillyTavern、RisuAI)保留 得少。

fol. iv.r

PNG tEXt:看不見的舞臺

在欄位層級的詮釋差異之前,PNG 容器本身就已經是漂移的來源。 Tavern 卡的 payload 住在 PNG 的 tEXt 區塊(較大時為 zTXt), 以 chara 為鍵、Base64 編碼。三個宿主處理這個區塊的力道並不一樣:

  • SillyTavern 匯入時讀取、匯出時重寫 —— 對已知欄位無損, 但對不認識的延伸資料,曾被回報在來回時偶爾被重排或 正規化。
  • Chub.ai 在上傳時大體保留原始區塊,但生成縮圖或最佳化 變體時可能重新編碼 PNG 本身;下載「原始卡」走的那條 路徑通常最安全。
  • RisuAI 的匯入流程會把 payload 先過自家模型再重發,所以 經過 Risu 來回一次的卡,結構上常常一致、位元上卻不同。

如果你發現卡在上傳後悄悄掉欄位卻找不到原因,答案多半在 這一層。我們在另一篇 PNG tEXt chunk metadata 與 Tavern 卡中詳細拆解編碼。

fol. vi.r

如何讓你的卡庫保持同步

你沒辦法讓三個宿主完全一致。你可以讓它們「夠接近」,讓你 的卡庫能撐過跨平臺旅程。三個工作習慣最有用:

  1. 以最小公倍數欄位 集為主要載體。 把 V2 正規欄位 —— name description personality scenario first_mes alternate_greetings mes_example system_prompt character_book —— 當作承重結構,把所有住在 extensions 裡的東西當成 best-effort。重要行為必須能用正規欄位表達。
  2. 每次發版都做 round-trip 測試。 從你的真相來源匯出,逐個匯入目標宿主、再匯出,把 JSON diff 出來。那份 diff 就是漂移。多數作者人工做一次後 就沒下文;能長期存活的卡,都是把這件事自動化了的人 在維護。
  3. 把 diff 留成報表。 漂移會累積。昨天還能撐三輪 round-trip 的欄位,下週某個 宿主更新後就可能斷裂。把 diff 當資料追蹤而不是憑感覺, 才有機會在讀者發現之前先抓到回歸。
fol. vii.r

一份原稿,三種方言

tavernai.cards 想做的, 正是這個問題的譯本:一張正規卡、三種活的方言、一份你看 得懂的 diff。

  • 雙向同步 —— 把同一張卡推到 Chub.ai、RisuAI、SillyTavern,也把宿主端 的修改拉回你的真相來源。
  • 自動 diff 報表 —— 每次 round-trip 之後,告訴你哪些欄位被保留、被正規化、 被丟棄,逐宿主清單呈現。
  • 格式感知的轉換 —— V1、V2、V3 加上各宿主在 extensions 下的方言,用可見的對應關係轉換,不是黑盒重寫。
  • 發布前 lint —— 把不相容欄位、失效資產引用、靜默編碼錯誤先抓出來, 再讓卡出門。

工作臺以小批次開放。如果你的卡庫必須同時活在 Chub、Risu 與 Tavern 上,先在卷軸上留個名 —— 跨平臺同步是第一個出門的 功能。

其他語言