This commit is contained in:
RossAscends
2023-05-06 04:07:16 +09:00
9 changed files with 142 additions and 28 deletions

View File

@ -1185,6 +1185,15 @@
<option value="3">Sentencepiece (LLaMA)</option> <option value="3">Sentencepiece (LLaMA)</option>
</select> </select>
</div> </div>
<div class="range-block">
<div class="range-block-title justifyLeft">
Token Padding
<a href="/notes#tokenpadding" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</div>
<input id="token_padding" class="text_pole" type="number" min="-2048" max="2048" />
</div>
<label class="checkbox_label" for="always-force-name2-checkbox"> <label class="checkbox_label" for="always-force-name2-checkbox">
<input id="always-force-name2-checkbox" type="checkbox" /> <input id="always-force-name2-checkbox" type="checkbox" />
Always add character's name to prompt Always add character's name to prompt
@ -1501,6 +1510,10 @@
<input id="auto_fix_generated_markdown" type="checkbox" /> <input id="auto_fix_generated_markdown" type="checkbox" />
Auto-fix Markdown Auto-fix Markdown
</label> </label>
<label class="checkbox_label" for="allow_name2_display">
<input id="allow_name2_display" type="checkbox" />
Allow {{char}}: display in bot messages
</label>
<label for="auto_scroll_chat_to_bottom"> <label for="auto_scroll_chat_to_bottom">
<input id="auto_scroll_chat_to_bottom" type="checkbox" /> <input id="auto_scroll_chat_to_bottom" type="checkbox" />
Auto-scroll Chat Auto-scroll Chat
@ -1728,6 +1741,7 @@
<div id="rm_group_chats_block" class="right_menu"> <div id="rm_group_chats_block" class="right_menu">
<div id="rm_group_top_bar"> <div id="rm_group_top_bar">
<div id="rm_button_back_from_group" class="menu_button fa-solid fa-left-long"></div> <div id="rm_button_back_from_group" class="menu_button fa-solid fa-left-long"></div>
<div id="rm_group_scenario" class="menu_button fa-solid fa-scroll" title="Set a group chat scenario"></div>
<input id="rm_group_chat_name" class="text_pole" type="text" name="chat_name" placeholder="Chat Name (Optional)" maxlength="100" /> <input id="rm_group_chat_name" class="text_pole" type="text" name="chat_name" placeholder="Chat Name (Optional)" maxlength="100" />
<div id="group_favorite_button" class="menu_button fa-solid fa-star" title="Add to Favorites"></div> <div id="group_favorite_button" class="menu_button fa-solid fa-star" title="Add to Favorites"></div>
<input id="rm_group_fav" type="hidden" /> <input id="rm_group_fav" type="hidden" />
@ -1965,6 +1979,21 @@
<!-- templates for JS to reuse when needed --> <!-- templates for JS to reuse when needed -->
<div id="group_scenario_template" class="template_element">
<div class="group_scenario range-block flexFlowColumn flex-container">
<div class="range-block-title title_restorable">
<h3>Group Chat Scenario Override</h3>
<div title="Remove" class="menu_button fa-solid fa-trash-can remove_scenario_override"></div>
</div>
<div class="range-block-counter justifyLeft flex-container flexFlowColumn">
All group members will use the following scenario text instead of what is specified in their character cards.
</div>
<div class="range-block-range wide100p">
<textarea class="wide100p group_chat_scenario" class="text_pole" rows="5" placeholder="Type here..."></textarea>
</div>
</div>
</div>
<div id="past_chat_template" class="template_element"> <div id="past_chat_template" class="template_element">
<div class="select_chat_block_wrapper"> <div class="select_chat_block_wrapper">
<div class="select_chat_block" file_name=""> <div class="select_chat_block" file_name="">

View File

