Merge branch 'staging' into fix-bogus-sorting

8bc515c6a1c9909692ae10ba52bcfa7140be9ef9

Cohee <18619528+Cohee1207@users.noreply.github.com>

6 files changed, +59 -27Ignore whitespace
.github/readme-zh_tw.md+11 -11
@@ -1,5 +1,5 @@
1> [!IMPORTANT] 1> [!IMPORTANT]
2> 這裡的資訊可能已經過時或不完整,僅供您參考。請使用英文版本以取得最新資訊。2> 此處資訊可能已經過時或不完整,僅供您參考。請使用英文版本以取得最新資訊。
33
4<a name="readme-top"></a>4<a name="readme-top"></a>
55
@@ -18,7 +18,7 @@
1818
19---19---
2020
21SillyTavern 提供一個統一的前端介面,整合多種大型語言模型的 API(包括:KoboldAI/CPP、Horde、NovelAI、Ooba、Tabby、OpenAI、OpenRouter、Claude、Mistral 等)。同時具備行動裝置友善的佈局、視覺小說模式(Visual Novel Mode)、Automatic1111 與 ComfyUI 的影像生成 API 整合、TTS(語音合成)、世界資訊(Lorebook)、可自訂 UI、自動翻譯功能,以及強大的提示詞(prompt)設定選項和無限的第三方擴充潛力。21SillyTavern 提供一個統一的前端介面,整合多種大型語言模型的 API(包括:KoboldAI/CPP、Horde、NovelAI、Ooba、Tabby、OpenAI、OpenRouter、Claude、Mistral 等)。同時具備對行動裝置友善的佈局、視覺小說模式(Visual Novel Mode)、Automatic1111 與 ComfyUI 的影像生成 API 整合、TTS(語音合成)、世界資訊(Lorebook)、可自訂 UI、自動翻譯功能,以及強大的提示詞(prompt)設定選項和無限的第三方擴充潛力。
2222
23我們擁有一個 [官方文件網站](https://docs.sillytavern.app/) 可以幫助解答絕大多數的使用問題,並幫助您順利入門。23我們擁有一個 [官方文件網站](https://docs.sillytavern.app/) 可以幫助解答絕大多數的使用問題,並幫助您順利入門。
2424
@@ -30,18 +30,18 @@ SillyTavern 起源於 2023 年 2 月,作為 TavernAI 1.2.8 的分支版本發
3030
31## 我們的願景31## 我們的願景
3232
331. 我們致力於賦予使用者對 LLM 提示詞的最大控制權與實用性,並認為學習過程中的挑戰是樂趣的一部分331. 我們致力於賦予使用者對 LLM 提示詞的最大控制權與實用性,並認為學習過程中的挑戰是樂趣的一部分。
342. 我們不提供任何線上或託管服務,也不會程式化追蹤任何使用者數據。342. 我們不提供任何線上或託管服務,也不會程式化追蹤任何使用者數據。
353. SillyTavern 是由一群熱衷於 LLM 的開發者社群所打造的熱情專案,並將永遠保持免費與開源。353. SillyTavern 是由一群熱衷於 LLM 的開發者社群所打造的專案,並將永遠保持免費與開源。
3636
37## 分支介紹37## 分支介紹
3838
39SillyTavern 採用雙分支開發模式,確保為所有使用者提供流暢的使用體驗。39SillyTavern 採用雙分支開發模式,確保為所有使用者提供流暢的體驗。
4040
41* `release`(穩定版):🌟 **推薦給大部分的使用者使用。** 此分支最為穩定,僅在主要版本發布時更新。適合大多數人,通常每月更新一次。41* `release`(穩定版):🌟 **推薦給大部分的使用者使用。** 此分支最為穩定,僅在主要版本發布時更新。適合大多數人,通常每月更新一次。
42* `staging`(開發版):⚠️ **不建議普通使用者使用。** 此分支包含最新功能,但可能隨時出現問題。適合進階使用者與愛好者,每日多次更新。42* `staging`(開發版):⚠️ **不建議普通使用者使用。** 此分支包含最新功能,但可能隨時出現問題。適合進階使用者與愛好者,每日多次更新。
4343
44如果您不熟悉 git CLI 或對分支概念不清楚,請放心對您來說,`release`(穩定版)分支永遠是首選。44如果您不熟悉 git CLI 或對分支概念不清楚,請放心,對您來說,`release`(穩定版)分支永遠是首選。
4545
46## 使用 SillyTavern 需要什麼?46## 使用 SillyTavern 需要什麼?
4747
@@ -84,18 +84,18 @@ SillyTavern 的硬體需求相當低。任何能夠運行 NodeJS 18 或更高版
8484
85## 角色卡85## 角色卡
8686
87SillyTavern 的核心概念是「角色卡」(Character Cards)。角色卡是一組設定 LLM 行為的提示詞,用於 SillyTavern 中進行持續性對話。其功能類似於 ChatGPT 的 GPT 或 Poe 的聊天機器人。角色卡的內容可以是任何形式:抽象場景、針對特定任務設計的助手、知名人物,或者虛構角色。87SillyTavern 的核心概念是「角色卡」(Character Cards)。角色卡是一組設定 LLM 行為的提示詞,用於 SillyTavern 中進行持續性對話。功能類似於 ChatGPT 的 GPT 或 Poe 的聊天機器人。角色卡的內容可以是任何形式:抽象場景、針對特定任務設計的助手、知名人物,或者虛構角色。
8888
89角色卡中唯一必填的項目是名稱欄位。若想與語言模型開始一般對話,您只需創建一個名稱為「Assistant」的新卡片,其餘欄位皆可保持空白。若希望進行更具主題性的對話,則可以提供語言模型背景資訊、行為模式、寫作風格以及特定情境來啟動聊天。89角色卡中唯一必填的項目是名稱欄位。若想與語言模型開始一般對話,您只需創建一個名稱為「Assistant」的新卡片,其餘欄位皆可保持空白。若希望進行更具主題性的對話,則可以提供語言模型背景資訊、行為模式、寫作風格以及特定情境來啟動聊天。
9090
91如果您僅想進行快速對話而不選擇角色卡片,或想測試 LLM 的連線,則可在打開 SillyTavern 後,於歡迎頁面的輸入欄位中直接輸入您的提示內容。請注意,這類對話是暫時的,不會被永久保存。91如果僅想進行快速對話而不選擇角色卡片,或想測試 LLM 的連線,則可在開啟 SillyTavern 後,於歡迎頁面的輸入欄位中直接輸入您的提示內容。請注意,這類對話是暫時的,不會被永久保存。
9292
93若想了解如何設定角色卡,可參考預設角色(如 Seraphina)或從「下載擴充功能 & 資源」(Download Extensions & Assets)選單中下載社群製作的角色卡。93若想了解如何設定角色卡,可參考預設角色(如 Seraphina)或從「下載擴充功能 & 資源」(Download Extensions & Assets)選單中下載社群製作的角色卡。
9494
95## 核心功能95## 核心功能
9696
97* 進階文本生成設定:內含許多社群製作的預設設定97* 進階文本生成設定:內含許多社群製作的預設設定
98* 支援世界資訊(World Info):創建豐富的背景故事,或節省角色卡片中的 Token(符記)使用98* 支援世界資訊(World Info):創建豐富的背景故事,或節省角色卡中的 Token(符元)使用
99* 群組聊天:多角色聊天室,可讓角色與您或彼此對話99* 群組聊天:多角色聊天室,可讓角色與您或彼此對話
100* 豐富的 UI 自定義選項:主題顏色、背景圖片、自定義 CSS 等100* 豐富的 UI 自定義選項:主題顏色、背景圖片、自定義 CSS 等
101* 使用者設定:讓 AI 更了解您並提升沉浸感101* 使用者設定:讓 AI 更了解您並提升沉浸感
@@ -110,7 +110,7 @@ SillyTavern 支持多種擴充功能。
110* 聊天記錄自動摘要110* 聊天記錄自動摘要
111* 自動化介面與聊天翻譯111* 自動化介面與聊天翻譯
112* 穩定擴散(Stable Diffusion)、FLUX 和 DALL-E 的影像生成整合112* 穩定擴散(Stable Diffusion)、FLUX 和 DALL-E 的影像生成整合
113* 語音合成:AI 回應訊息可透過 ElevenLabs、Silero 或系統 TTS 語音合成113* 語音合成:AI 回應的訊息可使用 ElevenLabs、Silero 或系統 TTS 語音合成
114* 網頁搜尋功能:為提示詞添加真實世界的上下文資訊114* 網頁搜尋功能:為提示詞添加真實世界的上下文資訊
115* 更多擴展:可從「下載擴充功能 & 資源」(Download Extensions & Assets)選單中下載115* 更多擴展:可從「下載擴充功能 & 資源」(Download Extensions & Assets)選單中下載
116116
@@ -367,7 +367,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
367* 經授權使用部分來自 CncAnon 的 TavernAITurbo 模組367* 經授權使用部分來自 CncAnon 的 TavernAITurbo 模組
368* 視覺小說模式(Visual Novel Mode)的靈感,來源於 PepperTaco 的貢獻(<https://github.com/peppertaco/Tavern/>)368* 視覺小說模式(Visual Novel Mode)的靈感,來源於 PepperTaco 的貢獻(<https://github.com/peppertaco/Tavern/>)
369* Noto Sans 字體由 Google 提供(OFL 許可)369* Noto Sans 字體由 Google 提供(OFL 許可)
370* 主題圖示由 Font Awesome <https://fontawesome.com> 提供(圖示:CC BY 4.0,字體:SIL OFL 1.1,代碼:MIT 許可)370* 主題圖示由 Font Awesome <https://fontawesome.com> 提供(圖示:CC BY 4.0,字體:SIL OFL 1.1,程式碼:MIT 許可)
371* 預設資源來源於 @OtisAlejandro(包含角色 Seraphina 與知識書)與 @kallmeflocc(SillyTavern 官方 Discord 伺服器成員突破 10K 的慶祝背景)371* 預設資源來源於 @OtisAlejandro(包含角色 Seraphina 與知識書)與 @kallmeflocc(SillyTavern 官方 Discord 伺服器成員突破 10K 的慶祝背景)
372* Docker 安裝指南由 [@mrguymiah](https://github.com/mrguymiah) 和 [@Bronya-Rand](https://github.com/Bronya-Rand) 編寫372* Docker 安裝指南由 [@mrguymiah](https://github.com/mrguymiah) 和 [@Bronya-Rand](https://github.com/Bronya-Rand) 編寫
373373
default/config.yaml+14 -8
@@ -84,6 +84,20 @@ autorun: true
84# use if you don't have 'localhost' in your hosts file84# use if you don't have 'localhost' in your hosts file
85avoidLocalhost: false85avoidLocalhost: false
8686
87## BACKUP CONFIGURATION
88backups:
89 # Common settings for all backup types
90 common:
91 # Number of backups to keep for each chat and settings file
92 numberOfBackups: 50
93 chat:
94 # Enable automatic chat backups
95 enabled: true
96 # Maximum number of chat backups to keep per user (starting from the most recent). Set to -1 to keep all backups.
97 maxTotalBackups: -1
98 # Interval in milliseconds to throttle chat backups per user
99 throttleInterval: 10000
100
87# THUMBNAILING CONFIGURATION101# THUMBNAILING CONFIGURATION
88thumbnails:102thumbnails:
89 # Enable thumbnail generation103 # Enable thumbnail generation
@@ -102,14 +116,6 @@ thumbnails:
102allowKeysExposure: false116allowKeysExposure: false
103# Skip new default content checks117# Skip new default content checks
104skipContentCheck: false118skipContentCheck: false
105# Disable automatic chats backup
106disableChatBackup: false
107# Number of backups to keep for each chat and settings file
108numberOfBackups: 50
109# Maximum number of chat backups to keep per user (starting from the most recent). Set to -1 to keep all backups.
110maxTotalChatBackups: -1
111# Interval in milliseconds to throttle chat backups per user
112chatBackupThrottleInterval: 10000
113# Allowed hosts for card downloads119# Allowed hosts for card downloads
114whitelistImportDomains:120whitelistImportDomains:
115 - localhost121 - localhost
post-install.js+20 -0
@@ -44,6 +44,26 @@ const keyMigrationMap = [
44 newKey: 'thumbnails.format',44 newKey: 'thumbnails.format',
45 migrate: (value) => (value ? 'png' : 'jpg'),45 migrate: (value) => (value ? 'png' : 'jpg'),
46 },46 },
47 {
48 oldKey: 'disableChatBackup',
49 newKey: 'backups.chat.enabled',
50 migrate: (value) => !value,
51 },
52 {
53 oldKey: 'numberOfBackups',
54 newKey: 'backups.common.numberOfBackups',
55 migrate: (value) => value,
56 },
57 {
58 oldKey: 'maxTotalChatBackups',
59 newKey: 'backups.chat.maxTotalBackups',
60 migrate: (value) => value,
61 },
62 {
63 oldKey: 'chatBackupThrottleInterval',
64 newKey: 'backups.chat.throttleInterval',
65 migrate: (value) => value,
66 },
47];67];
4868
49/**69/**
src/endpoints/backends/chat-completions.js+8 -2
@@ -308,14 +308,20 @@ async function sendMakerSuiteRequest(request, response) {
308 ) && request.body.use_makersuite_sysprompt;308 ) && request.body.use_makersuite_sysprompt;
309309
310 const prompt = convertGooglePrompt(request.body.messages, model, should_use_system_prompt, getPromptNames(request));310 const prompt = convertGooglePrompt(request.body.messages, model, should_use_system_prompt, getPromptNames(request));
311 let safetySettings = GEMINI_SAFETY;
312
313 if (model.includes('gemini-2.0-flash-exp')) {
314 safetySettings = GEMINI_SAFETY.map(setting => ({ ...setting, threshold: 'OFF' }));
315 }
316
311 let body = {317 let body = {
312 contents: prompt.contents,318 contents: prompt.contents,
313 safetySettings: GEMINI_SAFETY,319 safetySettings: safetySettings,
314 generationConfig: generationConfig,320 generationConfig: generationConfig,
315 };321 };
316322
317 if (should_use_system_prompt) {323 if (should_use_system_prompt) {
318 body.system_instruction = prompt.system_instruction;324 body.systemInstruction = prompt.system_instruction;
319 }325 }
320326
321 return body;327 return body;
src/endpoints/chats.js+4 -4
@@ -18,9 +18,9 @@ import {
18 formatBytes,18 formatBytes,
19} from '../util.js';19} from '../util.js';
2020
21const isBackupDisabled = getConfigValue('disableChatBackup', false);21const isBackupEnabled = !!getConfigValue('backups.chat.enabled', true);
22const maxTotalChatBackups = Number(getConfigValue('maxTotalChatBackups', -1));22const maxTotalChatBackups = Number(getConfigValue('backups.chat.maxTotalBackups', -1));
23const throttleInterval = getConfigValue('chatBackupThrottleInterval', 10_000);23const throttleInterval = Number(getConfigValue('backups.chat.throttleInterval', 10_000));
2424
25/**25/**
26 * Saves a chat to the backups directory.26 * Saves a chat to the backups directory.
@@ -31,7 +31,7 @@ const throttleInterval = getConfigValue('chatBackupThrottleInterval', 10_000);
31function backupChat(directory, name, chat) {31function backupChat(directory, name, chat) {
32 try {32 try {
3333
34 if (isBackupDisabled) {34 if (!isBackupEnabled) {
35 return;35 return;
36 }36 }
3737
src/util.js+2 -2
@@ -389,10 +389,10 @@ export function generateTimestamp() {
389 * Remove old backups with the given prefix from a specified directory.389 * Remove old backups with the given prefix from a specified directory.
390 * @param {string} directory The root directory to remove backups from.390 * @param {string} directory The root directory to remove backups from.
391 * @param {string} prefix File prefix to filter backups by.391 * @param {string} prefix File prefix to filter backups by.
392 * @param {number?} limit Maximum number of backups to keep. If null, the limit is determined by the `numberOfBackups` config value.392 * @param {number?} limit Maximum number of backups to keep. If null, the limit is determined by the `backups.common.numberOfBackups` config value.
393 */393 */
394export function removeOldBackups(directory, prefix, limit = null) {394export function removeOldBackups(directory, prefix, limit = null) {
395 const MAX_BACKUPS = limit ?? Number(getConfigValue('numberOfBackups', 50));395 const MAX_BACKUPS = limit ?? Number(getConfigValue('backups.common.numberOfBackups', 50));
396396
397 let files = fs.readdirSync(directory).filter(f => f.startsWith(prefix));397 let files = fs.readdirSync(directory).filter(f => f.startsWith(prefix));
398 if (files.length > MAX_BACKUPS) {398 if (files.length > MAX_BACKUPS) {