Extensions: Add global CFG support

CFG is bundled as an extension which is more flexible in terms of
storing settings and consolidating code.

Global CFG is currently supported and the old power user setting
is auto-migrated.

Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
kingbri 2023-08-08 23:22:25 -04:00
parent d18bd20d75
commit 0c94740560
8 changed files with 314 additions and 3 deletions

View File

@ -0,0 +1,180 @@
import {
chat_metadata,
eventSource,
event_types,
getTokenCount,
saveSettingsDebounced,
this_chid,
} from "../../../script.js";
import { selected_group } from "../../group-chats.js";
import { extension_settings, getContext, saveMetadataDebounced, loadExtensionSettings } from "../../extensions.js";
import { getCharaFilename, debounce, waitUntilCondition, delay } from "../../utils.js";
import { power_user } from "../../power-user.js";
// Keep track of where your extension is located, name should match repo name
const extensionName = "cfg";
const extensionFolderPath = `scripts/extensions/${extensionName}`;
const defaultSettings = {
"global": {
"guidance_scale": 1,
"negative_prompt": ''
},
"chara": []
};
function updateSettings() {
saveSettingsDebounced();
loadSettings();
//setFloatingPrompt();
}
function setCharCfgNegative() {
}
function setCharCfgScale() {
}
function setChatCfgNegative() {
}
function setChatCfgScale() {
}
// TODO: Only change CFG when character is selected
function onCfgMenuItemClick() {
//if (selected_group || this_chid) {
//show CFG config if it's hidden
if ($("#cfgConfig").css("display") !== 'flex') {
$("#cfgConfig").addClass('resizing')
$("#cfgConfig").css("display", "flex");
$("#cfgConfig").css("opacity", 0.0);
$("#cfgConfig").transition({
opacity: 1.0,
duration: 250,
}, async function () {
await delay(50);
$("#cfgConfig").removeClass('resizing')
});
//auto-open the main AN inline drawer
if ($("#CFGBlockToggle")
.siblings('.inline-drawer-content')
.css('display') !== 'block') {
$("#floatingPrompt").addClass('resizing')
$("#CFGBlockToggle").click();
}
} else {
//hide AN if it's already displayed
$("#cfgConfig").addClass('resizing')
$("#cfgConfig").transition({
opacity: 0.0,
duration: 250,
},
async function () {
await delay(50);
$("#cfgConfig").removeClass('resizing')
});
setTimeout(function () {
$("#cfgConfig").hide();
}, 250);
}
//duplicate options menu close handler from script.js
//because this listener takes priority
$("#options").stop().fadeOut(250);
/*
} else {
toastr.warning(`Select a character before trying to configure CFG`, '', { timeOut: 2000 });
}
*/
}
// TODO: Load character-specific settings here and set the relevant HTML
function onChatChanged() {
console.log("Chat changed");
}
// Loads the extension settings if they exist, otherwise initializes them to the defaults.
async function loadSettings() {
// Create the settings if they don't exist
extension_settings[extensionName] = extension_settings[extensionName] || {};
if (Object.keys(extension_settings[extensionName]).length === 0) {
Object.assign(extension_settings[extensionName], defaultSettings);
saveSettingsDebounced();
}
// Set global CFG values on load
$('#global_cfg_guidance_scale').val(extension_settings.cfg.global.guidance_scale);
$('#global_cfg_guidance_scale_counter').text(extension_settings.cfg.global.guidance_scale.toFixed(2));
$('#global_cfg_negative_prompt').val(extension_settings.cfg.global.negative_prompt);
}
function migrateSettings() {
let performSave = false;
if (power_user.guidance_scale) {
extension_settings.cfg.global.guidance_scale = power_user.guidance_scale;
delete power_user['guidance_scale'];
performSave = true;
}
if (power_user.negative_prompt) {
extension_settings.cfg.global.negative_prompt = power_user.negative_prompt;
delete power_user['negative_prompt'];
performSave = true;
}
if (performSave) {
saveSettingsDebounced();
}
}
// This function is called when the extension is loaded
jQuery(async () => {
// This is an example of loading HTML from a file
const windowHtml = $(await $.get(`${extensionFolderPath}/window.html`));
// Append settingsHtml to extensions_settings
// extension_settings and extensions_settings2 are the left and right columns of the settings menu
// Left should be extensions that deal with system functions and right should be visual/UI related
windowHtml.find('#CFGClose').on('click', function () {
$("#cfgConfig").transition({
opacity: 0,
duration: 200,
easing: 'ease-in-out',
});
setTimeout(function () { $('#cfgConfig').hide() }, 200);
})
windowHtml.find('#global_cfg_guidance_scale').on('input', function() {
extension_settings.cfg.global.guidance_scale = Number($(this).val());
$('#global_cfg_guidance_scale_counter').text(extension_settings.cfg.global.guidance_scale.toFixed(2));
console.log(extension_settings.cfg.global.guidance_scale)
saveSettingsDebounced();
});
windowHtml.find('#global_cfg_negative_prompt').on('input', function() {
extension_settings.cfg.global.negative_prompt = $(this).val();
saveSettingsDebounced();
});
$("#movingDivs").append(windowHtml);
// Load settings when starting things up (if you have any)
loadSettings();
if (extension_settings.cfg) {
migrateSettings();
}
const buttonHtml = $(await $.get(`${extensionFolderPath}/menuButton.html`));
buttonHtml.on('click', onCfgMenuItemClick)
buttonHtml.insertAfter("#option_toggle_AN");
// Hook events
eventSource.on(event_types.CHAT_CHANGED, onChatChanged);
});

