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