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

This commit is contained in:
Cohee 2023-11-05 21:54:23 +02:00
commit c1e126985d
15 changed files with 770 additions and 261 deletions

View File

@ -1,3 +1,3 @@
<svg width="33" height="41" viewBox="0 0 33 41" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.89418 31.9285C4.51814 29.6818 2.83212 27.8112 0.836131 26.521C0.26793 26.1537 0.124452 25.3382 0.540438 24.8047C4.15593 20.1672 9.79294 8.01868 12.7415 1.40215C13.181 0.416062 14.6883 0.738582 14.6883 1.81816V19.44C13.1242 20.1331 12.0332 21.6992 12.0332 23.5201C12.0332 24.1851 12.1787 24.8161 12.4397 25.383L5.89418 31.9285ZM7.34675 34.6814C8.03773 36.2042 8.61427 37.8368 9.07635 39.5334C9.19588 39.9722 9.59101 40.2824 10.0459 40.2824H16.4937H22.9416C23.3964 40.2824 23.7916 39.9722 23.9111 39.5334C24.3732 37.8368 24.9497 36.2042 25.6407 34.6814L22.211 31.2516L19.3551 34.1075C19.4281 34.3655 19.4672 34.6378 19.4672 34.9192C19.4672 36.5615 18.1358 37.8928 16.4935 37.8928C14.8512 37.8928 13.5198 36.5615 13.5198 34.9192C13.5198 33.2768 14.8512 31.9455 16.4935 31.9455C16.7448 31.9455 16.9888 31.9766 17.2219 32.0353L20.1083 29.1489L18.4762 27.5169C17.879 27.8137 17.2058 27.9806 16.4937 27.9806C15.7816 27.9806 15.1084 27.8137 14.5112 27.5169L7.34675 34.6814ZM27.0933 31.9285C28.4693 29.6818 30.1553 27.8112 32.1513 26.521C32.7195 26.1537 32.863 25.3382 32.447 24.8047C28.8315 20.1672 23.1945 8.01868 20.2459 1.40215C19.8065 0.416062 18.2992 0.738582 18.2992 1.81816V19.44C19.8632 20.1332 20.9542 21.6992 20.9542 23.5201C20.9542 24.1851 20.8087 24.8161 20.5478 25.383L27.0933 31.9285Z" fill="white"/>
<svg width="33" height="41" viewBox="0 0 33 41" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.89418 31.9285C4.51814 29.6818 2.83212 27.8112 0.836131 26.521C0.26793 26.1537 0.124452 25.3382 0.540438 24.8047C4.15593 20.1672 9.79294 8.01868 12.7415 1.40215C13.181 0.416062 14.6883 0.738582 14.6883 1.81816V19.44C13.1242 20.1331 12.0332 21.6992 12.0332 23.5201C12.0332 24.1851 12.1787 24.8161 12.4397 25.383L5.89418 31.9285ZM7.34675 34.6814C8.03773 36.2042 8.61427 37.8368 9.07635 39.5334C9.19588 39.9722 9.59101 40.2824 10.0459 40.2824H16.4937H22.9416C23.3964 40.2824 23.7916 39.9722 23.9111 39.5334C24.3732 37.8368 24.9497 36.2042 25.6407 34.6814L22.211 31.2516L19.3551 34.1075C19.4281 34.3655 19.4672 34.6378 19.4672 34.9192C19.4672 36.5615 18.1358 37.8928 16.4935 37.8928C14.8512 37.8928 13.5198 36.5615 13.5198 34.9192C13.5198 33.2768 14.8512 31.9455 16.4935 31.9455C16.7448 31.9455 16.9888 31.9766 17.2219 32.0353L20.1083 29.1489L18.4762 27.5169C17.879 27.8137 17.2058 27.9806 16.4937 27.9806C15.7816 27.9806 15.1084 27.8137 14.5112 27.5169L7.34675 34.6814ZM27.0933 31.9285C28.4693 29.6818 30.1553 27.8112 32.1513 26.521C32.7195 26.1537 32.863 25.3382 32.447 24.8047C28.8315 20.1672 23.1945 8.01868 20.2459 1.40215C19.8065 0.416062 18.2992 0.738582 18.2992 1.81816V19.44C19.8632 20.1332 20.9542 21.6992 20.9542 23.5201C20.9542 24.1851 20.8087 24.8161 20.5478 25.383L27.0933 31.9285Z" />
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -123,7 +123,9 @@
<div data-i18n="clickslidertips" class="toggle-description wide100p editable-slider-notification">
Click slider numbers to input manually.
</div>
<a href="https://docs.sillytavern.app/usage/api-connections/koboldai/" target="_blank" title="Improved Samplers documentation coming soon."><span name="samplerHelpButton" class="note-link-span topRightInset fa-solid fa-circle-question"></span></a>
<a href="https://docs.sillytavern.app/usage/common-settings/" target="_blank" title="Documentation on sampling parameters.">
<span name="samplerHelpButton" class="note-link-span topRightInset fa-solid fa-circle-question"></span>
</a>
<div class="scrollableInner">
<div class="flex-container" id="ai_response_configuration">
<div id="respective-presets-block" class="width100p">
@ -474,7 +476,7 @@
<input class="neo-range-input" type="number" min="0" max="4096" step="1" data-for="rep_pen_range_textgenerationwebui" id="rep_pen_range_counter_textgenerationwebui">
</div>
<div data-forAphro=False data-newbie-hidden class="alignitemscenter flex-container marginBot5 flexFlowColumn flexBasis48p flexGrow flexShrink gap0" data-i18n="Encoder Rep. Pen.">
<small>Encoder Repetition Penalty
<small>Encoder Penalty
</small>
<input class="neo-range-slider" type="range" id="encoder_rep_pen_textgenerationwebui" name="volume" min="0.8" max="1.5" step="0.01" />
@ -1303,6 +1305,11 @@
<input class="neo-range-slider" type="range" id="typical_p_textgenerationwebui" name="volume" min="0" max="1" step="0.01">
<input class="neo-range-input" type="number" min="0" max="1" step="0.01" data-for="typical_p_textgenerationwebui" id="typical_p_counter_textgenerationwebui">
</div>
<div class="alignitemscenter flex-container flexFlowColumn flexBasis48p flexGrow flexShrink gap0" data-i18n="Min P">
<small>Min P</small>
<input class="neo-range-slider" type="range" id="min_p_textgenerationwebui" name="volume" min="0" max="1" step="0.01">
<input class="neo-range-input" type="number" min="0" max="1" step="0.05" data-for="min_p_textgenerationwebui" id="min_p_counter_textgenerationwebui">
</div>
<div class="alignitemscenter flex-container flexFlowColumn flexBasis48p flexGrow flexShrink gap0" data-i18n="Top A">
<small>Top A</small>
<input class="neo-range-slider" type="range" id="top_a_textgenerationwebui" name="volume" min="0" max="1" step="0.01">
@ -1376,6 +1383,12 @@
<input type="checkbox" id="skip_special_tokens_textgenerationwebui" />
<small data-i18n="Skip Special Tokens">Skip Special Tokens</small>
</label>
<label data-forAphro=False class="checkbox_label" for="temperature_last_textgenerationwebui">
<input type="checkbox" id="temperature_last_textgenerationwebui" />
<small data-i18n="Temperature Last">Temperature Last
<div class="fa-solid fa-circle-info opacity50p " data-i18n="Use the temperature sampler last." title="Use the temperature sampler last."></div>
</small>
</label>
<!--
<label data-forAphro=True class="checkbox_label" for="spaces_between_special_tokens_aphrodite_textgenerationwebui">
<input type="checkbox" id="spaces_between_special_tokens_aphrodite_textgenerationwebui" />
@ -1384,7 +1397,7 @@
-->
</div>
</div>
<div name="miroStatBlock">
<div name="miroStatBlock" class="wide100p">
<h4 class="wide100p textAlignCenter" data-i18n="Mirostat (mode=1 is only for llama.cpp)">Mirostat
<div class=" fa-solid fa-circle-info opacity50p " title="Mode=1 is only for llama.cpp&#13;More helpful tips coming soon."></div>
</h4>
@ -2510,114 +2523,154 @@
</h3>
</div>
<div id="wi-holder" class="margin5">
<div class="justifyContentSpaceAround wi-settings flex-container gap10px alignitemscenter">
<div id="WIMultiSelector" class="flex2 flex alignSelfStart range-block">
<div class="range-block-title justifyLeft">
<span data-i18n="Active World(s) for all chats"><small>Active World(s) for all chats</small></span>
</div>
<div class="range-block-range">
<select id="world_info" multiple>
<option value="">
<span data-i18n="-- World Info not found --">-- World Info not found --</span>
</option>
</select>
</div>
<div id="WIMultiSelector" class="flex2 flex alignSelfStart range-block">
<div class="range-block-title justifyLeft">
<span data-i18n="Active World(s) for all chats"><small>Active World(s) for all chats</small></span>
</div>
<div class="flex2 flex-container flexFlowColumn">
<div data-newbie-hidden class="flex range-block">
<div class="range-block-title justifyLeft">
<label for="world_info_character_strategy">
<span data-i18n="Character Lore Insertion Strategy"><small>Character Lore Insertion Strategy</small></span>
<div class="range-block-range">
<select id="world_info" multiple>
<option value="">
<span data-i18n="-- World Info not found --">-- World Info not found --</span>
</option>
</select>
</div>
</div>
<div data-newbie-hidden class="inline-drawer wide100p flexFlowColumn">
<div class="inline-drawer-toggle inline-drawer-header">
<b><span data-i18n="Activation Settings">Activation Settings</span></b>
<div class="fa-solid fa-circle-chevron-down inline-drawer-icon down"></div>
</div>
<div class="inline-drawer-content">
<div class="justifyContentSpaceAround wi-settings flex-container gap10px alignitemscenter">
<div class="flex2 flex-container flexFlowColumn">
<div data-newbie-hidden class="flex range-block">
<div class="range-block-title justifyLeft">
<label for="world_info_character_strategy">
<span data-i18n="Character Lore Insertion Strategy"><small>Character Lore Insertion Strategy</small></span>
</label>
</div>
<div class="range-block-range">
<select id="world_info_character_strategy" class="flexGrow margin0">
<option value="0" data-i18n="Sorted Evenly">Sorted Evenly</option>
<option value="1" data-i18n="Character Lore First">Character Lore First</option>
<option value="2" data-i18n="Global Lore First">Global Lore First</option>
</select>
</div>
</div>
<div name="WIScanAndTokens" class="flex1 flex-container flexFlowColumn">
<div data-newbie-hidden class="flex1 gap5px range-block">
<div class="wide10pMinFit">
<small data-i18n="Scan Depth">Scan Depth</small>
</div>
<div class="range-block-range-and-counter">
<div class="range-block-range paddingLeftRight5">
<input type="range" id="world_info_depth" name="volume" min="0" max="100" step="1">
</div>
<div class="range-block-counter margin0">
<input type="number" data-for="world_info_depth" id="world_info_depth_counter">
</div>
</div>
</div>
<div class="flex1 gap5px range-block">
<div class="wide10pMinFit">
<small data-i18n="Context %">Context %</small>
</div>
<div class="range-block-range-and-counter ">
<div class="range-block-range paddingLeftRight5">
<input type="range" id="world_info_budget" name="volume" min="1" max="100" step="1">
</div>
<div class="range-block-counter margin0">
<input type="number" min="1" max="100" step="1" data-for="world_info_budget" id="world_info_budget_counter">
</div>
</div>
</div>
<div data-newbie-hidden class="flex1 gap5px range-block">
<div class="wide10pMinFit">
<small data-i18n="Budget Cap">Budget Cap</small>
</div>
<div class="range-block-range-and-counter ">
<div class="range-block-range paddingLeftRight5">
<input type="range" id="world_info_budget_cap" name="volume" min="0" max="8192" step="1">
</div>
<div class="range-block-counter margin0">
<input type="number" min="0" max="8192" step="1" data-for="world_info_budget_cap" id="world_info_budget_cap_counter">
</div>
</div>
<div class="budget_cap_note">
<small data-i18n="(0 = disabled)">(0 = disabled)</small>
</div>
</div>
<div data-newbie-hidden class="flex1 gap5px range-block" title="Scan chronologically until reached min entries or token budget." data-i18n="[title]Scan chronologically until reached min entries or token budget.">
<div class="wide10pMinFit">
<small data-i18n="Min Activations">Min Activations</small>
</div>
<div class="range-block-range-and-counter">
<div class="range-block-range paddingLeftRight5">
<input type="range" id="world_info_min_activations" name="volume" min="0" max="100" step="1">
</div>
<div class="range-block-counter margin0">
<input type="number" data-for="world_info_min_activations" id="world_info_min_activations_counter">
</div>
</div>
</div>
<div data-newbie-hidden class="flex1 gap5px range-block">
<div class="wide10pMinFit">
<small data-i18n="Max Depth">Max Depth</small>
</div>
<div class="range-block-range-and-counter">
<div class="range-block-range paddingLeftRight5">
<input type="range" id="world_info_min_activations_depth_max" name="volume" min="0" max="100" step="1">
</div>
<div class="range-block-counter margin0">
<input type="number" data-for="world_info_min_activations_depth_max" id="world_info_min_activations_depth_max_counter">
</div>
</div>
<div class="budget_cap_note">
<small data-i18n="(0 = unlimited, use budget)">(0 = unlimited, use budget)</small>
</div>
</div>
</div>
</div>
<div id="worldInfoScanningCheckboxes" data-newbie-hidden class="alignitemsflexstart flex1 flex-container flexFlowColumn">
<label title="Entries can activate other entries by mentioning their keywords" data-i18n="[title]Entries can activate other entries by mentioning their keywords" class="checkbox_label flex1">
<input id="world_info_recursive" type="checkbox" />
<small data-i18n="Recursive Scan" class="whitespacenowrap flex1">
Recursive Scan
</small>
</label>
<label title="Lookup for the entry keys in the context will respect the case" data-i18n="[title]Lookup for the entry keys in the context will respect the case" class="checkbox_label flex1">
<input id="world_info_case_sensitive" type="checkbox" />
<small data-i18n="Case Sensitive" class="whitespacenowrap flex1">
Case-sensitive
</small>
</label>
<label title="If the entry key consists of only one word, it would not be matched as part of other words" data-i18n="[title]If the entry key consists of only one word, it would not be matched as part of other words" class="checkbox_label flex1">
<input id="world_info_match_whole_words" type="checkbox" />
<small data-i18n="Match whole words" class="whitespacenowrap flex1">
Match whole words
</small>
</label>
<label title="Alert if your world info is greater than the allocated budget." data-i18n="[title]Alert if your world info is greater than the allocated budget." class="checkbox_label flex1">
<input id="world_info_overflow_alert" type="checkbox" />
<small data-i18n="Alert On Overflow" class="whitespacenowrap flex1">
Alert On Overflow
</small>
</label>
</div>
<div class="range-block-range">
<select id="world_info_character_strategy" class="flexGrow margin0">
<option value="0" data-i18n="Sorted Evenly">Sorted Evenly</option>
<option value="1" data-i18n="Character Lore First">Character Lore First</option>
<option value="2" data-i18n="Global Lore First">Global Lore First</option>
</select>
</div>
</div>
<div name="WIScanAndTokens" class="flex1 flex-container flexFlowColumn">
<div data-newbie-hidden class="flex1 gap5px range-block">
<div class="wide10pMinFit">
<small data-i18n="Scan Depth">Scan Depth</small>
</div>
<div class="range-block-range-and-counter">
<div class="range-block-range paddingLeftRight5">
<input type="range" id="world_info_depth" name="volume" min="0" max="100" step="1">
</div>
<div class="range-block-counter margin0">
<input type="number" data-for="world_info_depth" id="world_info_depth_counter">
</div>
</div>
</div>
<div class="flex1 gap5px range-block">
<div class="wide10pMinFit">
<small data-i18n="Context %">Context %</small>
</div>
<div class="range-block-range-and-counter ">
<div class="range-block-range paddingLeftRight5">
<input type="range" id="world_info_budget" name="volume" min="1" max="100" step="1">
</div>
<div class="range-block-counter margin0">
<input type="number" min="1" max="100" step="1" data-for="world_info_budget" id="world_info_budget_counter">
</div>
</div>
</div>
<div data-newbie-hidden class="flex1 gap5px range-block">
<div class="wide10pMinFit">
<small data-i18n="Budget Cap">Budget Cap</small>
</div>
<div class="range-block-range-and-counter ">
<div class="range-block-range paddingLeftRight5">
<input type="range" id="world_info_budget_cap" name="volume" min="0" max="8192" step="1">
</div>
<div class="range-block-counter margin0">
<input type="number" min="0" max="8192" step="1" data-for="world_info_budget_cap" id="world_info_budget_cap_counter">
</div>
</div>
<div class="budget_cap_note">
<small data-i18n="(0 = disabled)">(0 = disabled)</small>
</div>
</div>
</div>
</div>
<div id="worldInfoScanningCheckboxes" data-newbie-hidden class="alignitemsflexstart flex1 flex-container flexFlowColumn">
<label title="Entries can activate other entries by mentioning their keywords" data-i18n="[title]Entries can activate other entries by mentioning their keywords" class="checkbox_label flex1">
<input id="world_info_recursive" type="checkbox" />
<small data-i18n="Recursive Scan" class="whitespacenowrap flex1">
Recursive Scan
</small>
</label>
<label title="Lookup for the entry keys in the context will respect the case" data-i18n="[title]Lookup for the entry keys in the context will respect the case" class="checkbox_label flex1">
<input id="world_info_case_sensitive" type="checkbox" />
<small data-i18n="Case Sensitive" class="whitespacenowrap flex1">
Case-sensitive
</small>
</label>
<label title="If the entry key consists of only one word, it would not be matched as part of other words" data-i18n="[title]If the entry key consists of only one word, it would not be matched as part of other words" class="checkbox_label flex1">
<input id="world_info_match_whole_words" type="checkbox" />
<small data-i18n="Match whole words" class="whitespacenowrap flex1">
Match whole words
</small>
</label>
<label title="Alert if your world info is greater than the allocated budget." data-i18n="[title]Alert if your world info is greater than the allocated budget." class="checkbox_label flex1">
<input id="world_info_overflow_alert" type="checkbox" />
<small data-i18n="Alert On Overflow" class="whitespacenowrap flex1">
Alert On Overflow
</small>
</label>
</div>
<div id="WIInputWidthReference" style="display:none; height:1px;">10000</div>
</div>
<div id="world_popup">
@ -2852,6 +2905,11 @@
<span data-i18n="Auto-Expand Message Actions">Expand Message Actions</span>
</label>
<label data-newbie-hidden for="enableZenSliders" class="checkbox_label">
<input id="enableZenSliders" type="checkbox" />
<span data-i18n="Zen Sliders">Zen Sliders</span>
</label>
<label data-newbie-hidden for="messageTimerEnabled" class="checkbox_label">
<input id="messageTimerEnabled" type="checkbox" />
<span data-i18n="Message Timer">Message Timer</span>

