diff --git a/public/script.js b/public/script.js index c22628ff5..7567a7c02 100644 --- a/public/script.js +++ b/public/script.js @@ -2720,6 +2720,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, is_send_press = true; } + console.log(cycleGenerationPromt) generatedPromtCache += cycleGenerationPromt; if (generatedPromtCache.length == 0 || type === 'continue') { if (main_api === 'openai') { @@ -2871,17 +2872,28 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, setPromtString(); } + // Fetches the combined prompt for both negative and positive prompts const cfgGuidanceScale = getGuidanceScale(); function getCombinedPrompt(isNegative) { - if (isNegative && cfgGuidanceScale !== 1) { - const negativePrompt = getCfgPrompt(cfgGuidanceScale); - if (negativePrompt && negativePrompt?.value) { - // TODO: kingbri: use the insertion depth method instead of splicing - mesSend.splice(mesSend.length - negativePrompt.depth, 0, `${negativePrompt.value}\n`); + // Use a negative mesSend if present + let negativeMesSend = []; + let cfgPrompt = {}; + if (cfgGuidanceScale && cfgGuidanceScale?.value !== 1) { + cfgPrompt = getCfgPrompt(cfgGuidanceScale, isNegative); + } + + if (cfgPrompt && cfgPrompt?.value && cfgPrompt?.depth !== 0) { + const cfgPromptValue = `${cfgPrompt.value}\n` + // TODO: kingbri: use the insertion depth method instead of splicing + if (isNegative) { + negativeMesSend = [...mesSend]; + negativeMesSend.splice(mesSend.length - cfgPrompt.depth, 0, cfgPromptValue); + } else { + mesSend.splice(mesSend.length - cfgPrompt.depth, 0, cfgPromptValue); } } - let mesSendString = mesSend.join(''); + let mesSendString = isNegative ? negativeMesSend.join('') : mesSend.join(''); // add chat preamble mesSendString = addChatsPreamble(mesSendString); @@ -2889,12 +2901,6 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, // add a custom dingus (if defined) mesSendString = addChatsSeparator(mesSendString); - if (zeroDepthAnchor && zeroDepthAnchor.length) { - if (!isMultigenEnabled() || tokens_already_generated == 0) { - combinedPrompt = appendZeroDepthAnchor(force_name2, zeroDepthAnchor, combinedPrompt); - } - } - let combinedPrompt = storyString + afterScenarioAnchor + @@ -2902,6 +2908,19 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, mesSendString + generatedPromtCache; + if (zeroDepthAnchor && zeroDepthAnchor.length) { + if (!isMultigenEnabled() || tokens_already_generated == 0) { + combinedPrompt = appendZeroDepthAnchor(force_name2, zeroDepthAnchor, combinedPrompt); + } + } + + // Append zero-depth anchor for CFG + if (cfgPrompt && cfgPrompt?.value && cfgPrompt?.depth === 0) { + if (!isMultigenEnabled() || tokens_already_generated == 0) { + combinedPrompt = appendZeroDepthAnchor(force_name2, cfgPrompt.value, combinedPrompt); + } + } + combinedPrompt = combinedPrompt.replace(/\r/gm, ''); if (power_user.collapse_newlines) { @@ -2911,15 +2930,9 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, return combinedPrompt; } - let mesSendString = mesSend.join(''); - // add chat preamble - mesSendString = addChatsPreamble(mesSendString); - - // add a custom dingus (if defined) - mesSendString = addChatsSeparator(mesSendString); - - let finalPromt = getCombinedPrompt(false); + // Get the negative prompt first since it has the unmodified mesSend array let negativePrompt = getCombinedPrompt(true); + let finalPromt = getCombinedPrompt(false); const cfgValues = { guidanceScale: cfgGuidanceScale?.value, negativePrompt: negativePrompt @@ -3018,7 +3031,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, storyString: storyString, afterScenarioAnchor: afterScenarioAnchor, examplesString: examplesString, - mesSendString: mesSendString, + mesSendString: mesSend.join(''), generatedPromtCache: generatedPromtCache, promptBias: promptBias, finalPromt: finalPromt, diff --git a/public/scripts/extensions/cfg/index.js b/public/scripts/extensions/cfg/index.js index e38a255e0..c850ca6d6 100644 --- a/public/scripts/extensions/cfg/index.js +++ b/public/scripts/extensions/cfg/index.js @@ -23,7 +23,8 @@ const defaultSettings = { }; const settingType = { guidance_scale: 0, - negative_prompt: 1 + negative_prompt: 1, + positive_prompt: 2 } // Used for character and chat CFG values @@ -36,19 +37,19 @@ function setCharCfg(tempValue, setting) { const avatarName = getCharaFilename(); // Assign temp object - let tempCharaCfg; + let tempCharaCfg = { + name: avatarName + }; + switch(setting) { case settingType.guidance_scale: - tempCharaCfg = { - "name": avatarName, - "guidance_scale": Number(tempValue) - } + tempCharaCfg["guidance_scale"] = Number(tempValue); break; case settingType.negative_prompt: - tempCharaCfg = { - "name": avatarName, - "negative_prompt": tempValue - } + tempCharaCfg["negative_prompt"] = tempValue; + break; + case settingType.positive_prompt: + tempCharaCfg["positive_prompt"] = tempValue; break; default: return false; @@ -66,7 +67,11 @@ function setCharCfg(tempValue, setting) { const tempAssign = Object.assign(existingCharaCfg, tempCharaCfg); // If both values are default, remove the entry - if (!existingCharaCfg.useChara && (tempAssign.guidance_scale ?? 1.00) === 1.00 && (tempAssign.negative_prompt?.length ?? 0) === 0) { + if (!existingCharaCfg.useChara && + (tempAssign.guidance_scale ?? 1.00) === 1.00 && + (tempAssign.negative_prompt?.length ?? 0) === 0 && + (tempAssign.positive_prompt?.length ?? 0) === 0) + { extension_settings.cfg.chara.splice(existingCharaCfgIndex, 1); } } else if (avatarName && tempValue.length > 0) { @@ -95,6 +100,9 @@ function setChatCfg(tempValue, setting) { case settingType.negative_prompt: chat_metadata[metadataKeys.negative_prompt] = tempValue; break; + case settingType.positive_prompt: + chat_metadata[metadataKeys.positive_prompt] = tempValue; + break; default: return false; } @@ -174,31 +182,32 @@ function loadSettings() { $('#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] ?? ''); + $('#chat_cfg_positive_prompt').val(chat_metadata[metadataKeys.positive_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}"]`) + if (chat_metadata[metadataKeys.prompt_combine]?.length > 0) { + chat_metadata[metadataKeys.prompt_combine].forEach((element) => { + $(`input[name="cfg_prompt_combine"][value="${element}"]`) .prop("checked", true); }); } // Display the negative separator in quotes if not quoted already - let negativeSeparatorDisplay = []; - const negativeSeparator = chat_metadata[metadataKeys.negative_separator]; - if (negativeSeparator) { - negativeSeparatorDisplay.push(negativeSeparator); - if (!negativeSeparator.startsWith(`"`)) { - negativeSeparatorDisplay.unshift(`"`); + let promptSeparatorDisplay = []; + const promptSeparator = chat_metadata[metadataKeys.prompt_separator]; + if (promptSeparator) { + promptSeparatorDisplay.push(promptSeparator); + if (!promptSeparator.startsWith(`"`)) { + promptSeparatorDisplay.unshift(`"`); } - if (!negativeSeparator.endsWith(`"`)) { - negativeSeparatorDisplay.push(`"`); + if (!promptSeparator.endsWith(`"`)) { + promptSeparatorDisplay.push(`"`); } } - $('#cfg_negative_separator').val(negativeSeparatorDisplay.length === 0 ? '' : negativeSeparatorDisplay.join('')); + $('#cfg_prompt_separator').val(promptSeparatorDisplay.length === 0 ? '' : promptSeparatorDisplay.join('')); - $('#cfg_negative_insertion_depth').val(chat_metadata[metadataKeys.negative_insertion_depth] ?? 1); + $('#cfg_prompt_insertion_depth').val(chat_metadata[metadataKeys.prompt_insertion_depth] ?? 1); // Set character CFG if it exists if (!selected_group) { @@ -206,6 +215,7 @@ function loadSettings() { $('#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 ?? ''); + $('#chara_cfg_positive_prompt').val(charaCfg?.positive_prompt ?? ''); } } @@ -222,26 +232,50 @@ async function initialLoadSettings() { $('#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); + $('#global_cfg_positive_prompt').val(extension_settings.cfg.global.positive_prompt); } function migrateSettings() { - let performSave = false; + let performSettingsSave = false; + let performMetaSave = false; if (power_user.guidance_scale) { extension_settings.cfg.global.guidance_scale = power_user.guidance_scale; delete power_user['guidance_scale']; - performSave = true; + performSettingsSave = true; } if (power_user.negative_prompt) { extension_settings.cfg.global.negative_prompt = power_user.negative_prompt; delete power_user['negative_prompt']; - performSave = true; + performSettingsSave = true; } - if (performSave) { + if (chat_metadata["cfg_negative_combine"]) { + chat_metadata[metadataKeys.prompt_combine] = chat_metadata["cfg_negative_combine"]; + chat_metadata["cfg_negative_combine"] = undefined; + performMetaSave = true; + } + + if (chat_metadata["cfg_negative_insertion_depth"]) { + chat_metadata[metadataKeys.prompt_insertion_depth] = chat_metadata["cfg_negative_insertion_depth"]; + chat_metadata["cfg_negative_insertion_depth"] = undefined; + performMetaSave = true; + } + + if (chat_metadata["cfg_negative_separator"]) { + chat_metadata[metadataKeys.prompt_separator] = chat_metadata["cfg_negative_separator"]; + chat_metadata["cfg_negative_separator"] = undefined; + performMetaSave = true; + } + + if (performSettingsSave) { saveSettingsDebounced(); } + + if (performMetaSave) { + saveMetadataDebounced(); + } } // This function is called when the extension is loaded @@ -273,6 +307,10 @@ jQuery(async () => { setChatCfg($(this).val(), settingType.negative_prompt); }); + windowHtml.find('#chat_cfg_positive_prompt').on('input', function() { + setChatCfg($(this).val(), settingType.positive_prompt); + }); + windowHtml.find('#chara_cfg_guidance_scale').on('input', function() { const value = $(this).val(); const success = setCharCfg(value, settingType.guidance_scale); @@ -285,6 +323,10 @@ jQuery(async () => { setCharCfg($(this).val(), settingType.negative_prompt); }); + windowHtml.find('#chara_cfg_positive_prompt').on('input', function() { + setCharCfg($(this).val(), settingType.positive_prompt); + }); + 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)); @@ -296,24 +338,29 @@ jQuery(async () => { saveSettingsDebounced(); }); - windowHtml.find(`input[name="cfg_negative_combine"]`).on('input', function() { - const values = windowHtml.find(`input[name="cfg_negative_combine"]`) + windowHtml.find('#global_cfg_positive_prompt').on('input', function() { + extension_settings.cfg.global.positive_prompt = $(this).val(); + saveSettingsDebounced(); + }); + + windowHtml.find(`input[name="cfg_prompt_combine"]`).on('input', function() { + const values = windowHtml.find(`input[name="cfg_prompt_combine"]`) .filter(":checked") .map(function() { return parseInt($(this).val()) }) .get() .filter((e) => e !== NaN) || []; - chat_metadata[metadataKeys.negative_combine] = values; + chat_metadata[metadataKeys.prompt_combine] = values; saveMetadataDebounced(); }); - windowHtml.find(`#cfg_negative_insertion_depth`).on('input', function() { - chat_metadata[metadataKeys.negative_insertion_depth] = Number($(this).val()); + windowHtml.find(`#cfg_prompt_insertion_depth`).on('input', function() { + chat_metadata[metadataKeys.prompt_insertion_depth] = Number($(this).val()); saveMetadataDebounced(); }); - windowHtml.find(`#cfg_negative_separator`).on('input', function() { - chat_metadata[metadataKeys.negative_separator] = $(this).val(); + windowHtml.find(`#cfg_prompt_separator`).on('input', function() { + chat_metadata[metadataKeys.prompt_separator] = $(this).val(); saveMetadataDebounced(); }); diff --git a/public/scripts/extensions/cfg/util.js b/public/scripts/extensions/cfg/util.js index d37d54725..108c22646 100644 --- a/public/scripts/extensions/cfg/util.js +++ b/public/scripts/extensions/cfg/util.js @@ -11,14 +11,15 @@ export const cfgType = { export const metadataKeys = { guidance_scale: "cfg_guidance_scale", negative_prompt: "cfg_negative_prompt", - negative_combine: "cfg_negative_combine", + positive_prompt: "cfg_positive_prompt", + prompt_combine: "cfg_prompt_combine", groupchat_individual_chars: "cfg_groupchat_individual_chars", - negative_insertion_depth: "cfg_negative_insertion_depth", - negative_separator: "cfg_negative_separator" + prompt_insertion_depth: "cfg_prompt_insertion_depth", + prompt_separator: "cfg_prompt_separator" } // Gets the CFG guidance scale -// If the guidance scale is 1, ignore the CFG negative prompt since it won't be used anyways +// If the guidance scale is 1, ignore the CFG prompt(s) since it won't be used anyways export function getGuidanceScale() { const charaCfg = extension_settings.cfg.chara?.find((e) => e.name === getCharaFilename(this_chid)); const chatGuidanceScale = chat_metadata[metadataKeys.guidance_scale]; @@ -44,32 +45,49 @@ export function getGuidanceScale() { }; } -// Gets the CFG prompt. Currently only gets the negative prompt -export function getCfgPrompt(guidanceScale) { - let splitNegativePrompt = []; +// Gets the CFG prompt +export function getCfgPrompt(guidanceScale, isNegative) { + let splitCfgPrompt = []; - const chatNegativeCombine = chat_metadata[metadataKeys.negative_combine] ?? []; - if (guidanceScale.type === cfgType.chat || chatNegativeCombine.includes(cfgType.chat)) { - splitNegativePrompt.unshift(substituteParams(chat_metadata[metadataKeys.negative_prompt])?.trim()); + const cfgPromptCombine = chat_metadata[metadataKeys.prompt_combine] ?? []; + if (guidanceScale.type === cfgType.chat || cfgPromptCombine.includes(cfgType.chat)) { + splitCfgPrompt.unshift( + substituteParams( + chat_metadata[isNegative ? metadataKeys.negative_prompt : metadataKeys.positive_prompt] + ) + ?.trim() + ); } const charaCfg = extension_settings.cfg.chara?.find((e) => e.name === getCharaFilename(this_chid)); - if (guidanceScale.type === cfgType.chara || chatNegativeCombine.includes(cfgType.chara)) { - splitNegativePrompt.unshift(substituteParams(charaCfg.negative_prompt)?.trim()) + if (guidanceScale.type === cfgType.chara || cfgPromptCombine.includes(cfgType.chara)) { + splitCfgPrompt.unshift( + substituteParams( + isNegative ? charaCfg.negative_prompt : charaCfg.positive_prompt + ) + ?.trim() + ); } - if (guidanceScale.type === cfgType.global || chatNegativeCombine.includes(cfgType.global)) { - splitNegativePrompt.unshift(substituteParams(extension_settings.cfg.global.negative_prompt)?.trim()); + console.log(guidanceScale.type); + console.log(cfgPromptCombine); + if (guidanceScale.type === cfgType.global || cfgPromptCombine.includes(cfgType.global)) { + splitCfgPrompt.unshift( + substituteParams( + isNegative ? extension_settings.cfg.global.negative_prompt : extension_settings.cfg.global.positive_prompt + ) + ?.trim() + ); } // This line is a bit hacky with a JSON.stringify and JSON.parse. Fix this if possible. - const negativeSeparator = JSON.parse(chat_metadata[metadataKeys.negative_separator] || JSON.stringify("\n")) ?? "\n"; - const combinedNegatives = splitNegativePrompt.filter((e) => e.length > 0).join(negativeSeparator); - const insertionDepth = chat_metadata[metadataKeys.negative_insertion_depth] ?? 1; - console.log(`Setting CFG with guidance scale: ${guidanceScale.value}, negatives: ${combinedNegatives}`); + const customSeparator = JSON.parse(chat_metadata[metadataKeys.prompt_separator] || JSON.stringify("\n")) ?? "\n"; + const combinedCfgPrompt = splitCfgPrompt.filter((e) => e.length > 0).join(customSeparator); + const insertionDepth = chat_metadata[metadataKeys.prompt_insertion_depth] ?? 1; + console.log(`Setting CFG with guidance scale: ${guidanceScale.value}, negatives: ${combinedCfgPrompt}`); return { - value: combinedNegatives, + value: combinedCfgPrompt, depth: insertionDepth }; } diff --git a/public/scripts/extensions/cfg/window.html b/public/scripts/extensions/cfg/window.html index 5e0d21f7c..889d5b0bb 100644 --- a/public/scripts/extensions/cfg/window.html +++ b/public/scripts/extensions/cfg/window.html @@ -14,7 +14,7 @@ Unique to this chat.
- + + +
@@ -86,7 +96,7 @@
Will be used as the default CFG options for every chat unless overridden.
- + + +
-
+

- Negative Cascading + CFG Prompt Cascading
- Combine negative prompts from other boxes. + Combine positive/negative prompts from other boxes.
For example, ticking the chat, global, and character boxes combine all negative prompts into a comma-separated string.

-