View File

@ -0,0 +1,11 @@
{
"display_name": "CFG",
"loading_order": 1,
"requires": [],
"optional": [],
"js": "index.js",
"css": "style.css",
"author": "kingbri",
"version": "1.0.0",
"homePage": "https://github.com/SillyTavern/SillyTavern"
}

View File

@ -0,0 +1,4 @@
<a id="option_toggle_CFG">
<i class="fa-lg fa-solid fa-scale-balanced"></i>
<span data-i18n="CFG Scale">CFG Scale</span>
</a>

View File

View File

@ -0,0 +1,9 @@
import { extension_settings } from "../../extensions.js"
// TODO: Update to use per-chat and per-character CFG
export function getCfg() {
return {
guidanceScale: extension_settings.cfg.global.guidance_scale,
negativePrompt: extension_settings.cfg.global.negative_prompt
}
}

View File

@ -0,0 +1,99 @@
<div id="cfgConfig" class="drawer-content flexGap5">
<div class="panelControlBar flex-container">
<div id="cfgConfigHeader" class="fa-solid fa-grip drag-grabber"></div>
<div id="CFGClose" class="fa-solid fa-circle-xmark"></div>
</div>
<div name="cfgConfigHolder" class="scrollY">
<div class="inline-drawer">
<div id="CFGBlockToggle" class="inline-drawer-toggle inline-drawer-header">
<b>Chat CFG</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">
<small>
<b>Unique to this chat</b>.<br>
</small>
<label for="chat_cfg_negative_prompt">
<span data-i18n="Scale">Scale</span>
</label>
<div class="range-block-range-and-counter">
<div class="range-block-range">
<input type="range" id="chat_cfg_guidance_scale" name="volume" min="0.10" max="4.00" step="0.05">
</div>
<div class="range-block-counter">
<div contenteditable="true" data-for="chat_cfg_guidance_scale" id="chat_cfg_guidance_scale_counter">
select
</div>
</div>
</div>
<div>
<label for="chat_cfg_negative_prompt">
<span data-i18n="Negative Prompt">Negative Prompt</span>
</label>
<textarea id="chat_cfg_negative_prompt" rows="2" class="text_pole textarea_compact" data-i18n="[placeholder]write short replies, write replies using past tense" placeholder="write short replies, write replies using past tense"></textarea>
</div>
</div>
</div>
<hr class="sysHR">
<div class="inline-drawer">
<div id="charaANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
<b>Character CFG</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">
<small>Will be automatically added as the CFG for this character. Will be used in groups, but
can't be modified when a group chat is open.</small>
<br />
<label for="chara_cfg_negative_prompt">
<span data-i18n="Scale">Scale</span>
</label>
<div class="range-block-range-and-counter">
<div class="range-block-range">
<input type="range" id="chara_cfg_guidance_scale" name="volume" min="0.10" max="4.00" step="0.05">
</div>
<div class="range-block-counter">
<div contenteditable="true" data-for="chara_cfg_guidance_scale" id="chara_cfg_guidance_scale_counter">
select
</div>
</div>
</div>
<div>
<label for="chara_cfg_negative_prompt">
<span data-i18n="Negative Prompt">Negative Prompt</span>
</label>
<textarea id="chara_cfg_negative_prompt" rows="2" class="text_pole textarea_compact" data-i18n="[placeholder]write short replies, write replies using past tense" placeholder="write short replies, write replies using past tense"></textarea>
</div>
</div>
</div>
<hr class="sysHR">
<div class="inline-drawer">
<div id="defaultANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
<b>Global CFG</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">
<small>Will be used as the default CFG options for every chat unless overridden.</small>
<br />
<label for="global_cfg_negative_prompt">
<span data-i18n="Scale">Scale</span>
</label>
<div class="range-block-range-and-counter">
<div class="range-block-range">
<input type="range" id="global_cfg_guidance_scale" name="volume" min="0.10" max="4.00" step="0.05">
</div>
<div class="range-block-counter">
<div contenteditable="true" data-for="global_cfg_guidance_scale" id="global_cfg_guidance_scale_counter">
select
</div>
</div>
</div>
<div>
<label for="global_cfg_negative_prompt">
<span data-i18n="Negative Prompt">Negative Prompt</span>
</label>
<textarea id="global_cfg_negative_prompt" rows="2" class="text_pole textarea_compact" data-i18n="[placeholder]write short replies, write replies using past tense" placeholder="write short replies, write replies using past tense"></textarea>
</div>
</div>
</div>
</div>
</div>

