CFG: Add ability to combine negative prompts

This allows for flexibility with global, character, and chat negative
prompts. Combining prompts is very useful for users who want to maintain
a set of global negatives and then add extra layers on top of that. The
ordering is chat -> character -> global tags due to the specificity of
each.

The guidance scale follows the cascade of chat -> character -> global
due to being one number that is set when CFG is fired. If the guidance
scale is 1, nothing happens.

Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
kingbri
2023-08-12 16:17:35 -04:00
parent 5bb6c89868
commit 4a21ee0337
3 changed files with 114 additions and 57 deletions

View File

@ -2,32 +2,67 @@ import { chat_metadata } from "../../../script.js";
import { extension_settings } from "../../extensions.js"
import { getCharaFilename } from "../../utils.js";
export const cfgType = {
chat: 0,
chara: 1,
global: 2
}
export const metadataKeys = {
guidance_scale: "cfg_guidance_scale",
negative_prompt: "cfg_negative_prompt",
negative_combine: "cfg_negative_combine"
}
// 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
// If the guidance scale is 1, ignore the CFG negative prompt since it won't be used anyways
// TODO: Add the ability to combine negative prompts if specified. Proposed, chat + global and chat + chara
// TODO: Add groupchat support and fetch the CFG values for the current character
export function getCfg() {
if (chat_metadata['guidance_scale'] !== 1) {
return {
guidanceScale: chat_metadata['guidance_scale'],
negativePrompt: chat_metadata['negative_prompt']
}
}
let splitNegativePrompt = [];
const charaCfg = extension_settings.cfg.chara?.find((e) => e.name === getCharaFilename());
const guidanceScale = getGuidanceScale(charaCfg);
const chatNegativeCombine = chat_metadata[metadataKeys.negative_combine];
const charaCfg = extension_settings.cfg.chara.find((e) => e.name === getCharaFilename());
if (charaCfg && charaCfg?.useChara) {
if (charaCfg.guidance_scale !== 1) {
return {
guidanceScale: charaCfg.guidance_scale,
negativePrompt: charaCfg.negative_prompt
}
// If there's a guidance scale, continue. Otherwise assume undefined
if (guidanceScale?.value && guidanceScale?.value !== 1) {
if (guidanceScale.type === cfgType.chat || chatNegativeCombine.includes(cfgType.chat)) {
splitNegativePrompt.push(chat_metadata[metadataKeys.negative_prompt]?.trim());
}
} else if (extension_settings.cfg.global?.guidance_scale !== 1) {
if (guidanceScale.type === cfgType.chara || chatNegativeCombine.includes(cfgType.chara)) {
splitNegativePrompt.push(charaCfg.negative_prompt?.trim())
}
if (guidanceScale.type === cfgType.global || chatNegativeCombine.includes(cfgType.global)) {
splitNegativePrompt.push(extension_settings.cfg.global.negative_prompt?.trim());
}
return {
guidanceScale: extension_settings.cfg.global.guidance_scale,
negativePrompt: extension_settings.cfg.global.negative_prompt
guidanceScale: guidanceScale.value,
negativePrompt: splitNegativePrompt.filter((e) => e.length > 0).join(", ")
}
}
}
// 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) {
return {
type: cfgType.chat,
value: chatGuidanceScale
};
}
if (charaCfg && charaCfg.guidance_scale !== 1) {
return {
type: cfgType.chara,
value: charaCfg.guidance_scale
};
}
return {
type: cfgType.global,
value: extension_settings.cfg.global.guidance_scale
};
}