@ -422,6 +422,8 @@ To import Character.AI chats, use this tool: [https://github.com/0x000011b/chara
## Tokenizer ## Tokenizer
**Important: This section doesn't apply to OpenAI API. SillyTavern will always use a matching tokenizer for OpenAI models.**
A tokenizer is a tool that breaks down a piece of text into smaller units called tokens. These tokens can be individual words or even parts of words, such as prefixes, suffixes, or punctuation. A rule of thumb is that one token generally corresponds to 3~4 characters of text. A tokenizer is a tool that breaks down a piece of text into smaller units called tokens. These tokens can be individual words or even parts of words, such as prefixes, suffixes, or punctuation. A rule of thumb is that one token generally corresponds to 3~4 characters of text.
SillyTavern can use the following tokenizers while forming a request to the AI backend: SillyTavern can use the following tokenizers while forming a request to the AI backend:
@ -431,6 +433,18 @@ SillyTavern can use the following tokenizers while forming a request to the AI b
3. (Legacy) GPT-2/3 tokenizer. Used by original TavernAI. **Pick this if you're unsure.** More info: [gpt-2-3-tokenizer](https://github.com/josephrocca/gpt-2-3-tokenizer). 3. (Legacy) GPT-2/3 tokenizer. Used by original TavernAI. **Pick this if you're unsure.** More info: [gpt-2-3-tokenizer](https://github.com/josephrocca/gpt-2-3-tokenizer).
4. Sentencepiece tokenizer. Used by LLaMA model family: Alpaca, Vicuna, Koala, etc. **Pick if you use a LLaMA model.** 4. Sentencepiece tokenizer. Used by LLaMA model family: Alpaca, Vicuna, Koala, etc. **Pick if you use a LLaMA model.**
## Token Padding
**Important: This section doesn't apply to OpenAI API. SillyTavern will always use a matching tokenizer for OpenAI models.**
SillyTavern cannot use a proper tokenizer provided by the model running on a remote instance of KoboldAI or Oobabooga's TextGen, so all token counts assumed during prompt generation are estimated based on the selected [tokenizer](#Tokenizer) type.
Since the results of tokenization can be inaccurate on context sizes close to the model-defined maximum, some parts of the prompt may be trimmed or dropped, which may negatively affect the coherence of character definitions.
To prevent this, SillyTavern allocates a portion of the context size as padding to avoid adding more chat items than the model can accommodate. If you find that some part of the prompt is trimmed even with the most-matching tokenizer selected, adjust the padding so the description is not truncated.
You can input negative values for reverse padding, which allows allocating more than the set maximum amount of tokens.
## Advanced Formatting ## Advanced Formatting
The settings provided in this section allow for more control over the prompt building strategy. Most specifics of the prompt building depend on whether a Pygmalion model is selected or special formatting is force-enabled. The core differences between the formatting schemas are listed below. The settings provided in this section allow for more control over the prompt building strategy. Most specifics of the prompt building depend on whether a Pygmalion model is selected or special formatting is force-enabled. The core differences between the formatting schemas are listed below.

View File

@ -143,7 +143,7 @@ export {
setRightTabSelectedClass, setRightTabSelectedClass,
openCharacterChat, openCharacterChat,
saveChat, saveChat,
messageFormating, messageFormatting,
getExtensionPrompt, getExtensionPrompt,
showSwipeButtons, showSwipeButtons,
hideSwipeButtons, hideSwipeButtons,
@ -472,7 +472,6 @@ var preset_settings = "gui";
var user_avatar = "you.png"; var user_avatar = "you.png";
var amount_gen = 80; //default max length of AI generated responses var amount_gen = 80; //default max length of AI generated responses
var max_context = 2048; var max_context = 2048;
let padding_tokens = 64; // reserved tokens to prevent prompt overflow
var is_pygmalion = false; var is_pygmalion = false;
var tokens_already_generated = 0; var tokens_already_generated = 0;
@ -934,7 +933,7 @@ export async function reloadCurrentChat() {
} }
} }
function messageFormating(mes, ch_name, isSystem, forceAvatar) { function messageFormatting(mes, ch_name, isSystem, isUser) {
if (!mes) { if (!mes) {
mes = ''; mes = '';
} }
@ -970,9 +969,9 @@ function messageFormating(mes, ch_name, isSystem, forceAvatar) {
}); });
} }
/* if (ch_name && (forceAvatar || ch_name !== name1)) { if (!power_user.allow_name2_display && ch_name && !isUser && !isSystem) {
mes = mes.replaceAll(ch_name + ":", ""); mes = mes.replaceAll(`${ch_name}:`, "");
} */ }
return mes; return mes;
} }
@ -1060,13 +1059,13 @@ function addOneMessage(mes, { type = "normal", insertAfter = null, scroll = true
if (count_view_mes == 0) { if (count_view_mes == 0) {
messageText = substituteParams(messageText); messageText = substituteParams(messageText);
} }
messageText = messageFormating( messageText = messageFormatting(
messageText, messageText,
characterName, characterName,
isSystem, isSystem,
mes.force_avatar mes.is_user,
); );
const bias = messageFormating(mes.extra?.bias ?? ""); const bias = messageFormatting(mes.extra?.bias ?? "");
let params = { let params = {
mesId: count_view_mes, mesId: count_view_mes,
@ -1419,7 +1418,12 @@ class StreamingProcessor {
chat[messageId]['swipes'][chat[messageId]['swipe_id']] = processedText; chat[messageId]['swipes'][chat[messageId]['swipe_id']] = processedText;
} }
let formattedText = messageFormating(processedText, chat[messageId].name, chat[messageId].is_system, chat[messageId].force_avatar); let formattedText = messageFormatting(
processedText,
chat[messageId].name,
chat[messageId].is_system,
chat[messageId].is_user,
);
const mesText = $(`#chat .mes[mesid="${messageId}"] .mes_text`); const mesText = $(`#chat .mes[mesid="${messageId}"] .mes_text`);
mesText.html(formattedText); mesText.html(formattedText);
$(`#chat .mes[mesid="${messageId}"] .mes_timer`).text(timePassed.timerValue).attr('title', timePassed.timerTitle); $(`#chat .mes[mesid="${messageId}"] .mes_timer`).text(timePassed.timerValue).attr('title', timePassed.timerTitle);
@ -1632,9 +1636,10 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
addOneMessage(chat[chat.length - 1]); addOneMessage(chat[chat.length - 1]);
} }
//////////////////////////////////// ////////////////////////////////////
const scenarioText = chat_metadata['scenario'] || characters[this_chid].scenario;
let charDescription = baseChatReplace($.trim(characters[this_chid].description), name1, name2); let charDescription = baseChatReplace($.trim(characters[this_chid].description), name1, name2);
let charPersonality = baseChatReplace($.trim(characters[this_chid].personality), name1, name2); let charPersonality = baseChatReplace($.trim(characters[this_chid].personality), name1, name2);
let Scenario = baseChatReplace($.trim(characters[this_chid].scenario), name1, name2); let Scenario = baseChatReplace($.trim(scenarioText), name1, name2);
let mesExamples = baseChatReplace($.trim(characters[this_chid].mes_example), name1, name2); let mesExamples = baseChatReplace($.trim(characters[this_chid].mes_example), name1, name2);
// Parse example messages // Parse example messages
@ -1782,7 +1787,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
allAnchors, allAnchors,
quiet_prompt, quiet_prompt,
].join('').replace(/\r/gm, ''); ].join('').replace(/\r/gm, '');
return getTokenCount(encodeString, padding_tokens) < this_max_context; return getTokenCount(encodeString, power_user.token_padding) < this_max_context;
} }
// Force pinned examples into the context // Force pinned examples into the context
@ -1935,7 +1940,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
allAnchors, allAnchors,
quiet_prompt, quiet_prompt,
].join('').replace(/\r/gm, ''); ].join('').replace(/\r/gm, '');
let thisPromtContextSize = getTokenCount(prompt, padding_tokens); let thisPromtContextSize = getTokenCount(prompt, power_user.token_padding);
if (thisPromtContextSize > this_max_context) { //if the prepared prompt is larger than the max context size... if (thisPromtContextSize > this_max_context) { //if the prepared prompt is larger than the max context size...
if (count_exm_add > 0) { // ..and we have example mesages.. if (count_exm_add > 0) { // ..and we have example mesages..
@ -2012,7 +2017,6 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
if (power_user.collapse_newlines) { if (power_user.collapse_newlines) {
finalPromt = collapseNewlines(finalPromt); finalPromt = collapseNewlines(finalPromt);
} }
//console.log(`---Calculated Prompt Tokens: ${getTokenCount(finalPromt, padding_tokens)}`);
let this_amount_gen = parseInt(amount_gen); // how many tokens the AI will be requested to generate let this_amount_gen = parseInt(amount_gen); // how many tokens the AI will be requested to generate
let this_settings = koboldai_settings[koboldai_setting_names[preset_settings]]; let this_settings = koboldai_settings[koboldai_setting_names[preset_settings]];
@ -3250,7 +3254,12 @@ function messageEditAuto(div) {
} }
chat[this_edit_mes_id]["extra"]["bias"] = bias ?? null; chat[this_edit_mes_id]["extra"]["bias"] = bias ?? null;
mesBlock.find(".mes_text").val(''); mesBlock.find(".mes_text").val('');
mesBlock.find(".mes_text").val(messageFormating(text, this_edit_mes_chname, chat[this_edit_mes_id].is_system, chat[this_edit_mes_id].force_avatar)); mesBlock.find(".mes_text").val(messageFormatting(
text,
this_edit_mes_chname,
chat[this_edit_mes_id].is_system,
chat[this_edit_mes_id].is_user,
));
saveChatDebounced(); saveChatDebounced();
} }
@ -3271,10 +3280,15 @@ function messageEditDone(div) {
mesBlock.find(".mes_edit_buttons").css("display", "none"); mesBlock.find(".mes_edit_buttons").css("display", "none");
mesBlock.find(".mes_edit").css("display", "inline-block"); mesBlock.find(".mes_edit").css("display", "inline-block");
mesBlock.find(".mes_text").append( mesBlock.find(".mes_text").append(
messageFormating(text, this_edit_mes_chname, chat[this_edit_mes_id].is_system, chat[this_edit_mes_id].force_avatar) messageFormatting(
text,
this_edit_mes_chname,
chat[this_edit_mes_id].is_system,
chat[this_edit_mes_id].is_user,
)
); );
mesBlock.find(".mes_bias").empty(); mesBlock.find(".mes_bias").empty();
mesBlock.find(".mes_bias").append(messageFormating(bias)); mesBlock.find(".mes_bias").append(messageFormatting(bias));
appendImageToMessage(chat[this_edit_mes_id], div.closest(".mes")); appendImageToMessage(chat[this_edit_mes_id], div.closest(".mes"));
addCopyToCodeBlocks(div.closest(".mes")); addCopyToCodeBlocks(div.closest(".mes"));
this_edit_mes_id = undefined; this_edit_mes_id = undefined;
@ -5214,7 +5228,12 @@ $(document).ready(function () {
$(this) $(this)
.closest(".mes_block") .closest(".mes_block")
.find(".mes_text") .find(".mes_text")
.append(messageFormating(text, this_edit_mes_chname, chat[this_edit_mes_id].is_system, chat[this_edit_mes_id].force_avatar)); .append(messageFormatting(
text,
this_edit_mes_chname,
chat[this_edit_mes_id].is_system,
chat[this_edit_mes_id].is_user,
));
appendImageToMessage(chat[this_edit_mes_id], $(this).closest(".mes")); appendImageToMessage(chat[this_edit_mes_id], $(this).closest(".mes"));
addCopyToCodeBlocks($(this).closest(".mes")); addCopyToCodeBlocks($(this).closest(".mes"));
this_edit_mes_id = undefined; this_edit_mes_id = undefined;

View File

@ -160,7 +160,7 @@ async function connectToApi(baseUrl) {
if (getExtensionsResult.ok) { if (getExtensionsResult.ok) {
const data = await getExtensionsResult.json(); const data = await getExtensionsResult.json();
modules = data.modules; modules = data.modules;
activateExtensions(); await activateExtensions();
} }
updateStatus(getExtensionsResult.ok); updateStatus(getExtensionsResult.ok);
@ -273,12 +273,15 @@ async function loadExtensionSettings(settings) {
} }
$("#extensions_url").val(extension_settings.apiUrl); $("#extensions_url").val(extension_settings.apiUrl);
$("#extensions_autoconnect").prop('checked', extension_settings.autoConnect).trigger('input'); $("#extensions_autoconnect").prop('checked', extension_settings.autoConnect);
// Activate offline extensions // Activate offline extensions
extensionNames = await discoverExtensions(); extensionNames = await discoverExtensions();
manifests = await getManifests(extensionNames) manifests = await getManifests(extensionNames)
activateExtensions(); await activateExtensions();
if (extension_settings.autoConnect && extension_settings.apiUrl) {
await connectToApi(extension_settings.apiUrl);
}
} }
$(document).ready(async function () { $(document).ready(async function () {

View File

@ -1,5 +1,6 @@
import { callPopup, saveSettingsDebounced } from '../../../script.js' import { callPopup, is_send_press, saveSettingsDebounced } from '../../../script.js'
import { extension_settings, getContext } from '../../extensions.js' import { extension_settings, getContext } from '../../extensions.js'
import { is_group_generating } from '../../group-chats.js'
import { getStringHash } from '../../utils.js' import { getStringHash } from '../../utils.js'
import { ElevenLabsTtsProvider } from './elevenlabs.js' import { ElevenLabsTtsProvider } from './elevenlabs.js'
import { SileroTtsProvider } from './silerotts.js' import { SileroTtsProvider } from './silerotts.js'
@ -43,6 +44,11 @@ async function moduleWorker() {
return return
} }
// Message is currently being generated
if (is_send_press || is_group_generating) {
return;
}
// Chat/character/group changed // Chat/character/group changed
if ( if (
(context.groupId && lastGroupId !== context.groupId) || (context.groupId && lastGroupId !== context.groupId) ||
@ -115,7 +121,7 @@ async function playAudioData(audioBlob) {
window['tts_preview'] = function (id) { window['tts_preview'] = function (id) {
const audio = document.getElementById(id) const audio = document.getElementById(id)
if (!audio.hidden) { if (!$(audio).data('disabled')) {
audio.play() audio.play()
} }
else { else {
@ -131,7 +137,7 @@ async function onTtsVoicesClick() {
for (const voice of voiceIds) { for (const voice of voiceIds) {
popupText += `<div class="voice_preview"><span class="voice_lang">${voice.lang || ''}</span> <b class="voice_name">${voice.name}</b> <i onclick="tts_preview('${voice.voice_id}')" class="fa-solid fa-play"></i></div>` popupText += `<div class="voice_preview"><span class="voice_lang">${voice.lang || ''}</span> <b class="voice_name">${voice.name}</b> <i onclick="tts_preview('${voice.voice_id}')" class="fa-solid fa-play"></i></div>`
popupText += `<audio id="${voice.voice_id}" src="${voice.preview_url}" hidden="${!!voice.preview_url}"></audio>` popupText += `<audio id="${voice.voice_id}" src="${voice.preview_url}" data-disabled="${voice.preview_url == false}"></audio>`
} }
} catch { } catch {
popupText = 'Could not load voices list. Check your API key.' popupText = 'Could not load voices list. Check your API key.'

View File

@ -87,7 +87,7 @@ class SystemTtsProvider {
return speechSynthesis return speechSynthesis
.getVoices() .getVoices()
.sort((a, b) => a.lang.localeCompare(b.lang) || a.name.localeCompare(b.name)) .sort((a, b) => a.lang.localeCompare(b.lang) || a.name.localeCompare(b.name))
.map(x => ({ name: x.name, voice_id: x.voiceURI, preview_url: '', lang: x.lang })); .map(x => ({ name: x.name, voice_id: x.voiceURI, preview_url: false, lang: x.lang }));
} }
previewTtsVoice(voiceId) { previewTtsVoice(voiceId) {

View File

@ -449,11 +449,11 @@ async function generateGroupWrapper(by_auto_mode, type = null, force_chid = null
const resolveOriginal = params.resolve; const resolveOriginal = params.resolve;
const rejectOriginal = params.reject; const rejectOriginal = params.reject;
params.resolve = function() { params.resolve = function () {
isQuietGenDone = true; isQuietGenDone = true;
resolveOriginal.apply(this, arguments); resolveOriginal.apply(this, arguments);
}; };
params.reject = function() { params.reject = function () {
isQuietGenDone = true; isQuietGenDone = true;
rejectOriginal.apply(this, arguments); rejectOriginal.apply(this, arguments);
} }
@ -909,9 +909,11 @@ function select_group_chats(groupId, skipAnimation) {
if (groupId) { if (groupId) {
$("#rm_group_submit").hide(); $("#rm_group_submit").hide();
$("#rm_group_delete").show(); $("#rm_group_delete").show();
$("#rm_group_scenario").show();
} else { } else {
$("#rm_group_submit").show(); $("#rm_group_submit").show();
$("#rm_group_delete").hide(); $("#rm_group_delete").hide();
$("#rm_group_scenario").hide();
} }
$("#rm_group_delete").off(); $("#rm_group_delete").off();
@ -1264,11 +1266,35 @@ export async function saveGroupBookmarkChat(groupId, name, metadata) {
}); });
} }
function setGroupScenario() {
if (!selected_group) {
return;
}
const template = $('#group_scenario_template .group_scenario').clone();
const metadataValue = chat_metadata['scenario'] || '';
template.find('.group_chat_scenario').text(metadataValue);
callPopup(template.get(0).outerHTML, 'text');
}
function onGroupScenarioInput() {
const value = $(this).val();
const metadata = { scenario: value, };
updateChatMetadata(metadata, false);
}
function onGroupScenarioRemoveClick() {
$(this).closest('.group_scenario').find('.group_chat_scenario').val('').trigger('input');
}
jQuery(() => { jQuery(() => {
$(document).on("click", ".group_select", selectGroup); $(document).on("click", ".group_select", selectGroup);
$(document).on("input", ".group_chat_scenario", onGroupScenarioInput);
$(document).on("click", ".remove_scenario_override", onGroupScenarioRemoveClick);
$("#rm_group_filter").on("input", filterGroupMembers); $("#rm_group_filter").on("input", filterGroupMembers);
$("#group_fav_filter").on("click", toggleFilterByFavorites); $("#group_fav_filter").on("click", toggleFilterByFavorites);
$("#rm_group_submit").on("click", createGroup); $("#rm_group_submit").on("click", createGroup);
$("#rm_group_scenario").on("click", setGroupScenario);
$("#rm_group_automode").on("input", function () { $("#rm_group_automode").on("input", function () {
const value = $(this).prop("checked"); const value = $(this).prop("checked");
is_group_automode_enabled = value; is_group_automode_enabled = value;

View File

@ -57,6 +57,7 @@ const send_on_enter_options = {
let power_user = { let power_user = {
tokenizer: tokenizers.CLASSIC, tokenizer: tokenizers.CLASSIC,
token_padding: 64,
collapse_newlines: false, collapse_newlines: false,
pygmalion_formatting: pygmalion_options.AUTO, pygmalion_formatting: pygmalion_options.AUTO,
pin_examples: false, pin_examples: false,
@ -100,6 +101,7 @@ let power_user = {
auto_fix_generated_markdown: true, auto_fix_generated_markdown: true,
send_on_enter: send_on_enter_options.AUTO, send_on_enter: send_on_enter_options.AUTO,
render_formulas: false, render_formulas: false,
allow_name2_display: false,
}; };
let themes = []; let themes = [];
@ -372,9 +374,11 @@ function loadPowerUserSettings(settings, data) {
$("#play_message_sound").prop("checked", power_user.play_message_sound); $("#play_message_sound").prop("checked", power_user.play_message_sound);
$("#play_sound_unfocused").prop("checked", power_user.play_sound_unfocused); $("#play_sound_unfocused").prop("checked", power_user.play_sound_unfocused);
$("#auto_save_msg_edits").prop("checked", power_user.auto_save_msg_edits); $("#auto_save_msg_edits").prop("checked", power_user.auto_save_msg_edits);
$("#allow_name2_display").prop("checked", power_user.allow_name2_display);
$(`input[name="avatar_style"][value="${power_user.avatar_style}"]`).prop("checked", true); $(`input[name="avatar_style"][value="${power_user.avatar_style}"]`).prop("checked", true);
$(`input[name="chat_display"][value="${power_user.chat_display}"]`).prop("checked", true); $(`input[name="chat_display"][value="${power_user.chat_display}"]`).prop("checked", true);
$(`input[name="sheld_width"][value="${power_user.sheld_width}"]`).prop("checked", true); $(`input[name="sheld_width"][value="${power_user.sheld_width}"]`).prop("checked", true);
$("#token_padding").val(power_user.token_padding);
$("#font_scale").val(power_user.font_scale); $("#font_scale").val(power_user.font_scale);
$("#font_scale_counter").text(power_user.font_scale); $("#font_scale_counter").text(power_user.font_scale);
@ -747,6 +751,17 @@ $(document).ready(() => {
saveSettingsDebounced(); saveSettingsDebounced();
}) })
$("#allow_name2_display").on("input", function () {
power_user.allow_name2_display = !!$(this).prop('checked');
reloadCurrentChat();
saveSettingsDebounced();
});
$("#token_padding").on("input", function () {
power_user.token_padding = Number($(this).val());
saveSettingsDebounced();
});
$(window).on('focus', function () { $(window).on('focus', function () {
browser_has_focus = true; browser_has_focus = true;
}); });

View File

@ -1878,6 +1878,7 @@ input[type='checkbox']:not(#nav-toggle):not(#rm_button_panel_pin) {
background-color: white; background-color: white;
box-shadow: inset 0 0 3px 0 var(--black70a); box-shadow: inset 0 0 3px 0 var(--black70a);
cursor: pointer; cursor: pointer;
flex-shrink: 0;
} }
/* the checkbox starts with a size 0 background of a checkmark */ /* the checkbox starts with a size 0 background of a checkmark */
@ -3652,7 +3653,8 @@ toolcool-color-picker {
} }
.openai_restorable, .openai_restorable,
.poe_restorable { .poe_restorable,
.title_restorable {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;