Merge branch 'staging' of https://github.com/SillyLossy/TavernAI into staging

This commit is contained in:
Cohee
2023-08-05 15:44:18 +03:00
14 changed files with 232 additions and 74 deletions

View File

@ -1,6 +1,8 @@
[English](readme.md) | 中文
![image](https://github.com/SillyTavern/SillyTavern/assets/18619528/8c41a061-7f72-4d2b-9d54-e6d058209e7b) ![image](https://github.com/SillyTavern/SillyTavern/assets/18619528/8c41a061-7f72-4d2b-9d54-e6d058209e7b)
移动设备界面友好多种人工智能服务或模型支持KoboldAI/CPP, Horde, NovelAI, Ooba, OpenAI+proxies, WindowAI(Claude!)),类似 Galgame 的 老 婆 模 式Horde SD文本系统语音生成世界信息Lorebooks可定制的界面自动翻译和比你所需要的更多的 Prompt。附带扩展服务支持文本绘画生成与语音生成和基于向量数据库 ChromaDB 的聊天信息总结。 移动设备界面友好多种人工智能服务或模型支持KoboldAI/CPP, Horde, NovelAI, Ooba, OpenAI, OpenRouter, Claude, Scale),类似 Galgame 的 老 婆 模 式Horde SD文本系统语音生成世界信息Lorebooks可定制的界面自动翻译和比你所需要的更多的 Prompt。附带扩展服务支持文本绘画生成与语音生成和基于向量数据库 ChromaDB 的聊天信息总结。
基于 TavernAI 1.2.8 的分叉版本 基于 TavernAI 1.2.8 的分叉版本
@ -282,25 +284,26 @@ SillyTavern 会将 API 密钥保存在目录中的 `secrets.json` 文件内。
## 许可证和贡献 ## 许可证和贡献
** 发布本程序是希望它能有所帮助,但不做任何保证;甚至没有明示的性能、稳定性和其他任何特定用途的可用性保证。更多详情,请参阅 GNU Affero 通用公共许可证。 ** **发布本程序是希望它能有所帮助,但不做任何保证;甚至没有明示的性能、稳定性和其他任何特定用途的可用性保证。更多详情,请参阅 GNU Affero 通用公共许可证。**
** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. ** **This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.**
* TAI Base by Humi: Unknown license * TAI Base by Humi: Unknown license
* Cohee's modifications and derived code: AGPL v3 * Cohee's modifications and derived code: AGPL v3
* RossAscends' additions: AGPL v3 * RossAscends' additions: AGPL v3
* Portions of CncAnon's TavernAITurbo mod: Unknown license * Portions of CncAnon's TavernAITurbo mod: Unknown license
* kingbri's various commits and suggestions (https://github.com/bdashore3) * kingbri's various commits and suggestions (<https://github.com/bdashore3>)
* StefanDanielSchwarz's various commits and bug reports (https://github.com/StefanDanielSchwarz) * StefanDanielSchwarz's various commits and bug reports (<https://github.com/StefanDanielSchwarz>)
* Waifu mode inspired by the work of PepperTaco (https://github.com/peppertaco/Tavern/) * Waifu mode inspired by the work of PepperTaco (<https://github.com/peppertaco/Tavern/>)
* Thanks Pygmalion University for being awesome testers and suggesting cool features! * Thanks Pygmalion University for being awesome testers and suggesting cool features!
* Thanks oobabooga for compiling presets for TextGen * Thanks oobabooga for compiling presets for TextGen
* KoboldAI Presets from KAI Lite: https://lite.koboldai.net/ * KoboldAI Presets from KAI Lite: <https://lite.koboldai.net/>
* Noto Sans font by Google (OFL license) * Noto Sans font by Google (OFL license)
* Icon theme by Font Awesome https://fontawesome.com (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) * Icon theme by Font Awesome <https://fontawesome.com> (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* AI Horde client library by ZeldaFan0225: https://github.com/ZeldaFan0225/ai_horde * AI Horde client library by ZeldaFan0225: <https://github.com/ZeldaFan0225/ai_horde>
* Linux startup script by AlpinDale * Linux startup script by AlpinDale
* Thanks paniphons for providing a FAQ document * Thanks paniphons for providing a FAQ document
* 10K Discord Users Celebratory Background by @kallmeflocc * 10K Discord Users Celebratory Background by @kallmeflocc
* Default content (characters and lore books) provided by @OtisAlejandro, @RossAscends and @kallmeflocc * Default content (characters and lore books) provided by @OtisAlejandro, @RossAscends and @kallmeflocc
* Korean translation by @doloroushyeonse * Korean translation by @doloroushyeonse
* 中文翻译由 [@XXpE3](https://github.com/XXpE3) 完成,中文 ISSUES 可以联系 @XXpE3

7
.github/readme.md vendored
View File

@ -1,6 +1,8 @@
English | [中文](readme-zh_cn.md)
![image](https://github.com/SillyTavern/SillyTavern/assets/18619528/8c41a061-7f72-4d2b-9d54-e6d058209e7b) ![image](https://github.com/SillyTavern/SillyTavern/assets/18619528/8c41a061-7f72-4d2b-9d54-e6d058209e7b)
Mobile-friendly, Multi-API (KoboldAI/CPP, Horde, NovelAI, Ooba, OpenAI+proxies, WindowAI(Claude!)), VN-like Waifu Mode, Horde SD, System TTS, WorldInfo (lorebooks), customizable UI, auto-translate, and more prompt options than you'd ever want or need. Optional Extras server for more SD/TTS options + ChromaDB/Summarize. Mobile-friendly, Multi-API (KoboldAI/CPP, Horde, NovelAI, Ooba, OpenAI, OpenRouter, Claude, Scale), VN-like Waifu Mode, Horde SD, System TTS, WorldInfo (lorebooks), customizable UI, auto-translate, and more prompt options than you'd ever want or need. Optional Extras server for more SD/TTS options + ChromaDB/Summarize.
Based on a fork of TavernAI 1.2.8 Based on a fork of TavernAI 1.2.8
@ -65,7 +67,7 @@ Get in touch with the developers directly:
* Chat bookmarks / branching (duplicates the dialogue in its current state) * Chat bookmarks / branching (duplicates the dialogue in its current state)
* Advanced KoboldAI / TextGen generation settings with a lot of community-made presets * Advanced KoboldAI / TextGen generation settings with a lot of community-made presets
* World Info support: create rich lore or save tokens on your character card * World Info support: create rich lore or save tokens on your character card
* Window AI browser extension support (run models like Claude, GPT 4): <https://windowai.io/> * [OpenRouter](https://openrouter.ai) connection for various APIs (Claude, GPT-4/3.5 and more)
* [Oobabooga's TextGen WebUI](https://github.com/oobabooga/text-generation-webui) API connection * [Oobabooga's TextGen WebUI](https://github.com/oobabooga/text-generation-webui) API connection
* [AI Horde](https://horde.koboldai.net/) connection * [AI Horde](https://horde.koboldai.net/) connection
* Prompt generation formatting tweaking * Prompt generation formatting tweaking
@ -307,3 +309,4 @@ GNU Affero General Public License for more details.**
* Default content (characters and lore books) provided by @OtisAlejandro, @RossAscends and @kallmeflocc * Default content (characters and lore books) provided by @OtisAlejandro, @RossAscends and @kallmeflocc
* Korean translation by @doloroushyeonse * Korean translation by @doloroushyeonse
* k_euler_a support for Horde by <https://github.com/Teashrock> * k_euler_a support for Horde by <https://github.com/Teashrock>
* Chinese translation by [@XXpE3](https://github.com/XXpE3), 中文 ISSUES 可以联系 @XXpE3

View File

@ -59,7 +59,7 @@
"trusted_workers_only": false "trusted_workers_only": false
}, },
"power_user": { "power_user": {
"tokenizer": 3, "tokenizer": 99,
"token_padding": 64, "token_padding": 64,
"collapse_newlines": false, "collapse_newlines": false,
"pygmalion_formatting": 0, "pygmalion_formatting": 0,
@ -147,6 +147,7 @@
"persona_description": "", "persona_description": "",
"persona_description_position": 0, "persona_description_position": 0,
"custom_stopping_strings": "", "custom_stopping_strings": "",
"custom_stopping_strings_macro": true,
"fuzzy_search": false "fuzzy_search": false
}, },
"extension_settings": { "extension_settings": {

View File

@ -328,7 +328,7 @@
</div> </div>
<div class="range-block-range-and-counter"> <div class="range-block-range-and-counter">
<div class="range-block-range"> <div class="range-block-range">
<input type="range" id="temp_novel" name="volume" min="0.1" max="2.0" step="0.01"> <input type="range" id="temp_novel" name="volume" min="0.1" max="2.50" step="0.01">
</div> </div>
<div class="range-block-counter"> <div class="range-block-counter">
<div contenteditable="true" data-for="temp_novel" id="temp_counter_novel"> <div contenteditable="true" data-for="temp_novel" id="temp_counter_novel">
@ -342,7 +342,7 @@
</div> </div>
<div class="range-block-range-and-counter"> <div class="range-block-range-and-counter">
<div class="range-block-range"> <div class="range-block-range">
<input type="range" id="rep_pen_novel" name="volume" min="1" max="1.5" step="0.01"> <input type="range" id="rep_pen_novel" name="volume" min="1" max="8" step="0.05">
</div> </div>
<div class="range-block-counter"> <div class="range-block-counter">
<div contenteditable="true" data-for="rep_pen_novel" id="rep_pen_counter_novel"> <div contenteditable="true" data-for="rep_pen_novel" id="rep_pen_counter_novel">
@ -387,7 +387,7 @@
</div> </div>
<div class="range-block-range-and-counter"> <div class="range-block-range-and-counter">
<div class="range-block-range"> <div class="range-block-range">
<input type="range" id="rep_pen_freq_novel" name="volume" min="0" max="1" step="0.00001"> <input type="range" id="rep_pen_freq_novel" name="volume" min="0" max="1" step="0.01">
</div> </div>
<div class="range-block-counter"> <div class="range-block-counter">
<div contenteditable="true" data-for="rep_pen_freq_novel" id="rep_pen_freq_counter_novel"> <div contenteditable="true" data-for="rep_pen_freq_novel" id="rep_pen_freq_counter_novel">
@ -402,7 +402,7 @@
</div> </div>
<div class="range-block-range-and-counter"> <div class="range-block-range-and-counter">
<div class="range-block-range"> <div class="range-block-range">
<input type="range" id="rep_pen_presence_novel" name="volume" min="0" max="1" step="0.001"> <input type="range" id="rep_pen_presence_novel" name="volume" min="0" max="1" step="0.01">
</div> </div>
<div class="range-block-counter"> <div class="range-block-counter">
<div contenteditable="true" data-for="rep_pen_presence_novel" id="rep_pen_presence_counter_novel"> <div contenteditable="true" data-for="rep_pen_presence_novel" id="rep_pen_presence_counter_novel">
@ -815,8 +815,8 @@
<div class="fa-solid fa-clock-rotate-left "></div> <div class="fa-solid fa-clock-rotate-left "></div>
</div> </div>
</div> </div>
<div class="toggle-description justifyLeft" data-i18n="Use style tags to improve the quality of the output"> <div class="toggle-description justifyLeft" data-i18n="Use style tags to modify the writing style of the output">
Use style tags to improve the quality of the output Use style tags to modify the writing style of the output
</div> </div>
<div class="wide100p"> <div class="wide100p">
<textarea id="nai_preamble_textarea" class="text_pole textarea_compact" name="nai_preamble" rows="2" <textarea id="nai_preamble_textarea" class="text_pole textarea_compact" name="nai_preamble" rows="2"
@ -1336,12 +1336,8 @@
</div> </div>
</div> </div>
<div class="range-block" data-source="claude"> <div class="range-block" data-source="claude">
<div class="range-block-title" data-i18n="Assistant Prefill"> <span data-i18n="Assistant Prefill">Assistant Prefill</span>
Assistant Prefill <textarea id="claude_assistant_prefill" class="text_pole textarea_compact" name="assistant_prefill" rows="3" maxlength="5000" placeholder="Start Claude's answer with..."></textarea>
</div>
<div class="wide100p">
<input type="text" id="claude_assistant_prefill" class="text_pole" placeholder="Start Claude's answer with...">
</div>
</div> </div>
<div class="inline-drawer wide100p"> <div class="inline-drawer wide100p">
@ -1556,11 +1552,11 @@
</div> </div>
<div id="textgenerationwebui_api" style="display: none;position: relative;"> <div id="textgenerationwebui_api" style="display: none;position: relative;">
<form action="javascript:void(null);" method="post" enctype="multipart/form-data"> <form action="javascript:void(null);" method="post" enctype="multipart/form-data">
If you are using: If you are using:
<div class="flex-container indent20p"> <div class="flex-container indent20p">
<a href="https://github.com/oobabooga/text-generation-webui" target="_blank"> <a href="https://github.com/oobabooga/text-generation-webui" target="_blank">
oobabooga/text-generation-webui oobabooga/text-generation-webui
</a>, </a>
<span data-i18n="Make sure you run it with"> <span data-i18n="Make sure you run it with">
Make sure you run it with <tt>--api</tt> flag Make sure you run it with <tt>--api</tt> flag
</span> </span>
@ -1568,7 +1564,7 @@
<div class="flex-container indent20p"> <div class="flex-container indent20p">
<a href="https://mancer.tech/" target="_blank"> <a href="https://mancer.tech/" target="_blank">
Mancer AI Mancer AI
</a>, </a>
<label class="checkbox_label" for="use-mancer-api-checkbox"> <label class="checkbox_label" for="use-mancer-api-checkbox">
<span data-i18n="Use API key (Only required for Mancer)"> <span data-i18n="Use API key (Only required for Mancer)">
Click this box (and add your API key!): Click this box (and add your API key!):
@ -1961,6 +1957,7 @@
</a> </a>
</h4> </h4>
<select id="tokenizer"> <select id="tokenizer">
<option value="99">Best match (recommended)</option>
<option value="0">None / Estimated</option> <option value="0">None / Estimated</option>
<option value="1">GPT-3 (OpenAI)</option> <option value="1">GPT-3 (OpenAI)</option>
<option value="2">GPT-3 (Alternative / Classic)</option> <option value="2">GPT-3 (Alternative / Classic)</option>
@ -2037,6 +2034,12 @@
<div> <div>
<textarea id="custom_stopping_strings" rows="2" class="text_pole textarea_compact" placeholder="[&quot;Ford&quot;, &quot;BMW&quot;, &quot;Fiat&quot;]"></textarea> <textarea id="custom_stopping_strings" rows="2" class="text_pole textarea_compact" placeholder="[&quot;Ford&quot;, &quot;BMW&quot;, &quot;Fiat&quot;]"></textarea>
</div> </div>
<label class="checkbox_label" for="custom_stopping_strings_macro">
<input id="custom_stopping_strings_macro" type="checkbox" checked>
<span data-i18n="Replace Macro in Custom Stopping Strings">
Replace Macro in Custom Stopping Strings
</span>
</label>
<h4> <h4>
<span data-i18n="Pygmalion Formatting"> <span data-i18n="Pygmalion Formatting">
Pygmalion Formatting Pygmalion Formatting

View File

@ -0,0 +1,12 @@
{
"input_sequence": "User: ",
"macro": true,
"name": "OpenOrca/OpenChat",
"names": true,
"output_sequence": "<|end_of_turn|>\nAssistant: ",
"separator_sequence": "<|end_of_turn|>\n",
"stop_sequence": "",
"system_prompt": "You are a helpful assistant. Please answer truthfully and write out your thinking step by step to be sure you get the right answer. If you make a mistake or encounter an error in your thinking, say so out loud and attempt to correct it. If you don't know or aren't sure about something, say so clearly. You will act as a professional logician, mathematician, and physicist. You will also act as the most appropriate type of expert to answer any particular question or solve the relevant problem; state which expert type your are, if so. Also think of any particular named expert that would be ideal to answer the relevant question or solve the relevant problem; name and act as them, if appropriate.\n",
"system_sequence": "",
"wrap": false
}

View File

@ -1,5 +1,4 @@
{ {
"enabled": true,
"input_sequence": "### Instruction:", "input_sequence": "### Instruction:",
"macro": true, "macro": true,
"name": "Roleplay", "name": "Roleplay",

View File

@ -546,6 +546,25 @@ async function getClientVersion() {
} }
} }
function getTokenizerBestMatch() {
if (main_api === 'novel') {
if (nai_settings.model_novel.includes('krake') || nai_settings.model_novel.includes('euterpe')) {
return tokenizers.CLASSIC;
}
if (nai_settings.model_novel.includes('clio')) {
return tokenizers.NERD;
}
if (nai_settings.model_novel.includes('kayra')) {
return tokenizers.NERD2;
}
}
if (main_api === 'kobold' || main_api === 'textgenerationwebui' || main_api === 'koboldhorde') {
return tokenizers.LLAMA;
}
return power_user.NONE;
}
function getTokenCount(str, padding = undefined) { function getTokenCount(str, padding = undefined) {
if (typeof str !== 'string') { if (typeof str !== 'string') {
return 0; return 0;
@ -563,6 +582,10 @@ function getTokenCount(str, padding = undefined) {
} }
} }
if (tokenizerType === tokenizers.BEST_MATCH) {
tokenizerType = getTokenizerBestMatch();
}
if (padding === undefined) { if (padding === undefined) {
padding = 0; padding = 0;
} }
@ -1229,8 +1252,8 @@ function messageFormatting(mes, ch_name, isSystem, isUser) {
mes = fixMarkdown(mes); mes = fixMarkdown(mes);
} }
if (this_chid != undefined && !isSystem) //if (this_chid != undefined && !isSystem)
mes = mes.replaceAll("<", "&lt;").replaceAll(">", "&gt;"); //for welcome message // mes = mes.replaceAll("<", "&lt;").replaceAll(">", "&gt;"); //for welcome message
if ((this_chid === undefined || this_chid === "invalid-safety-id") && !selected_group) { if ((this_chid === undefined || this_chid === "invalid-safety-id") && !selected_group) {
mes = mes mes = mes
.replace(/\*\*(.+?)\*\*/g, "<b>$1</b>") .replace(/\*\*(.+?)\*\*/g, "<b>$1</b>")
@ -1727,7 +1750,11 @@ function getStoppingStrings(isImpersonate, addSpace) {
if (power_user.custom_stopping_strings) { if (power_user.custom_stopping_strings) {
const customStoppingStrings = getCustomStoppingStrings(); const customStoppingStrings = getCustomStoppingStrings();
result.push(...customStoppingStrings); if (power_user.custom_stopping_strings_macro) {
result.push(...customStoppingStrings.map(x => substituteParams(x, name1, name2)));
} else {
result.push(...customStoppingStrings);
}
} }
return addSpace ? result.map(x => `${x} `) : result; return addSpace ? result.map(x => `${x} `) : result;
@ -2669,8 +2696,11 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
setPromtString(); setPromtString();
} }
// add chat preamble
mesSendString = addChatsPreamble(mesSendString);
// add a custom dingus (if defined) // add a custom dingus (if defined)
mesSendString = adjustChatsSeparator(mesSendString); mesSendString = addChatsSeparator(mesSendString);
let finalPromt = let finalPromt =
storyString + storyString +
@ -3156,16 +3186,13 @@ function parseTokenCounts(counts, thisPromptBits) {
}); });
} }
function adjustChatsSeparator(mesSendString) { function addChatsPreamble(mesSendString) {
if (main_api === 'novel') { const preamble = main_api === 'novel' ? nai_settings.preamble : "";
let preamble = "\n***\n" + nai_settings.nai_preamble; return preamble + '\n' + mesSendString;
if (!preamble.endsWith('\n')) { }
preamble += '\n';
}
mesSendString = preamble + mesSendString;
}
else if (power_user.custom_chat_separator && power_user.custom_chat_separator.length) { function addChatsSeparator(mesSendString) {
if (power_user.custom_chat_separator && power_user.custom_chat_separator.length) {
mesSendString = power_user.custom_chat_separator + '\n' + mesSendString; mesSendString = power_user.custom_chat_separator + '\n' + mesSendString;
} }
@ -3174,6 +3201,10 @@ function adjustChatsSeparator(mesSendString) {
mesSendString = mesSendString; mesSendString = mesSendString;
} }
else if (main_api === 'novel') {
mesSendString = '\n***\n' + mesSendString;
}
// add non-pygma dingus // add non-pygma dingus
else if (!is_pygmalion) { else if (!is_pygmalion) {
mesSendString = '\nThen the roleplay chat between ' + name1 + ' and ' + name2 + ' begins.\n' + mesSendString; mesSendString = '\nThen the roleplay chat between ' + name1 + ' and ' + name2 + ' begins.\n' + mesSendString;
@ -7005,13 +7036,13 @@ function doCloseChat() {
* *
* @param {string} popup_type - The type of popup currently active. * @param {string} popup_type - The type of popup currently active.
* @param {string} this_chid - The character ID to be deleted. * @param {string} this_chid - The character ID to be deleted.
* @param {boolean} delete_chats - Whether to delete chats or not.
*/ */
export async function handleDeleteCharacter(popup_type, this_chid) { export async function handleDeleteCharacter(popup_type, this_chid, delete_chats) {
if (popup_type !== "del_ch") { if (popup_type !== "del_ch") {
return; return;
} }
const delete_chats = !!$("#del_char_checkbox").prop("checked");
const avatar = characters[this_chid].avatar; const avatar = characters[this_chid].avatar;
const name = characters[this_chid].name; const name = characters[this_chid].name;
@ -7449,7 +7480,8 @@ $(document).ready(function () {
}, 200); }, 200);
} }
if (popup_type == "del_ch") { if (popup_type == "del_ch") {
handleDeleteCharacter(popup_type, this_chid, characters); const deleteChats = !!$("#del_char_checkbox").prop("checked");
await handleDeleteCharacter(popup_type, this_chid, deleteChats);
} }
if (popup_type == "alternate_greeting" && menu_type !== "create") { if (popup_type == "alternate_greeting" && menu_type !== "create") {
createOrEditCharacter(); createOrEditCharacter();

View File

@ -1,4 +1,4 @@
import { characters, getCharacters, saveSettingsDebounced, handleDeleteCharacter } from "../../../script.js"; import { characters, getCharacters, handleDeleteCharacter, callPopup } from "../../../script.js";
let is_bulk_edit = false; let is_bulk_edit = false;
@ -27,7 +27,7 @@ function onEditButtonClick() {
* @param {string} this_chid - The chid of the character to delete. * @param {string} this_chid - The chid of the character to delete.
*/ */
async function deleteCharacter(this_chid) { async function deleteCharacter(this_chid) {
await handleDeleteCharacter("del_ch", this_chid); await handleDeleteCharacter("del_ch", this_chid, false);
} }
/** /**
@ -45,6 +45,13 @@ async function onDeleteButtonClick() {
toDelete.push(avatar); toDelete.push(avatar);
}); });
const confirm = await callPopup('<h3>Are you sure you want to delete these characters?</h3>You would need to delete the chat files manually.<br>', 'confirm');
if (!confirm) {
console.log('User cancelled delete');
return;
}
// Delete the characters // Delete the characters
for (const avatar of toDelete) { for (const avatar of toDelete) {
console.log(`Deleting character with avatar ${avatar}`); console.log(`Deleting character with avatar ${avatar}`);
@ -78,7 +85,7 @@ function addButtons() {
* Enables bulk selection by adding a checkbox next to each character. * Enables bulk selection by adding a checkbox next to each character.
*/ */
function enableBulkSelect() { function enableBulkSelect() {
$(".character_select").each((i, el) => { $("#rm_print_characters_block .character_select").each((i, el) => {
const character = $(el).text(); const character = $(el).text();
const checkbox = $("<input type='checkbox' class='bulk_select_checkbox'>"); const checkbox = $("<input type='checkbox' class='bulk_select_checkbox'>");
checkbox.on("change", () => { checkbox.on("change", () => {
@ -86,6 +93,7 @@ function enableBulkSelect() {
}); });
$(el).prepend(checkbox); $(el).prepend(checkbox);
}); });
$("#rm_print_characters_block").addClass("bulk_select");
// We also need to disable the default click event for the character_select divs // We also need to disable the default click event for the character_select divs
$(document).on("click", ".bulk_select_checkbox", function (event) { $(document).on("click", ".bulk_select_checkbox", function (event) {
event.stopImmediatePropagation(); event.stopImmediatePropagation();
@ -97,6 +105,7 @@ function enableBulkSelect() {
*/ */
function disableBulkSelect() { function disableBulkSelect() {
$(".bulk_select_checkbox").remove(); $(".bulk_select_checkbox").remove();
$("#rm_print_characters_block").removeClass("bulk_select");
} }
/** /**

View File

@ -0,0 +1,7 @@
.bulk_select_checkbox {
align-self: center;
}
#rm_print_characters_block .wide100pLess70px {
width: calc(100% - 85px);
}

View File

@ -45,8 +45,6 @@ let lastCharacter = undefined;
let lastMessage = null; let lastMessage = null;
let spriteCache = {}; let spriteCache = {};
let inApiCall = false; let inApiCall = false;
let previousSrc = null;
function isVisualNovelMode() { function isVisualNovelMode() {
return Boolean(!isMobile() && power_user.waifuMode && getContext().groupId); return Boolean(!isMobile() && power_user.waifuMode && getContext().groupId);
@ -395,6 +393,21 @@ function onExpressionsShowDefaultInput() {
} }
} }
async function unloadLiveChar() {
try {
const url = new URL(getApiUrl());
url.pathname = '/api/live2d/unload';
const loadResponse = await doExtrasFetch(url);
if (!loadResponse.ok) {
throw new Error(loadResponse.statusText);
}
const loadResponseText = await loadResponse.text();
//console.log(`Response: ${loadResponseText}`);
} catch (error) {
//console.error(`Error unloading - ${error}`);
}
}
async function loadLiveChar() { async function loadLiveChar() {
if (!modules.includes('live2d')) { if (!modules.includes('live2d')) {
console.debug('live2d module is disabled'); console.debug('live2d module is disabled');
@ -456,7 +469,6 @@ function handleImageChange() {
} }
if (extension_settings.expressions.live2d) { if (extension_settings.expressions.live2d) {
previousSrc = imgElement.src;
// Method get IP of endpoint // Method get IP of endpoint
const live2dResultFeedSrc = `${getApiUrl()}/api/live2d/result_feed`; const live2dResultFeedSrc = `${getApiUrl()}/api/live2d/result_feed`;
$('#expression-holder').css({ display: '' }); $('#expression-holder').css({ display: '' });
@ -496,7 +508,6 @@ async function moduleWorker() {
if (context.groupId !== lastCharacter && context.characterId !== lastCharacter) { if (context.groupId !== lastCharacter && context.characterId !== lastCharacter) {
removeExpression(); removeExpression();
spriteCache = {}; spriteCache = {};
previousSrc = null;
//clear expression //clear expression
let imgElement = document.getElementById('expression-image'); let imgElement = document.getElementById('expression-image');
@ -611,12 +622,62 @@ async function moduleWorker() {
} }
} }
async function live2dcheck() {
const context = getContext();
let spriteFolderName = context.name2;
const message = getLastCharacterMessage();
const avatarFileName = getSpriteFolderName(message);
const expressionOverride = extension_settings.expressionOverrides.find((e) =>
e.name == avatarFileName
);
if (expressionOverride && expressionOverride.path) {
spriteFolderName = expressionOverride.path;
}
try {
await validateImages(spriteFolderName);
let live2dObj = spriteCache[spriteFolderName].find(obj => obj.label === 'live2d');
let live2dPath_f = live2dObj ? live2dObj.path : null;
if(live2dPath_f != null){
//console.log("live2dPath_f " + live2dPath_f);
return true;
} else {
//console.log("live2dPath_f is null");
unloadLiveChar();
return false;
}
} catch (err) {
return err;
}
}
function setLive2dState(switch_var){ function setLive2dState(switch_var){
extension_settings.expressions.live2d = switch_var; // Store setting extension_settings.expressions.live2d = switch_var; // Store setting
saveSettingsDebounced(); saveSettingsDebounced();
if (extension_settings.expressions.live2d) { loadLiveChar(); } // load char as needed live2dcheck().then(result => {
handleImageChange(switch_var); // Change image as needed if (result) {
//console.log("Live2d exists!");
if (extension_settings.expressions.live2d) {
loadLiveChar();
} else {
unloadLiveChar();
}
handleImageChange(switch_var); // Change image as needed
} else {
//console.log("Live2d does not exist.");
}
});
} }
function getSpriteFolderName(message) { function getSpriteFolderName(message) {
@ -917,13 +978,25 @@ async function setExpression(character, expression, force) {
document.getElementById("expression-holder").style.display = ''; document.getElementById("expression-holder").style.display = '';
} else { } else {
// Find the <img> element with id="expression-image" and class="expression"
const imgElement = document.querySelector('img#expression-image.expression');
//console.log("searching"); live2dcheck().then(result => {
if (imgElement) { if (result) {
console.log("setting value"); // Find the <img> element with id="expression-image" and class="expression"
imgElement.src = getApiUrl() + '/api/live2d/result_feed'; const imgElement = document.querySelector('img#expression-image.expression');
//console.log("searching");
if (imgElement) {
//console.log("setting value");
imgElement.src = getApiUrl() + '/api/live2d/result_feed';
}
} else {
//console.log("The fetch failed!");
} }
});
} }
} }

View File

@ -79,7 +79,7 @@ function loadNovelSettings(settings) {
$(`#model_novel_select option[value=${nai_settings.model_novel}]`).attr("selected", true); $(`#model_novel_select option[value=${nai_settings.model_novel}]`).attr("selected", true);
$('#model_novel_select').val(nai_settings.model_novel); $('#model_novel_select').val(nai_settings.model_novel);
if (settings.nai_preamble !== undefined) nai_settings.nai_preamble = settings.nai_preamble; if (settings.nai_preamble !== undefined) nai_settings.preamble = settings.nai_preamble;
nai_settings.preset_settings_novel = settings.preset_settings_novel; nai_settings.preset_settings_novel = settings.preset_settings_novel;
nai_settings.temperature = settings.temperature; nai_settings.temperature = settings.temperature;
nai_settings.repetition_penalty = settings.repetition_penalty; nai_settings.repetition_penalty = settings.repetition_penalty;
@ -347,13 +347,13 @@ export async function generateNovelWithStreaming(generate_data, signal) {
} }
$("#nai_preamble_textarea").on('input', function () { $("#nai_preamble_textarea").on('input', function () {
nai_settings.nai_preamble = $('#nai_preamble_textarea').val(); nai_settings.preamble = $('#nai_preamble_textarea').val();
saveSettingsDebounced(); saveSettingsDebounced();
}); });
$("#nai_preamble_restore").on('click', function () { $("#nai_preamble_restore").on('click', function () {
nai_settings.nai_preamble = default_preamble; nai_settings.preamble = default_preamble;
$('#nai_preamble_textarea').val(nai_settings.nai_preamble); $('#nai_preamble_textarea').val(nai_settings.preamble);
saveSettingsDebounced(); saveSettingsDebounced();
}); });

View File

@ -71,6 +71,7 @@ const tokenizers = {
NERD: 4, NERD: 4,
NERD2: 5, NERD2: 5,
API: 6, API: 6,
BEST_MATCH: 99,
} }
const send_on_enter_options = { const send_on_enter_options = {
@ -87,7 +88,7 @@ export const persona_description_positions = {
} }
let power_user = { let power_user = {
tokenizer: tokenizers.CLASSIC, tokenizer: tokenizers.BEST_MATCH,
token_padding: 64, token_padding: 64,
collapse_newlines: false, collapse_newlines: false,
pygmalion_formatting: pygmalion_options.AUTO, pygmalion_formatting: pygmalion_options.AUTO,
@ -187,6 +188,7 @@ let power_user = {
persona_show_notifications: true, persona_show_notifications: true,
custom_stopping_strings: '', custom_stopping_strings: '',
custom_stopping_strings_macro: true,
fuzzy_search: false, fuzzy_search: false,
}; };
@ -678,6 +680,7 @@ function loadPowerUserSettings(settings, data) {
$('#auto_swipe_blacklist').val(power_user.auto_swipe_blacklist.join(", ")); $('#auto_swipe_blacklist').val(power_user.auto_swipe_blacklist.join(", "));
$('#auto_swipe_blacklist_threshold').val(power_user.auto_swipe_blacklist_threshold); $('#auto_swipe_blacklist_threshold').val(power_user.auto_swipe_blacklist_threshold);
$('#custom_stopping_strings').val(power_user.custom_stopping_strings); $('#custom_stopping_strings').val(power_user.custom_stopping_strings);
$("#custom_stopping_strings_macro").prop("checked", power_user.custom_stopping_strings_macro);
$('#fuzzy_search_checkbox').prop("checked", power_user.fuzzy_search); $('#fuzzy_search_checkbox').prop("checked", power_user.fuzzy_search);
$('#persona_show_notifications').prop("checked", power_user.persona_show_notifications); $('#persona_show_notifications').prop("checked", power_user.persona_show_notifications);
@ -1995,6 +1998,11 @@ $(document).ready(() => {
saveSettingsDebounced(); saveSettingsDebounced();
}); });
$("#custom_stopping_strings_macro").change(function () {
power_user.custom_stopping_strings_macro = !!$(this).prop("checked");
saveSettingsDebounced();
});
$('#fuzzy_search_checkbox').on('input', function () { $('#fuzzy_search_checkbox').on('input', function () {
power_user.fuzzy_search = !!$(this).prop('checked'); power_user.fuzzy_search = !!$(this).prop('checked');
saveSettingsDebounced(); saveSettingsDebounced();

View File

@ -223,6 +223,12 @@ table.responsiveTable {
font-weight: 500; font-weight: 500;
} }
.mes_text blockquote {
border-left: 3px solid var(--SmartThemeQuoteColor);
padding-left: 10px;
background-color: var(--black30a);
}
.mes_text strong em, .mes_text strong em,
.mes_text strong, .mes_text strong,
.mes_text h2, .mes_text h2,
@ -1293,7 +1299,8 @@ body.charListGrid #rm_print_characters_block .tags_inline {
} }
.floating_prompt_radio_group, .radio_group { .floating_prompt_radio_group,
.radio_group {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
@ -3050,12 +3057,13 @@ h5 {
/* HEINOUS */ /* HEINOUS */
@keyframes infinite-spinning { @keyframes infinite-spinning {
from { from {
transform: rotate(0deg); transform: rotate(0deg);
} }
to {
transform: rotate(360deg); to {
} transform: rotate(360deg);
}
} }
#export_character_div { #export_character_div {
@ -5461,4 +5469,4 @@ body.waifuMode .zoomed_avatar {
background-color: var(--SmartThemeBlurTintColor); background-color: var(--SmartThemeBlurTintColor);
text-align: center; text-align: center;
line-height: 14px; line-height: 14px;
} }

View File

@ -1169,7 +1169,7 @@ app.post("/deletecharacter", jsonParser, async function (request, response) {
return response.sendStatus(403); return response.sendStatus(403);
} }
if (request.body.delete_chats == 'true') { if (request.body.delete_chats == true) {
try { try {
await fs.promises.rm(path.join(chatsPath, sanitize(dir_name)), { recursive: true, force: true }) await fs.promises.rm(path.join(chatsPath, sanitize(dir_name)), { recursive: true, force: true })
} catch (err) { } catch (err) {
@ -3475,7 +3475,7 @@ app.post("/tokenize_via_api", jsonParser, async function (request, response) {
body: JSON.stringify({ "prompt": text }), body: JSON.stringify({ "prompt": text }),
headers: { "Content-Type": "application/json" } headers: { "Content-Type": "application/json" }
}; };
if (main_api == 'textgenerationwebui' && request.body.use_mancer) { if (main_api == 'textgenerationwebui' && request.body.use_mancer) {
args.headers = Object.assign(args.headers, get_mancer_headers()); args.headers = Object.assign(args.headers, get_mancer_headers());
} }