View File

@ -93,6 +93,7 @@ import {
openai_messages_count,
chat_completion_sources,
getChatCompletionModel,
isOpenRouterWithInstruct,
} from "./scripts/openai.js";
import {
@ -260,7 +261,7 @@ export {
}
// Cohee: Uncomment when we decide to use loader
// showLoader();
showLoader();
// Allow target="_blank" in links
DOMPurify.addHook('afterSanitizeAttributes', function (node) {
@ -324,6 +325,7 @@ reloadMarkdownProcessor();
// array for prompt token calculations
console.debug('initializing Prompt Itemization Array on Startup');
const promptStorage = new localforage.createInstance({ name: "SillyTavern_Prompts" });
let itemizedPrompts = [];
export const systemUserName = "SillyTavern System";
@ -595,11 +597,12 @@ function reloadMarkdownProcessor(render_formulas = false) {
}
function getCurrentChatId() {
console.debug(`selectedGroup:${selected_group}, this_chid:${this_chid}`)
if (selected_group) {
return groups.find(x => x.id == selected_group)?.chat_id;
}
else if (this_chid) {
return characters[this_chid].chat;
return characters[this_chid]?.chat;
}
}
@ -713,6 +716,7 @@ async function firstLoadInit() {
const tokenData = await tokenResponse.json();
token = tokenData.token;
} catch {
hideLoader();
toastr.error("Couldn't get CSRF token. Please refresh the page.", "Error", { timeOut: 0, extendedTimeOut: 0, preventDuplicates: true });
throw new Error("Initialization failed");
}
@ -734,7 +738,7 @@ async function firstLoadInit() {
initCfg();
doDailyExtensionUpdatesCheck();
// Cohee: Uncomment when we decide to use loader
// hideLoader();
hideLoader();
}
function checkOnlineStatus() {
@ -771,6 +775,92 @@ export function setActiveGroup(group) {
active_group = group;
}
/**
* Gets the itemized prompts for a chat.
* @param {string} chatId Chat ID to load
*/
export async function loadItemizedPrompts(chatId) {
try {
if (!chatId) {
itemizedPrompts = [];
return;
}
itemizedPrompts = await promptStorage.getItem(chatId);
if (!itemizedPrompts) {
itemizedPrompts = [];
}
} catch {
console.log("Error loading itemized prompts for chat", chatId);
itemizedPrompts = [];
}
}
/**
* Saves the itemized prompts for a chat.
* @param {string} chatId Chat ID to save itemized prompts for
*/
export async function saveItemizedPrompts(chatId) {
try {
if (!chatId) {
return;
}
await promptStorage.setItem(chatId, itemizedPrompts);
} catch {
console.log("Error saving itemized prompts for chat", chatId);
}
}
/**
* Replaces the itemized prompt text for a message.
* @param {number} mesId Message ID to get itemized prompt for
* @param {string} promptText New raw prompt text
* @returns
*/
export async function replaceItemizedPromptText(mesId, promptText) {
if (!Array.isArray(itemizedPrompts)) {
itemizedPrompts = [];
}
const itemizedPrompt = itemizedPrompts.find(x => x.mesId === mesId);
if (!itemizedPrompt) {
return;
}
itemizedPrompt.rawPrompt = promptText;
}
/**
* Deletes the itemized prompts for a chat.
* @param {string} chatId Chat ID to delete itemized prompts for
*/
export async function deleteItemizedPrompts(chatId) {
try {
if (!chatId) {
return;
}
await promptStorage.removeItem(chatId);
} catch {
console.log("Error deleting itemized prompts for chat", chatId);
}
}
/**
* Empties the itemized prompts array and caches.
*/
export async function clearItemizedPrompts() {
try {
await promptStorage.clear();
itemizedPrompts = [];
} catch {
console.log("Error clearing itemized prompts");
}
}
async function getStatus() {
if (is_get_status) {
if (main_api == "koboldhorde") {
@ -848,7 +938,7 @@ function resultCheckStatus() {
$("#api_button_textgenerationwebui").css("display", "inline-block");
}
export function selectCharacterById(id) {
export async function selectCharacterById(id) {
if (characters[id] == undefined) {
return;
}
@ -865,15 +955,15 @@ export function selectCharacterById(id) {
if (selected_group || this_chid !== id) {
//if clicked on a different character from what was currently selected
if (!is_send_press) {
await clearChat();
cancelTtsPlay();
resetSelectedGroup();
this_edit_mes_id = undefined;
selected_button = "character_edit";
this_chid = id;
clearChat();
chat.length = 0;
chat_metadata = {};
getChat();
await getChat();
}
} else {
//if clicked on character that was already selected
@ -1065,7 +1155,7 @@ async function delChat(chatfile) {
}
async function replaceCurrentChat() {
clearChat();
await clearChat();
chat.length = 0;
const chatsResponse = await fetch("/getallchatsofcharacter", {
@ -1133,7 +1223,7 @@ async function printMessages() {
}
}
function clearChat() {
async function clearChat() {
count_view_mes = 0;
extension_prompts = {};
$("#chat").children().remove();
@ -1141,6 +1231,8 @@ function clearChat() {
console.debug('saw avatars to remove')
$('.zoomed_avatar[forChar]').remove();
} else { console.debug('saw no avatars') }
await saveItemizedPrompts(getCurrentChatId());
itemizedPrompts = [];
}
@ -1152,7 +1244,7 @@ async function deleteLastMessage() {
}
export async function reloadCurrentChat() {
clearChat();
await clearChat();
chat.length = 0;
if (selected_group) {
@ -1182,6 +1274,11 @@ function messageFormatting(mes, ch_name, isSystem, isUser) {
isSystem = false;
}
// Let hidden messages have markdown
if (isSystem && ch_name !== systemUserName) {
isSystem = false;
}
// Prompt bias replacement should be applied on the raw message
if (!power_user.show_user_prompt_bias && ch_name && !isUser && !isSystem) {
mes = mes.replaceAll(substituteParams(power_user.user_prompt_bias), "");
@ -2631,6 +2728,13 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
coreChat.pop();
}
coreChat = coreChat.map(x => ({
...x,
mes: getRegexedString(x.mes, x.is_user ? regex_placement.USER_INPUT : regex_placement.AI_OUTPUT, {
isPrompt: true,
}),
}))
// Determine token limit
let this_max_context = getMaxContextSize();
@ -2835,7 +2939,8 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
if (isContinue) {
// Coping mechanism for OAI spacing
if ((main_api === 'openai') && !cyclePrompt.endsWith(' ')) {
const isForceInstruct = isOpenRouterWithInstruct();
if (main_api === 'openai' && !isForceInstruct && !cyclePrompt.endsWith(' ')) {
cyclePrompt += ' ';
continue_mag += ' ';
}
@ -3232,8 +3337,15 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
thisPromptBits = additionalPromptStuff;
//console.log(thisPromptBits);
const itemizedIndex = itemizedPrompts.findIndex((item) => item.mesId === thisPromptBits['mesId']);
if (itemizedIndex !== -1) {
itemizedPrompts[itemizedIndex] = thisPromptBits;
}
else {
itemizedPrompts.push(thisPromptBits);
}
itemizedPrompts.push(thisPromptBits);
console.debug(`pushed prompt bits to itemizedPrompts array. Length is now: ${itemizedPrompts.length}`);
if (main_api == 'openai') {
@ -3452,7 +3564,7 @@ function unblockGeneration() {
$("#send_textarea").removeAttr('disabled');
}
function getNextMessageId(type) {
export function getNextMessageId(type) {
return type == 'swipe' ? Number(count_view_mes - 1) : Number(count_view_mes);
}
@ -4354,7 +4466,7 @@ async function renameCharacter() {
if (newChId !== -1) {
// Select the character after the renaming
this_chid = -1;
selectCharacterById(String(newChId));
await selectCharacterById(String(newChId));
// Async delay to update UI
await delay(1);
@ -4647,6 +4759,7 @@ async function getChatResult() {
chat.push(message);
await saveChatConditional();
}
await loadItemizedPrompts(getCurrentChatId());
await printMessages();
select_selected_character(this_chid);
@ -4668,7 +4781,7 @@ function getFirstMessage() {
is_user: false,
is_system: false,
send_date: getMessageTimeStamp(),
mes: getRegexedString(firstMes, regex_placement.AI_OUTPUT),
mes: substituteParams(getRegexedString(firstMes, regex_placement.AI_OUTPUT)),
extra: {},
};
@ -4682,8 +4795,8 @@ function getFirstMessage() {
}
async function openCharacterChat(file_name) {
await clearChat();
characters[this_chid]["chat"] = file_name;
clearChat();
chat.length = 0;
chat_metadata = {};
await getChat();
@ -4888,7 +5001,7 @@ export function setUserName(value) {
if (power_user.persona_show_notifications) {
toastr.success(`Your messages will now be sent as ${name1}`, 'Current persona updated');
}
saveSettings("change_name");
saveSettingsDebounced();
}
function setUserAvatar() {
@ -5199,26 +5312,13 @@ async function saveSettings(type) {
kai_settings: kai_settings,
oai_settings: oai_settings,
}, null, 4),
beforeSend: function () {
if (type == "change_name") {
//let nameBeforeChange = name1;
name1 = $("#your_name").val();
//$(`.mes[ch_name="${nameBeforeChange}"]`).attr('ch_name' === name1);
//console.log('beforeSend name1 = ' + nameBeforeChange);
//console.log('new name: ' + name1);
}
},
beforeSend: function () { },
cache: false,
dataType: "json",
contentType: "application/json",
//processData: false,
success: async function (data) {
//online_status = data.result;
eventSource.emit(event_types.SETTINGS_UPDATED);
if (type == "change_name") {
clearChat();
await printMessages();
}
},
error: function (jqXHR, exception) {
toastr.error('Check the server connection and reload the page to prevent data loss.', 'Settings could not be saved');
@ -5300,7 +5400,7 @@ function openMessageDelete() {
$("#send_form").css("display", "none");
$(".del_checkbox").each(function () {
if ($(this).parent().attr("mesid") != 0) {
$(this).css("display", "block");
$(this).css("display", "grid");
$(this).parent().children(".for_checkbox").css("display", "none");
}
});
@ -5450,6 +5550,12 @@ export async function displayPastChats() {
const group = selected_group ? groups.find(x => x.id === selected_group) : null;
const data = await (selected_group ? getGroupPastChats(selected_group) : getPastCharacterChats());
if (!data) {
toastr.error('Could not load chat data. Try reloading the page.');
return;
}
const currentChat = selected_group ? group?.chat_id : characters[this_chid]["chat"];
const displayName = selected_group ? group?.name : characters[this_chid].name;
const avatarImg = selected_group ? group?.avatar_url : getThumbnailUrl('avatar', characters[this_chid]['avatar']);
@ -5674,7 +5780,7 @@ function select_rm_info(type, charId, previousCharId = null) {
export function select_selected_character(chid) {
//character select
//console.log('select_selected_character() -- starting with input of -- '+chid+' (name:'+characters[chid].name+')');
//console.log('select_selected_character() -- starting with input of -- ' + chid + ' (name:' + characters[chid].name + ')');
select_rm_create();
menu_type = "character_edit";
$("#delete_button").css("display", "flex");
@ -6042,8 +6148,9 @@ export async function saveChatConditional() {
await saveChat();
}
// Save token cache to IndexedDB storage
// Save token and prompts cache to IndexedDB storage
saveTokenCache();
saveItemizedPrompts(getCurrentChatId());
} catch (error) {
console.error('Error saving chat', error);
} finally {
@ -6502,7 +6609,7 @@ async function createOrEditCharacter(e) {
const chat_id = (chat.length - 1);
await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id);
clearChat();
await clearChat();
await printMessages();
await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, chat_id);
await saveChatConditional();
@ -7141,6 +7248,7 @@ export async function handleDeleteCharacter(popup_type, this_chid, delete_chats)
* @param {string} avatar - The avatar URL of the character to be deleted.
*/
export async function deleteCharacter(name, avatar) {
await clearChat();
$("#character_cross").click();
this_chid = "invalid-safety-id";
characters.length = 0;
@ -7148,7 +7256,6 @@ export async function deleteCharacter(name, avatar) {
chat = [...safetychat];
chat_metadata = {};
$(document.getElementById("rm_button_selected_ch")).children("h2").text("");
clearChat();
this_chid = undefined;
delete tag_map[avatar];
await getCharacters();
@ -7161,6 +7268,44 @@ function doTogglePanels() {
$("#option_settings").trigger('click')
}
function addDebugFunctions() {
registerDebugFunction('backfillTokenCounts', 'Backfill token counters',
`Recalculates token counts of all messages in the current chat to refresh the counters.
Useful when you switch between models that have different tokenizers.
This is a visual change only. Your chat will be reloaded.`, async () => {
for (const message of chat) {
// System messages are not counted
if (message.is_system) {
continue;
}
if (!message.extra) {
message.extra = {};
}
message.extra.token_count = getTokenCount(message.mes, 0);
}
await saveChatConditional();
await reloadCurrentChat();
});
registerDebugFunction('generationTest', 'Send a generation request', 'Generates text using the currently selected API.', async () => {
const text = prompt('Input text:', 'Hello');
toastr.info('Working on it...');
const message = await generateRaw(text, null);
alert(message);
});
registerDebugFunction('clearPrompts', 'Delete itemized prompts', 'Deletes all itemized prompts from the local storage.', async () => {
await clearItemizedPrompts();
toastr.info('Itemized prompts deleted.');
if (getCurrentChatId()) {
await reloadCurrentChat();
}
});
}
jQuery(async function () {
if (isMobile() === true) {
@ -7277,9 +7422,9 @@ jQuery(async function () {
$("#character_search_bar").val("").trigger("input");
});
$(document).on("click", ".character_select", function () {
$(document).on("click", ".character_select", async function () {
const id = $(this).attr("chid");
selectCharacterById(id);
await selectCharacterById(id);
});
$(document).on("input", ".edit_textarea", function () {
@ -7431,7 +7576,7 @@ jQuery(async function () {
menu_type != "create"
) {
//Fix it; New chat doesn't create while open create character menu
clearChat();
await clearChat();
chat.length = 0;
if (selected_group) {
@ -7748,7 +7893,7 @@ jQuery(async function () {
/* $('#set_chat_scenario').on('click', setScenarioOverride); */
///////////// OPTIMIZED LISTENERS FOR LEFT SIDE OPTIONS POPUP MENU //////////////////////
$("#options [id]").on("click", function (event, customData) {
$("#options [id]").on("click", async function (event, customData) {
const fromSlashCommand = customData?.fromSlashCommand || false;
var id = $(this).attr("id");
@ -7812,7 +7957,7 @@ jQuery(async function () {
else if (id == "option_close_chat") {
if (is_send_press == false) {
clearChat();
await clearChat();
chat.length = 0;
resetSelectedGroup();
setCharacterId(undefined);
@ -8804,7 +8949,7 @@ jQuery(async function () {
}
});
$(document).on('input', '.range-block-counter input', function () {
$(document).on('input', '.range-block-counter input, .neo-range-input', function () {
setTimeout(() => {
const caretPosition = saveCaretPosition($(this).get(0));
const myText = $(this).val().trim();
@ -8961,31 +9106,12 @@ jQuery(async function () {
// Added here to prevent execution before script.js is loaded and get rid of quirky timeouts
await firstLoadInit();
registerDebugFunction('backfillTokenCounts', 'Backfill token counters',
`Recalculates token counts of all messages in the current chat to refresh the counters.
Useful when you switch between models that have different tokenizers.
This is a visual change only. Your chat will be reloaded.`, async () => {
for (const message of chat) {
// System messages are not counted
if (message.is_system) {
continue;
}
addDebugFunctions();
if (!message.extra) {
message.extra = {};
}
message.extra.token_count = getTokenCount(message.mes, 0);
}
await saveChatConditional();
await reloadCurrentChat();
eventSource.on(event_types.CHAT_DELETED, async (name) => {
await deleteItemizedPrompts(name);
});
registerDebugFunction('generationTest', 'Send a generation request', 'Generates text using the currently selected API.', async () => {
const text = prompt('Input text:', 'Hello');
toastr.info('Working on it...');
const message = await generateRaw(text, null);
alert(message);
eventSource.on(event_types.GROUP_CHAT_DELETED, async (name) => {
await deleteItemizedPrompts(name);
});
});

View File

@ -268,11 +268,11 @@ async function RA_autoloadchat() {
let active_character_id = Object.keys(characters).find(key => characters[key].avatar === active_character);
if (active_character_id !== null) {
selectCharacterById(String(active_character_id));
await selectCharacterById(String(active_character_id));
}
if (active_group != null) {
openGroupById(String(active_group));
await openGroupById(String(active_group));
}
// if the character list hadn't been loaded yet, try again.

View File

@ -86,6 +86,10 @@
<input type="checkbox" name="only_format_display" />
<span data-i18n="Only Format Display">Only Format Display</span>
</label>
<label class="checkbox flex-container" title="Chat history won't change, only the prompt as the request is sent (on generation)">
<input type="checkbox" name="only_format_prompt"/>
<span data-i18n="Only Format Prompt (?)">Only Format Prompt (?)</span>
</label>
<label class="checkbox flex-container">
<input type="checkbox" name="run_on_edit" />
<span data-i18n="Run On Edit">Run On Edit</span>

View File

@ -38,19 +38,24 @@ function regexFromString(input) {
}
// Parent function to fetch a regexed version of a raw string
function getRegexedString(rawString, placement, { characterOverride, isMarkdown } = {}) {
function getRegexedString(rawString, placement, { characterOverride, isMarkdown, isPrompt } = {}) {
let finalString = rawString;
if (extension_settings.disabledExtensions.includes("regex") || !rawString || placement === undefined) {
return finalString;
}
extension_settings.regex.forEach((script) => {
if ((script.markdownOnly && !isMarkdown) || (!script.markdownOnly && isMarkdown)) {
return;
}
if (script.placement.includes(placement)) {
finalString = runRegexScript(script, finalString, { characterOverride });
if (
// Script applies to Markdown and input is Markdown
(script.markdownOnly && isMarkdown) ||
// Script applies to Generate and input is Generate
(script.promptOnly && isPrompt) ||
// Script applies to all cases when neither "only"s are true, but there's no need to do it when `isMarkdown`, the as source (chat history) should already be changed beforehand
(!script.markdownOnly && !script.promptOnly && !isMarkdown)
) {
if (script.placement.includes(placement)) {
finalString = runRegexScript(script, finalString, { characterOverride });
}
}
});

View File

@ -113,6 +113,9 @@ async function onRegexEditorOpenClick(existingId) {
editorHtml
.find(`input[name="only_format_display"]`)
.prop("checked", existingScript.markdownOnly ?? false);
editorHtml
.find(`input[name="only_format_prompt"]`)
.prop("checked", existingScript.promptOnly ?? false);
editorHtml
.find(`input[name="run_on_edit"]`)
.prop("checked", existingScript.runOnEdit ?? false);
@ -165,6 +168,10 @@ async function onRegexEditorOpenClick(existingId) {
editorHtml
.find(`input[name="only_format_display"]`)
.prop("checked"),
promptOnly:
editorHtml
.find(`input[name="only_format_prompt"]`)
.prop("checked"),
runOnEdit:
editorHtml
.find(`input[name="run_on_edit"]`)
@ -197,6 +204,7 @@ function migrateSettings() {
script.placement = script.placement.filter((e) => e !== regex_placement.MD_DISPLAY);
script.markdownOnly = true
script.promptOnly = true
performSave = true;
}

View File

@ -68,6 +68,7 @@ import {
setExternalAbortController,
baseChatReplace,
depth_prompt_depth_default,
loadItemizedPrompts,
} from "../script.js";
import { appendTagToList, createTagMapFromList, getTagsList, applyTagsOnCharacterSelect, tag_map, printTagFilters } from './tags.js';
import { FILTER_TYPES, FilterHelper } from './filters.js';
@ -168,6 +169,8 @@ export async function getGroupChat(groupId) {
const chat_id = group.chat_id;
const data = await loadGroupChat(chat_id);
await loadItemizedPrompts(getCurrentChatId());
if (Array.isArray(data) && data.length) {
data[0].is_group = true;
for (let key of data) {
@ -913,10 +916,10 @@ async function deleteGroup(id) {
}
if (response.ok) {
await clearChat();
selected_group = null;
delete tag_map[id];
resetChatState();
clearChat();
await printMessages();
await getCharacters();
@ -1385,12 +1388,12 @@ export async function openGroupById(groupId) {
if (!is_send_press && !is_group_generating) {
if (selected_group !== groupId) {
await clearChat();
cancelTtsPlay();
selected_group = groupId;
setCharacterId(undefined);
setCharacterName('');
setEditedMessageId(undefined);
clearChat();
updateChatMetadata({}, true);
chat.length = 0;
await getGroupChat(groupId);
@ -1484,7 +1487,7 @@ export async function createNewGroupChat(groupId) {
group.past_metadata = {};
}
clearChat();
await clearChat();
chat.length = 0;
if (oldChatName) {
group.past_metadata[oldChatName] = Object.assign({}, chat_metadata);
@ -1537,7 +1540,7 @@ export async function openGroupChat(groupId, chatId) {
return;
}
clearChat();
await clearChat();
chat.length = 0;
const previousChat = group.chat_id;
group.past_metadata[previousChat] = Object.assign({}, chat_metadata);

View File

@ -25,6 +25,9 @@ import {
event_types,
substituteParams,
MAX_INJECTION_DEPTH,
getStoppingStrings,
getNextMessageId,
replaceItemizedPromptText,
} from "../script.js";
import { groups, selected_group } from "./group-chats.js";
@ -367,14 +370,19 @@ function convertChatCompletionToInstruct(messages, type) {
}
const isImpersonate = type === 'impersonate';
const isContinue = type === 'continue';
const promptName = isImpersonate ? name1 : name2;
const promptLine = formatInstructModePrompt(promptName, isImpersonate, '', name1, name2).trimStart();
const promptLine = isContinue ? '' : formatInstructModePrompt(promptName, isImpersonate, '', name1, name2).trimStart();
const prompt = [systemPromptText, examplesText, chatMessagesText, promptLine]
let prompt = [systemPromptText, examplesText, chatMessagesText, promptLine]
.filter(x => x)
.map(x => x.endsWith('\n') ? x : `${x}\n`)
.join('');
if (isContinue) {
prompt = prompt.replace(/\n$/, '');
}
return prompt;
}
@ -578,6 +586,10 @@ function populationInjectionPrompts(prompts) {
openai_msgs = openai_msgs.reverse();
}
export function isOpenRouterWithInstruct() {
return oai_settings.chat_completion_source === chat_completion_sources.OPENROUTER && oai_settings.openrouter_force_instruct && power_user.instruct.enabled;
}
/**
* Populates the chat history of the conversation.
*
@ -604,7 +616,8 @@ function populateChatHistory(prompts, chatCompletion, type = null, cyclePrompt =
// Reserve budget for continue nudge
let continueMessage = null;
if (type === 'continue' && cyclePrompt) {
const instruct = isOpenRouterWithInstruct();
if (type === 'continue' && cyclePrompt && !instruct) {
const continuePrompt = new Prompt({
identifier: 'continueNudge',
role: 'system',
@ -1249,7 +1262,7 @@ function saveModelList(data) {
}
}
async function sendAltScaleRequest(openai_msgs_tosend, logit_bias, signal) {
async function sendAltScaleRequest(openai_msgs_tosend, logit_bias, signal, type) {
const generate_url = '/generate_altscale';
let firstSysMsgs = []
@ -1269,6 +1282,8 @@ async function sendAltScaleRequest(openai_msgs_tosend, logit_bias, signal) {
}, "");
openai_msgs_tosend = substituteParams(joinedSubsequentMsgs);
const messageId = getNextMessageId(type);
replaceItemizedPromptText(messageId, openai_msgs_tosend);
const generate_data = {
sysprompt: joinedSysMsgs,
@ -1304,6 +1319,7 @@ async function sendOpenAIRequest(type, openai_msgs_tosend, signal) {
openai_msgs_tosend = openai_msgs_tosend.filter(msg => msg && typeof msg === 'object');
let logit_bias = {};
const messageId = getNextMessageId(type);
const isClaude = oai_settings.chat_completion_source == chat_completion_sources.CLAUDE;
const isOpenRouter = oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER;
const isScale = oai_settings.chat_completion_source == chat_completion_sources.SCALE;
@ -1317,6 +1333,7 @@ async function sendOpenAIRequest(type, openai_msgs_tosend, signal) {
if (isTextCompletion && isOpenRouter) {
openai_msgs_tosend = convertChatCompletionToInstruct(openai_msgs_tosend, type);
replaceItemizedPromptText(messageId, openai_msgs_tosend);
}
if (isAI21 || isPalm) {
@ -1325,6 +1342,7 @@ async function sendOpenAIRequest(type, openai_msgs_tosend, signal) {
return acc + (prefix ? (selected_group ? "\n" : prefix + " ") : "") + obj.content + "\n";
}, "");
openai_msgs_tosend = substituteParams(joinedMsgs) + (isImpersonate ? `${name1}:` : `${name2}:`);
replaceItemizedPromptText(messageId, openai_msgs_tosend);
}
// If we're using the window.ai extension, use that instead
@ -1343,7 +1361,7 @@ async function sendOpenAIRequest(type, openai_msgs_tosend, signal) {
}
if (isScale && oai_settings.use_alt_scale) {
return sendAltScaleRequest(openai_msgs_tosend, logit_bias, signal)
return sendAltScaleRequest(openai_msgs_tosend, logit_bias, signal, type);
}
const model = getChatCompletionModel();
@ -1382,6 +1400,10 @@ async function sendOpenAIRequest(type, openai_msgs_tosend, signal) {
generate_data['use_openrouter'] = true;
generate_data['top_k'] = Number(oai_settings.top_k_openai);
generate_data['use_fallback'] = oai_settings.openrouter_use_fallback;
if (isTextCompletion) {
generate_data['stop'] = getStoppingStrings(isImpersonate);
}
}
if (isScale) {

View File

@ -162,6 +162,7 @@ let power_user = {
max_context_unlocked: false,
message_token_count_enabled: false,
expand_message_actions: false,
enableZenSliders: false,
prefer_character_prompt: true,
prefer_character_jailbreak: true,
quick_continue: false,
@ -251,6 +252,7 @@ const storage_keys = {
mesIDDisplay_enabled: 'mesIDDisplayEnabled',
message_token_count_enabled: 'MessageTokenCountEnabled',
expand_message_actions: 'ExpandMessageActions',
enableZenSliders: 'enableZenSliders',
};
const contextControls = [
@ -419,6 +421,148 @@ function switchMessageActions() {
$('.extraMesButtons, .extraMesButtonsHint').removeAttr('style');
}
async function switchZenSliders() {
const value = localStorage.getItem(storage_keys.enableZenSliders);
power_user.enableZenSliders = value === null ? false : value == "true";
$("body").toggleClass("enableZenSliders", power_user.enableZenSliders);
$("#enableZenSliders").prop("checked", power_user.enableZenSliders);
function revertOriginalSliders() {
$("#range_block_textgenerationwebui input[type='number']").show();
$("#textgenerationwebui_api-settings input[type='number']").show();
$("#pro-settings-block input[type='number']").show();
$(`#range_block_textgenerationwebui input[type='range'],
#textgenerationwebui_api-settings input[type='range'],
#pro-settings-block input[type='range']`).each(function () {
$(this).show();
});
$('div[id$="_zenslider"]').remove();
}
if (power_user.enableZenSliders) {
$("#range_block_textgenerationwebui input[type='number']").hide();
$("#textgenerationwebui_api-settings input[type='number']").hide();
$("#pro-settings-block input[type='number']").hide();
$("#seed_textgenerationwebui").show();
$(`#range_block_textgenerationwebui input[type='range'],
#textgenerationwebui_api-settings input[type='range'],
#pro-settings-block input[type='range']`).each(
function () {
CreateZenSliders($(this))
}
)
} else {
revertOriginalSliders();
}
async function CreateZenSliders(elmnt) {
await delay(100)
var originalSlider = elmnt;
var sliderID = originalSlider.attr('id')
var sliderMin = Number(originalSlider.attr('min'))
var sliderMax = Number(originalSlider.attr('max'))
var sliderValue = originalSlider.val();
var sliderRange = sliderMax - sliderMin
var midpoint = sliderRange / 2
var numSteps = 10
var decimals = 2
if (sliderID == 'rep_pen_range_textgenerationwebui') {
numSteps = 16
decimals = 0
}
if (sliderID == 'amount_gen') {
decimals = 0
}
if (sliderID == 'max_context') {
numSteps = 15
decimals = 0
}
if (sliderID == 'encoder_rep_pen_textgenerationwebui') {
numSteps = 14
}
if (sliderID == 'mirostat_mode_textgenerationwebui') {
numSteps = 2
decimals = 0
}
if (sliderID == 'mirostat_tau_textgenerationwebui' ||
sliderID == 'top_k_textgenerationwebui' ||
sliderID == 'num_beams_textgenerationwebui' ||
sliderID == 'no_repeat_ngram_size_textgenerationwebui') {
numSteps = 20
decimals = 0
}
if (sliderID == 'epsilon_cutoff_textgenerationwebui') {
numSteps = 20
decimals = 1
}
if (sliderID == 'tfs_textgenerationwebui' ||
sliderID == 'min_p_textgenerationwebui') {
numSteps = 20
decimals = 2
}
if (sliderID == 'mirostat_eta_textgenerationwebui' ||
sliderID == 'penalty_alpha_textgenerationwebui' ||
sliderID == 'length_penalty_textgenerationwebui') {
numSteps = 50
}
if (sliderID == 'eta_cutoff_textgenerationwebui') {
numSteps = 50
decimals = 1
}
if (sliderID == 'guidance_scale_textgenerationwebui') {
numSteps = 78
}
if (sliderID == 'min_length_textgenerationwebui') {
decimals = 0
}
if (sliderID == 'temp_textgenerationwebui') {
numSteps = 20
}
var stepScale = sliderRange / numSteps
var newSlider = $("<div>")
.attr('id', `${sliderID}_zenslider`)
.css("width", "100%")
.insertBefore(originalSlider);
newSlider.slider({
value: sliderValue,
step: stepScale,
min: sliderMin,
max: sliderMax,
create: function () {
var handle = $(this).find(".ui-slider-handle");
var handleText = Number(sliderValue).toFixed(decimals)
handle.text(handleText);
//var width = handle.width()
var stepNumber = ((sliderValue - sliderMin) / stepScale)
var leftMargin = (stepNumber / numSteps) * 50 * -1
handle.css('margin-left', `${leftMargin}px`)
},
slide: function (event, ui) {
var handle = $(this).find(".ui-slider-handle");
//var width = handle.outerWidth()
handle.text(ui.value.toFixed(decimals));
var stepNumber = ((ui.value - sliderMin) / stepScale)
var leftMargin = (stepNumber / numSteps) * 50 * -1
handle.css('margin-left', `${leftMargin}px`)
let handleText = (ui.value)
originalSlider.val(handleText);
originalSlider.trigger('input')
originalSlider.trigger('change')
}
});
originalSlider.data("newSlider", newSlider);
originalSlider.hide();
};
}
function switchUiMode() {
const fastUi = localStorage.getItem(storage_keys.fast_ui_mode);
power_user.fast_ui_mode = fastUi === null ? true : fastUi == "true";
@ -780,6 +924,13 @@ async function applyTheme(name) {
switchMessageActions();
}
},
{
key: 'enableZenSliders',
action: async () => {
localStorage.setItem(storage_keys.enableZenSliders, Boolean(power_user.enableZenSliders));
switchMessageActions();
}
},
{
key: 'hotswap_enabled',
action: async () => {
@ -894,6 +1045,7 @@ function loadPowerUserSettings(settings, data) {
const timestamps = localStorage.getItem(storage_keys.timestamps_enabled);
const mesIDDisplay = localStorage.getItem(storage_keys.mesIDDisplay_enabled);
const expandMessageActions = localStorage.getItem(storage_keys.expand_message_actions);
const enableZenSliders = localStorage.getItem(storage_keys.enableZenSliders);
power_user.fast_ui_mode = fastUi === null ? true : fastUi == "true";
power_user.movingUI = movingUI === null ? false : movingUI == "true";
power_user.noShadows = noShadows === null ? false : noShadows == "true";
@ -902,6 +1054,7 @@ function loadPowerUserSettings(settings, data) {
power_user.timestamps_enabled = timestamps === null ? true : timestamps == "true";
power_user.mesIDDisplay_enabled = mesIDDisplay === null ? true : mesIDDisplay == "true";
power_user.expand_message_actions = expandMessageActions === null ? true : expandMessageActions == "true";
power_user.enableZenSliders = enableZenSliders === null ? false : enableZenSliders == "true";
power_user.avatar_style = Number(localStorage.getItem(storage_keys.avatar_style) ?? avatar_styles.ROUND);
//power_user.chat_display = Number(localStorage.getItem(storage_keys.chat_display) ?? chat_styles.DEFAULT);
power_user.chat_width = Number(localStorage.getItem(storage_keys.chat_width) ?? 50);
@ -983,6 +1136,7 @@ function loadPowerUserSettings(settings, data) {
$("#mesIDDisplayEnabled").prop("checked", power_user.mesIDDisplay_enabled);
$("#prefer_character_prompt").prop("checked", power_user.prefer_character_prompt);
$("#prefer_character_jailbreak").prop("checked", power_user.prefer_character_jailbreak);
$("#enableZenSliders").prop('checked', power_user.enableZenSliders).trigger('input');
$(`input[name="avatar_style"][value="${power_user.avatar_style}"]`).prop("checked", true);
$(`#chat_display option[value=${power_user.chat_display}]`).attr("selected", true).trigger('change');
$('#chat_width_slider').val(power_user.chat_width);
@ -1402,7 +1556,7 @@ async function saveTheme() {
mesIDDisplay_enabled: power_user.mesIDDisplay_enabled,
message_token_count_enabled: power_user.message_token_count_enabled,
expand_message_actions: power_user.expand_message_actions,
enableZenSliders: power_user.enableZenSliders,
hotswap_enabled: power_user.hotswap_enabled,
custom_css: power_user.custom_css,
@ -2346,6 +2500,13 @@ $(document).ready(() => {
switchMessageActions();
});
$("#enableZenSliders").on("input", function () {
const value = !!$(this).prop('checked');
power_user.enableZenSliders = value;
localStorage.setItem(storage_keys.enableZenSliders, Boolean(power_user.enableZenSliders));
switchZenSliders();
});
$("#mesIDDisplayEnabled").on("input", function () {
const value = !!$(this).prop('checked');
power_user.mesIDDisplay_enabled = value;

View File

@ -639,21 +639,34 @@ async function sendCommentMessage(_, text) {
await saveChatConditional();
}
/**
* Displays a help message from the slash command
* @param {any} _ Unused
* @param {string} type Type of help to display
*/
function helpCommandCallback(_, type) {
switch (type?.trim()) {
switch (type?.trim()?.toLowerCase()) {
case 'slash':
case 'commands':
case 'slashes':
case 'slash commands':
case '1':
sendSystemMessage(system_message_types.SLASH_COMMANDS);
break;
case 'format':
case 'formatting':
case 'formats':
case 'chat formatting':
case '2':
sendSystemMessage(system_message_types.FORMATTING);
break;
case 'hotkeys':
case 'hotkey':
case '3':
sendSystemMessage(system_message_types.HOTKEYS);
break;
case 'macros':
case 'macro':
case '4':
sendSystemMessage(system_message_types.MACROS);
break;

View File

@ -29,6 +29,7 @@ export const textgen_types = {
const textgenerationwebui_settings = {
temp: 0.7,
temperature_last: true,
top_p: 0.5,
top_k: 40,
top_a: 0,
@ -36,6 +37,7 @@ const textgenerationwebui_settings = {
epsilon_cutoff: 0,
eta_cutoff: 0,
typical_p: 1,
min_p: 0,
rep_pen: 1.2,
rep_pen_range: 0,
no_repeat_ngram_size: 0,
@ -81,6 +83,7 @@ export let textgenerationwebui_preset_names = [];
const setting_names = [
"temp",
"temperature_last",
"rep_pen",
"rep_pen_range",
"no_repeat_ngram_size",
@ -91,6 +94,7 @@ const setting_names = [
"epsilon_cutoff",
"eta_cutoff",
"typical_p",
"min_p",
"penalty_alpha",
"num_beams",
"length_penalty",
@ -122,7 +126,7 @@ const setting_names = [
//'prompt_log_probs_aphrodite'
];
function selectPreset(name) {
async function selectPreset(name) {
const preset = textgenerationwebui_presets[textgenerationwebui_preset_names.indexOf(name)];
if (!preset) {
@ -351,6 +355,14 @@ function setSettingByName(i, value, trigger) {
const val = parseFloat(value);
$(`#${i}_textgenerationwebui`).val(val);
$(`#${i}_counter_textgenerationwebui`).val(val);
if (power_user.enableZenSliders) {
let zenSlider = $(`#${i}_textgenerationwebui_zenslider`).slider()
zenSlider.slider('option', 'value', val)
zenSlider.slider('option', 'slide')
.call(zenSlider, null, {
handle: $('.ui-slider-handle', zenSlider), value: val
});
}
}
if (trigger) {
@ -446,8 +458,10 @@ export function getTextGenGenerationData(finalPrompt, this_amount_gen, isImperso
'max_new_tokens': this_amount_gen,
'do_sample': textgenerationwebui_settings.do_sample,
'temperature': textgenerationwebui_settings.temp,
'temperature_last': textgenerationwebui_settings.temperature_last,
'top_p': textgenerationwebui_settings.top_p,
'typical_p': textgenerationwebui_settings.typical_p,
'min_p': textgenerationwebui_settings.min_p,
'repetition_penalty': textgenerationwebui_settings.rep_pen,
'repetition_penalty_range': textgenerationwebui_settings.rep_pen_range,
'encoder_repetition_penalty': textgenerationwebui_settings.encoder_rep_pen,

View File

@ -12,6 +12,8 @@ export {
world_info,
world_info_budget,
world_info_depth,
world_info_min_activations,
world_info_min_activations_depth_max,
world_info_recursive,
world_info_overflow_alert,
world_info_case_sensitive,
@ -35,6 +37,9 @@ let world_info = {};
let selected_world_info = [];
let world_names;
let world_info_depth = 2;
let world_info_min_activations = 0; // if > 0, will continue seeking chat until minimum world infos are activated
let world_info_min_activations_depth_max = 0; // used when (world_info_min_activations > 0)
let world_info_budget = 25;
let world_info_recursive = false;
let world_info_overflow_alert = false;
@ -55,14 +60,14 @@ const worldInfoFilter = new FilterHelper(() => updateEditor());
const SORT_ORDER_KEY = 'world_info_sort_order';
const METADATA_KEY = 'world_info';
const InputWidthReference = $("#WIInputWidthReference");
const DEFAULT_DEPTH = 4;
export function getWorldInfoSettings() {
return {
world_info,
world_info_depth,
world_info_min_activations,
world_info_min_activations_depth_max,
world_info_budget,
world_info_recursive,
world_info_overflow_alert,
@ -102,6 +107,10 @@ async function getWorldInfoPrompt(chat2, maxContext) {
function setWorldInfoSettings(settings, data) {
if (settings.world_info_depth !== undefined)
world_info_depth = Number(settings.world_info_depth);
if (settings.world_info_min_activations !== undefined)
world_info_min_activations = Number(settings.world_info_min_activations);
if (settings.world_info_min_activations_depth_max !== undefined)
world_info_min_activations_depth_max = Number(settings.world_info_min_activations_depth_max);
if (settings.world_info_budget !== undefined)
world_info_budget = Number(settings.world_info_budget);
if (settings.world_info_recursive !== undefined)
@ -138,6 +147,12 @@ function setWorldInfoSettings(settings, data) {
$("#world_info_depth_counter").val(world_info_depth);
$("#world_info_depth").val(world_info_depth);
$("#world_info_min_activations_counter").val(world_info_min_activations);
$("#world_info_min_activations").val(world_info_min_activations);
$("#world_info_min_activations_depth_max_counter").val(world_info_min_activations_depth_max);
$("#world_info_min_activations_depth_max").val(world_info_min_activations_depth_max);
$("#world_info_budget_counter").val(world_info_budget);
$("#world_info_budget").val(world_info_budget);
@ -367,24 +382,23 @@ function displayWorldEntries(name, data, navigation = navigation_option.none) {
<small class="flex1">
Title/Memo
</small>
<small style="width:${InputWidthReference.width() + 5 + 'px'}">
<small style="width: calc(3.5em + 5px)">
Status
</small>
<small style="width:${InputWidthReference.width() + 20 + 'px'}">
<small style="width: calc(3.5em + 20px)">
Position
</small>
<small style="width:${InputWidthReference.width() + 15 + 'px'}">
<small style="width: calc(3.5em + 15px)">
Depth
</small>
<small style="width:${InputWidthReference.width() + 15 + 'px'}">
<small style="width: calc(3.5em + 15px)">
Order
</small>
<small style="width:${InputWidthReference.width() + 15 + 'px'}">
<small style="width: calc(3.5em + 15px)">
Trigger %
</small>
</div>`
const blocks = page.map(entry => getWorldEntry(name, data, entry));
const blocks = page.map(entry => getWorldEntry(name, data, entry)).filter(x => x);
$("#world_popup_entries_list").append(keywordHeaders);
$("#world_popup_entries_list").append(blocks);
},
@ -545,6 +559,10 @@ function deleteOriginalDataValue(data, uid) {
}
function getWorldEntry(name, data, entry) {
if (!data.entries[entry.uid]) {
return;
}
const template = $("#entry_edit_template .world_entry").clone();
template.data("uid", entry.uid);
template.attr("uid", entry.uid);
@ -819,7 +837,7 @@ function getWorldEntry(name, data, entry) {
saveWorldInfo(name, data);
});
orderInput.val(entry.order).trigger("input");
orderInput.width(InputWidthReference.width() + 15 + 'px')
orderInput.css('width', 'calc(3em + 15px)');
// probability
if (entry.probability === undefined) {
@ -840,7 +858,7 @@ function getWorldEntry(name, data, entry) {
saveWorldInfo(name, data);
});
depthInput.val(entry.depth ?? DEFAULT_DEPTH).trigger("input");
depthInput.width(InputWidthReference.width() + 15 + 'px');
depthInput.css('width', 'calc(3em + 15px)');
// Hide by default unless depth is specified
if (entry.position === world_info_position.atDepth) {
@ -868,7 +886,7 @@ function getWorldEntry(name, data, entry) {
saveWorldInfo(name, data);
});
probabilityInput.val(entry.probability).trigger("input");
probabilityInput.width(InputWidthReference.width() + 15 + 'px')
probabilityInput.css('width', 'calc(3em + 15px)');
// probability toggle
if (entry.useProbability === undefined) {
@ -1379,6 +1397,7 @@ async function checkWorldInfo(chat, maxContext) {
// Combine the chat
let textToScan = chat.slice(0, messagesToLookBack).join("");
let minActivationMsgIndex = messagesToLookBack; // tracks chat index to satisfy `world_info_min_activations`
// Add the depth or AN if enabled
// Put this code here since otherwise, the chat reference is modified
@ -1402,6 +1421,7 @@ async function checkWorldInfo(chat, maxContext) {
textToScan = transformString(textToScan);
let needsToScan = true;
let token_budget_overflowed = false;
let count = 0;
let allActivatedEntries = new Set();
let failedProbabilityChecks = new Set();
@ -1531,6 +1551,7 @@ async function checkWorldInfo(chat, maxContext) {
toastr.warning(`World info budget reached after ${allActivatedEntries.size} entries.`, 'World Info');
}
needsToScan = false;
token_budget_overflowed = true;
break;
}
@ -1553,6 +1574,24 @@ async function checkWorldInfo(chat, maxContext) {
textToScan = (currentlyActivatedText + '\n' + textToScan);
allActivatedText = (currentlyActivatedText + '\n' + allActivatedText);
}
// world_info_min_activations
if (!needsToScan && !token_budget_overflowed) {
if (world_info_min_activations > 0 && (allActivatedEntries.size < world_info_min_activations)) {
let over_max = false
over_max = (
world_info_min_activations_depth_max > 0 &&
minActivationMsgIndex > world_info_min_activations_depth_max
) || (
minActivationMsgIndex >= chat.length
)
if (!over_max) {
needsToScan = true
textToScan = transformString(chat.slice(minActivationMsgIndex, minActivationMsgIndex + 1).join(""));
minActivationMsgIndex += 1
}
}
}
}
// Forward-sorted list of entries for joining
@ -2027,7 +2066,7 @@ jQuery(() => {
$("#world_editor_select").on('change', async () => {
$("#world_info_search").val('');
worldInfoFilter.setFilterData(FILTER_TYPES.WORLD_INFO_SEARCH, '', true);
const selectedIndex = $("#world_editor_select").find(":selected").val();
const selectedIndex = String($("#world_editor_select").find(":selected").val());
if (selectedIndex === "") {
hideWorldEditor();
@ -2042,27 +2081,39 @@ jQuery(() => {
eventSource.emit(event_types.WORLDINFO_SETTINGS_UPDATED);
}
$(document).on("input", "#world_info_depth", function () {
$("#world_info_depth").on('input', function () {
world_info_depth = Number($(this).val());
$("#world_info_depth_counter").val($(this).val());
saveSettings();
});
$(document).on("input", "#world_info_budget", function () {
$("#world_info_min_activations").on('input', function () {
world_info_min_activations = Number($(this).val());
$("#world_info_min_activations_counter").val($(this).val());
saveSettings();
});
$("#world_info_min_activations_depth_max").on('input', function () {
world_info_min_activations_depth_max = Number($(this).val());
$("#world_info_min_activations_depth_max_counter").val($(this).val());
saveSettings();
});
$("#world_info_budget").on('input', function () {
world_info_budget = Number($(this).val());
$("#world_info_budget_counter").val($(this).val());
saveSettings();
});
$(document).on("input", "#world_info_recursive", function () {
$("#world_info_recursive").on('input', function () {
world_info_recursive = !!$(this).prop('checked');
saveSettings();
})
});
$('#world_info_case_sensitive').on('input', function () {
world_info_case_sensitive = !!$(this).prop('checked');
saveSettings();
})
});
$('#world_info_match_whole_words').on('input', function () {
world_info_match_whole_words = !!$(this).prop('checked');

View File

@ -24,6 +24,7 @@
--grey10: rgb(25, 25, 25);
--grey30: rgb(75, 75, 75);
--grey50: rgb(125, 125, 125);
--grey5020a: rgba(125, 125, 125, 0.2);
--grey70: rgb(175, 175, 175);
--grey75: rgb(190, 190, 190);
@ -2129,15 +2130,6 @@ grammarly-extension {
gap: 5px;
}
/* STLYES FOR THE CHAT MESSAGE DELETION CHECKBOXES */
/* ------------------------------------------------*/
.del_checkbox {
display: none;
opacity: 0.7;
margin-top: 12px;
margin-right: 12px;
}
/* Override toastr default styles */
body #toast-container {
@ -2156,47 +2148,57 @@ body #toast-container>div {
display: block;
}
input[type='checkbox']:not(#nav-toggle):not(#rm_button_panel_pin) {
input[type='checkbox']:not(#nav-toggle):not(#rm_button_panel_pin):not(#lm_button_panel_pin):not(#WI_panel_pin) {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
outline: none;
outline: 1px solid var(--grey5020a);
position: relative;
width: var(--mainFontSize);
height: var(--mainFontSize);
overflow: hidden;
border-radius: 3px;
background-color: white;
box-shadow: inset 0 0 3px 0 var(--black70a);
border: 1px solid var(--SmartThemeBorderColor);
background-color: var(--SmartThemeBlurTintColor);
box-shadow: inset 0 0 2px 0 var(--SmartThemeShadowColor);
cursor: pointer;
transform: translateY(-0.075em);
flex-shrink: 0;
place-content: center;
}
input[type='checkbox']:not(#nav-toggle):not(#rm_button_panel_pin):not(#lm_button_panel_pin)::after {
content: '';
color: var(--white100);
position: absolute;
top: 1px;
right: 1px;
bottom: 1px;
left: 1px;
background-color: var(--transparent);
background-size: contain;
background-position: center center;
background-repeat: no-repeat;
border-radius: 2px;
-webkit-transform: scale(0);
input[type='checkbox']:not(#nav-toggle):not(#rm_button_panel_pin):not(#lm_button_panel_pin):not(#WI_panel_pin):not(.del_checkbox) {
display: grid;
}
input[type="checkbox"]:not(#nav-toggle):not(#rm_button_panel_pin):not(#lm_button_panel_pin):not(#WI_panel_pin)::before {
content: "";
width: 0.65em;
height: 0.65em;
transform: scale(0);
-webkit-transition: 0.25s ease-in-out;
transition: 0.25s ease-in-out;
background-image: url("data:image/svg+xml;base64,PCEtLSBHZW5lcmF0ZWQgYnkgSWNvTW9vbi5pbyAtLT4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjQ0OCIgaGVpZ2h0PSI0NDgiIHZpZXdCb3g9IjAgMCA0NDggNDQ4Ij4KPHRpdGxlPjwvdGl0bGU+CjxnIGlkPSJpY29tb29uLWlnbm9yZSI+CjwvZz4KPHBhdGggZD0iTTQxNy43NSAxNDEuNWMwIDYuMjUtMi41IDEyLjUtNyAxN2wtMjE1IDIxNWMtNC41IDQuNS0xMC43NSA3LTE3IDdzLTEyLjUtMi41LTE3LTdsLTEyNC41LTEyNC41Yy00LjUtNC41LTctMTAuNzUtNy0xN3MyLjUtMTIuNSA3LTE3bDM0LTM0YzQuNS00LjUgMTAuNzUtNyAxNy03czEyLjUgMi41IDE3IDdsNzMuNSA3My43NSAxNjQtMTY0LjI1YzQuNS00LjUgMTAuNzUtNyAxNy03czEyLjUgMi41IDE3IDdsMzQgMzRjNC41IDQuNSA3IDEwLjc1IDcgMTd6Ij48L3BhdGg+Cjwvc3ZnPgo=");
transition: 120ms transform ease-in-out;
box-shadow: inset 1em 1em var(--SmartThemeBodyColor);
transform-origin: bottom left;
clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}
input[type='checkbox']:not(#nav-toggle):not(#rm_button_panel_pin):not(#lm_button_panel_pin):checked::after {
-webkit-transform: scale(1);
input[type="checkbox"]:not(#nav-toggle):not(#rm_button_panel_pin):not(#lm_button_panel_pin):not(#WI_panel_pin):checked::before {
transform: scale(1);
}
input[type="checkbox"]:not(#nav-toggle):not(#rm_button_panel_pin):not(#lm_button_panel_pin):not(#WI_panel_pin):disabled {
color: grey;
cursor: not-allowed;
}
.del_checkbox {
display: none;
opacity: 0.7;
margin-top: 12px;
margin-right: 12px;
}
#user_avatar_block {
display: flex;
grid-gap: 10px;
@ -2320,7 +2322,7 @@ input[type='checkbox']:not(#nav-toggle):not(#rm_button_panel_pin):not(#lm_button
border-radius: 7px 7px 0 0 !important;
background-size: 70% 100% !important;
background-repeat: no-repeat !important;
box-shadow: inset 0 0 2px black !important;
box-shadow: inset 0 0 2px var(--black50a) !important;
cursor: ew-resize !important;
}
@ -2698,12 +2700,9 @@ h5 {
margin: 0;
}
/* .select_chat_block_wrapper {
display: grid;
grid-template-columns: auto min-content;
align-items: center;
grid-gap: 10px;
} */
.select_chat_block_wrapper {
cursor: pointer;
}
.select_chat_block {
border-radius: 5px;
@ -2794,17 +2793,61 @@ body .ui-front {
z-index: 10000;
}
body .ui-slider-handle {
background-color: var(--SmartThemeBlurTintColor);
border: 1px solid var(--SmartThemeBorderColor) !important;
border-radius: 5px;
outline: 1px solid var(--grey5020a);
box-shadow: 0 0 3px var(--black50a);
text-shadow: 0px 0px calc(var(--shadowWidth) * 1px) var(--SmartThemeShadowColor);
width: 50px !important;
padding: 0 5px;
text-align: center;
margin-left: 0;
opacity: 1 !important;
transition: filter 200ms;
}
.ui-slider-handle.ui-state-default {
color: var(--SmartThemeBodyColor);
background: var(--SmartThemeBlurTintColor);
}
.ui-slider-handle:focus {
outline: none;
}
.ui-slider-handle.ui-state-hover {
color: var(--SmartThemeBodyColor);
background: var(--SmartThemeBlurTintColor);
filter: brightness(1.2)
}
.ui-slider-handle.ui-state-active {
color: var(--SmartThemeBodyColor);
background: var(--SmartThemeBlurTintColor);
filter: brightness(1.5);
border-color: var(--SmartThemeBorderColor) !important;
}
body .ui-widget-content {
background-color: var(--SmartThemeBlurTintColor);
border: 1px solid var(--SmartThemeBorderColor) !important;
border-radius: 10px;
box-shadow: 0 0 5px black;
box-shadow: 0 0 3px var(--black50a);
text-shadow: 0px 0px calc(var(--shadowWidth) * 1px) var(--SmartThemeShadowColor);
backdrop-filter: blur(calc(var(--SmartThemeBlurStrength)*2));
color: var(--SmartThemeBodyColor);
}
body .ui-widget-content .ui-state-active {
.ui-slider {
margin: 5px 0;
outline: 1px solid var(--grey5020a);
border-radius: 5px !important;
}
body .ui-widget-content .ui-state-active:not(.ui-slider-handle) {
margin: unset !important;
}
@ -3484,6 +3527,7 @@ a {
aspect-ratio: 2 / 3;
padding: 0;
border: 0;
background-color: transparent;
}
.zoomed_avatar img {