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