View File

@ -6,6 +6,8 @@ import {
setGenerationParamsFromPreset,
} from "../script.js";
import { getCfg } from "./extensions/cfg/util.js";
import {
power_user,
} from "./power-user.js";
@ -230,6 +232,8 @@ async function generateTextGenWithStreaming(generate_data, signal) {
}
export function getTextGenGenerationData(finalPromt, this_amount_gen, isImpersonate) {
const { guidanceScale, negativePrompt } = getCfg();
return {
'prompt': finalPromt,
'max_new_tokens': this_amount_gen,
@ -247,6 +251,8 @@ export function getTextGenGenerationData(finalPromt, this_amount_gen, isImperson
'penalty_alpha': textgenerationwebui_settings.penalty_alpha,
'length_penalty': textgenerationwebui_settings.length_penalty,
'early_stopping': textgenerationwebui_settings.early_stopping,
'guidance_scale': guidanceScale ?? 1,
'negative_prompt': negativePrompt ?? '',
'seed': textgenerationwebui_settings.seed,
'add_bos_token': textgenerationwebui_settings.add_bos_token,
'stopping_strings': getStoppingStrings(isImpersonate, false),

View File

@ -1288,7 +1288,7 @@ body.charListGrid #rm_print_characters_block .tags_inline {
overflow-y: auto;
}
#floatingPrompt {
#floatingPrompt, #cfgConfig {
overflow-y: auto;
max-width: 90svw;
max-height: 90svh;
@ -5105,7 +5105,8 @@ body.waifuMode .zoomed_avatar {
#right-nav-panel,
#left-nav-panel,
#floatingPrompt {
#floatingPrompt,
#cfgConfig {
height: calc(100vh - 45px);
height: calc(100svh - 45px);
min-width: 100% !important;
@ -5121,7 +5122,8 @@ body.waifuMode .zoomed_avatar {
backdrop-filter: blur(calc(var(--SmartThemeBlurStrength) * 2));
}
#floatingPrompt {
#floatingPrompt,
#cfgConfig {
height: min-content;
}