CFG: Add groupchat support

Groupchats have their CFG defined a little differently. Chat and
global CFGs are publicly accessible within the window. As a compromise,
individual character CFGs can be injected as part of each character's
prompt. However, these CFG settings need to be adjusted in the character's
individual chats which will carry over to the group.

In addition, make this character logic gated under a checkbox to
always prefer chat unless explicitly specified. Negative cascading
is still open, so individual character negatives can be included
at any time.

Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
kingbri 2023-08-12 22:43:00 -04:00
parent 4a21ee0337
commit 43e91b150a
3 changed files with 180 additions and 134 deletions

View File

@ -7,7 +7,7 @@ import {
} from "../../../script.js";
import { selected_group } from "../../group-chats.js";
import { extension_settings, saveMetadataDebounced } from "../../extensions.js";
import { getCharaFilename, delay, debounce } from "../../utils.js";
import { getCharaFilename, delay } from "../../utils.js";
import { power_user } from "../../power-user.js";
import { metadataKeys } from "./util.js";
@ -76,7 +76,7 @@ function setCharCfg(tempValue, setting) {
extension_settings.cfg.chara.push(tempCharaCfg);
} else {
console.log("Character CFG error: No avatar name key could be found.");
console.debug("Character CFG error: No avatar name key could be found.");
// Don't save settings if something went wrong
return false;
@ -151,18 +151,30 @@ function onCfgMenuItemClick() {
}
}
// TODO: Load character-specific settings here and set the relevant HTML
function onChatChanged() {
async function onChatChanged() {
loadSettings();
await modifyCharaHtml();
}
// Rearrange the panel if a group chat is present
async function modifyCharaHtml() {
if (selected_group) {
$("#chara_cfg_container").hide();
$("#groupchat_cfg_use_chara_container").show();
} else {
$("#chara_cfg_container").show();
$("#groupchat_cfg_use_chara_container").hide();
// TODO: Remove chat checkbox here
}
}
// Reloads chat-specific settings
// TODO: Fix race condition bug where deleted chara CFG still loads previous prompts
function loadSettings() {
// Set chat CFG if it exists
$('#chat_cfg_guidance_scale').val(chat_metadata[metadataKeys.guidance_scale] ?? 1.0.toFixed(2));
$('#chat_cfg_guidance_scale_counter').text(chat_metadata[metadataKeys.guidance_scale]?.toFixed(2) ?? 1.0.toFixed(2));
$('#chat_cfg_negative_prompt').val(chat_metadata[metadataKeys.negative_prompt] ?? '');
$('#groupchat_cfg_use_chara').prop('checked', chat_metadata[metadataKeys.groupchat_individual_chars] ?? false);
if (chat_metadata[metadataKeys.negative_combine]?.length > 0) {
chat_metadata[metadataKeys.negative_combine].forEach((element) => {
$(`input[name="cfg_negative_combine"][value="${element}"]`)
@ -171,11 +183,13 @@ function loadSettings() {
}
// Set character CFG if it exists
if (!selected_group) {
const charaCfg = extension_settings.cfg.chara.find((e) => e.name === getCharaFilename());
$('#chara_cfg_guidance_scale').val(charaCfg?.guidance_scale ?? 1.00);
$('#chara_cfg_guidance_scale_counter').text(charaCfg?.guidance_scale?.toFixed(2) ?? 1.0.toFixed(2));
$('#chara_cfg_negative_prompt').val(charaCfg?.negative_prompt ?? '');
}
}
// Load initial extension settings
async function initialLoadSettings() {
@ -227,7 +241,7 @@ jQuery(async () => {
easing: 'ease-in-out',
});
setTimeout(function () { $('#cfgConfig').hide() }, 200);
})
});
windowHtml.find('#chat_cfg_guidance_scale').on('input', function() {
const numberValue = Number($(this).val());
@ -241,17 +255,6 @@ jQuery(async () => {
setChatCfg($(this).val(), settingType.negative_prompt);
});
windowHtml.find(`input[name="cfg_negative_combine"]`).on('input', function() {
const values = windowHtml.find(`input[name="cfg_negative_combine"]`)
.filter(":checked")
.map(function() { return parseInt($(this).val()) })
.get()
.filter((e) => e !== NaN) || [];
chat_metadata[metadataKeys.negative_combine] = values;
saveMetadataDebounced();
});
windowHtml.find('#chara_cfg_guidance_scale').on('input', function() {
const value = $(this).val();
const success = setCharCfg(value, settingType.guidance_scale);
@ -275,6 +278,28 @@ jQuery(async () => {
saveSettingsDebounced();
});
windowHtml.find(`input[name="cfg_negative_combine"]`).on('input', function() {
const values = windowHtml.find(`input[name="cfg_negative_combine"]`)
.filter(":checked")
.map(function() { return parseInt($(this).val()) })
.get()
.filter((e) => e !== NaN) || [];
chat_metadata[metadataKeys.negative_combine] = values;
saveMetadataDebounced();
});
windowHtml.find('#groupchat_cfg_use_chara').on('input', function() {
const checked = !!$(this).prop('checked');
chat_metadata[metadataKeys.groupchat_individual_chars] = checked
if (checked) {
toastr.info("You can edit character CFG values in their respective character chats.");
}
saveMetadataDebounced();
});
$("#movingDivs").append(windowHtml);
initialLoadSettings();
@ -288,5 +313,7 @@ jQuery(async () => {
buttonHtml.insertAfter("#option_toggle_AN");
// Hook events
eventSource.on(event_types.CHAT_CHANGED, onChatChanged);
eventSource.on(event_types.CHAT_CHANGED, async () => {
await onChatChanged();
});
});

View File

@ -1,5 +1,6 @@
import { chat_metadata } from "../../../script.js";
import { extension_settings } from "../../extensions.js"
import { chat_metadata, this_chid } from "../../../script.js";
import { extension_settings, getContext } from "../../extensions.js"
import { selected_group } from "../../group-chats.js";
import { getCharaFilename } from "../../utils.js";
export const cfgType = {
@ -10,18 +11,17 @@ export const cfgType = {
export const metadataKeys = {
guidance_scale: "cfg_guidance_scale",
negative_prompt: "cfg_negative_prompt",
negative_combine: "cfg_negative_combine"
negative_combine: "cfg_negative_combine",
groupchat_individual_chars: "cfg_groupchat_individual_chars"
}
// TODO: Add groupchat support and fetch the CFG values for the current character
// Gets the CFG value from hierarchy of chat -> character -> global
// Returns undefined values which should be handled in the respective backend APIs
export function getCfg() {
let splitNegativePrompt = [];
const charaCfg = extension_settings.cfg.chara?.find((e) => e.name === getCharaFilename());
const charaCfg = extension_settings.cfg.chara?.find((e) => e.name === getCharaFilename(this_chid));
const guidanceScale = getGuidanceScale(charaCfg);
const chatNegativeCombine = chat_metadata[metadataKeys.negative_combine];
const chatNegativeCombine = chat_metadata[metadataKeys.negative_combine] ?? [];
// If there's a guidance scale, continue. Otherwise assume undefined
if (guidanceScale?.value && guidanceScale?.value !== 1) {
@ -37,9 +37,12 @@ export function getCfg() {
splitNegativePrompt.push(extension_settings.cfg.global.negative_prompt?.trim());
}
const combinedNegatives = splitNegativePrompt.filter((e) => e.length > 0).join(", ");
console.debug(`Setting CFG with guidance scale: ${guidanceScale.value}, negatives: ${combinedNegatives}`)
return {
guidanceScale: guidanceScale.value,
negativePrompt: splitNegativePrompt.filter((e) => e.length > 0).join(", ")
negativePrompt: combinedNegatives
}
}
}
@ -47,14 +50,15 @@ export function getCfg() {
// If the guidance scale is 1, ignore the CFG negative prompt since it won't be used anyways
function getGuidanceScale(charaCfg) {
const chatGuidanceScale = chat_metadata[metadataKeys.guidance_scale];
if (chatGuidanceScale && chatGuidanceScale !== 1) {
const groupchatCharOverride = chat_metadata[metadataKeys.groupchat_individual_chars] ?? false;
if (chatGuidanceScale && chatGuidanceScale !== 1 && !groupchatCharOverride) {
return {
type: cfgType.chat,
value: chatGuidanceScale
};
}
if (charaCfg && charaCfg.guidance_scale !== 1) {
if ((!selected_group && charaCfg || groupchatCharOverride) && charaCfg?.guidance_scale !== 1) {
return {
type: cfgType.chara,
value: charaCfg.guidance_scale

View File

@ -4,6 +4,7 @@
<div id="CFGClose" class="fa-solid fa-circle-xmark"></div>
</div>
<div name="cfgConfigHolder" class="scrollY">
<div id="chat_cfg_container">
<div class="inline-drawer">
<div id="CFGBlockToggle" class="inline-drawer-toggle inline-drawer-header">
<b>Chat CFG</b>
@ -11,7 +12,7 @@
</div>
<div class="inline-drawer-content">
<small>
<b>Unique to this chat</b>.<br>
<b>Unique to this chat.</b><br>
</small>
<label for="chat_cfg_negative_prompt">
<span data-i18n="Scale">Scale</span>
@ -32,8 +33,16 @@
</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 id="groupchat_cfg_use_chara_container">
<label class="checkbox_label" for="groupchat_cfg_use_chara">
<input type="checkbox" id="groupchat_cfg_use_chara" />
<span data-i18n="Use character CFG scales">Use character CFG scales</span>
</label>
</div>
</div>
</div>
</div>
<div id="chara_cfg_container" style="display: none;">
<hr class="sysHR">
<div class="inline-drawer">
<div id="charaANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
@ -41,8 +50,7 @@
<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>
<small><b>Will be automatically added as the CFG for this character.</b></small>
<br />
<label for="chara_cfg_negative_prompt">
<span data-i18n="Scale">Scale</span>
@ -65,6 +73,8 @@
</div>
</div>
</div>
</div>
<div id="global_cfg_container">
<hr class="sysHR">
<div class="inline-drawer">
<div id="defaultANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
@ -72,7 +82,7 @@
<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>
<small><b>Will be used as the default CFG options for every chat unless overridden.</b></small>
<br />
<label for="global_cfg_negative_prompt">
<span data-i18n="Scale">Scale</span>
@ -95,6 +105,8 @@
</div>
</div>
</div>
</div>
<div id="cfg_negative_combine_container">
<hr class="sysHR">
<div class="inline-drawer">
<div id="defaultANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
@ -103,7 +115,9 @@
</div>
<div class="inline-drawer-content">
<small>
Combine negative prompts from other boxes. For example, ticking the chat, global, and character boxes combine all negative prompts into a comma-separated string.
<b>Combine negative prompts from other boxes.</b>
<br />
For example, ticking the chat, global, and character boxes combine all negative prompts into a comma-separated string.
</small>
<br />
<label for="cfg_negative_combine">
@ -111,17 +125,18 @@
</label>
<label class="checkbox_label">
<input type="checkbox" name="cfg_negative_combine" value="0" />
<span data-i18n="Only Format Display">Chat Negatives</span>
<span data-i18n="Chat Negatives">Chat Negatives</span>
</label>
<label class="checkbox_label">
<input type="checkbox" name="cfg_negative_combine" value="1" />
<span data-i18n="Only Format Display">Character Negatives</span>
<span data-i18n="Character Negatives">Character Negatives</span>
</label>
<label class="checkbox_label">
<input type="checkbox" name="cfg_negative_combine" value="2" />
<span data-i18n="Use character CFG">Global Negatives</span>
<span data-i18n="Global Negatives">Global Negatives</span>
</label>
</div>
</div>
</div>
</div>
</div>