mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
CFG: Include the entire prompt with negative prompt
CFG with LLMs works differently than stable diffusion. The main principle is prompt mixing and utilizing the differences between the two prompts rather than a full "negative prompt" of what the user doesn't want. SillyTavern its own way of formatting a prompt sent to an LLM backend. Therefore, take that prompt and add negatives to it. Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
@ -164,6 +164,7 @@ import { deviceInfo } from "./scripts/RossAscends-mods.js";
|
|||||||
import { registerPromptManagerMigration } from "./scripts/PromptManager.js";
|
import { registerPromptManagerMigration } from "./scripts/PromptManager.js";
|
||||||
import { getRegexedString, regex_placement } from "./scripts/extensions/regex/engine.js";
|
import { getRegexedString, regex_placement } from "./scripts/extensions/regex/engine.js";
|
||||||
import { FILTER_TYPES, FilterHelper } from "./scripts/filters.js";
|
import { FILTER_TYPES, FilterHelper } from "./scripts/filters.js";
|
||||||
|
import { getCfg, getNegativePrompt } from "./scripts/extensions/cfg/util.js";
|
||||||
|
|
||||||
//exporting functions and vars for mods
|
//exporting functions and vars for mods
|
||||||
export {
|
export {
|
||||||
@ -2905,6 +2906,8 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
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]];
|
||||||
|
|
||||||
|
const cfgValues = getCfg(finalPromt);
|
||||||
|
|
||||||
if (isMultigenEnabled() && type !== 'quiet') {
|
if (isMultigenEnabled() && type !== 'quiet') {
|
||||||
// if nothing has been generated yet..
|
// if nothing has been generated yet..
|
||||||
this_amount_gen = getMultigenAmount();
|
this_amount_gen = getMultigenAmount();
|
||||||
@ -2912,6 +2915,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
|
|
||||||
let thisPromptBits = [];
|
let thisPromptBits = [];
|
||||||
|
|
||||||
|
// TODO: Make this a switch
|
||||||
if (main_api == 'koboldhorde' && horde_settings.auto_adjust_response_length) {
|
if (main_api == 'koboldhorde' && horde_settings.auto_adjust_response_length) {
|
||||||
this_amount_gen = Math.min(this_amount_gen, adjustedParams.maxLength);
|
this_amount_gen = Math.min(this_amount_gen, adjustedParams.maxLength);
|
||||||
this_amount_gen = Math.max(this_amount_gen, MIN_AMOUNT_GEN); // prevent validation errors
|
this_amount_gen = Math.max(this_amount_gen, MIN_AMOUNT_GEN); // prevent validation errors
|
||||||
@ -2934,7 +2938,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (main_api == 'textgenerationwebui') {
|
else if (main_api == 'textgenerationwebui') {
|
||||||
generate_data = getTextGenGenerationData(finalPromt, this_amount_gen, isImpersonate);
|
generate_data = getTextGenGenerationData(finalPromt, this_amount_gen, isImpersonate, cfgValues);
|
||||||
generate_data.use_mancer = api_use_mancer_webui;
|
generate_data.use_mancer = api_use_mancer_webui;
|
||||||
}
|
}
|
||||||
else if (main_api == 'novel') {
|
else if (main_api == 'novel') {
|
||||||
|
@ -273,6 +273,7 @@ jQuery(async () => {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: Add negative insertion depth
|
||||||
windowHtml.find('#global_cfg_negative_prompt').on('input', function() {
|
windowHtml.find('#global_cfg_negative_prompt').on('input', function() {
|
||||||
extension_settings.cfg.global.negative_prompt = $(this).val();
|
extension_settings.cfg.global.negative_prompt = $(this).val();
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
|
@ -12,18 +12,23 @@ export const metadataKeys = {
|
|||||||
guidance_scale: "cfg_guidance_scale",
|
guidance_scale: "cfg_guidance_scale",
|
||||||
negative_prompt: "cfg_negative_prompt",
|
negative_prompt: "cfg_negative_prompt",
|
||||||
negative_combine: "cfg_negative_combine",
|
negative_combine: "cfg_negative_combine",
|
||||||
groupchat_individual_chars: "cfg_groupchat_individual_chars"
|
groupchat_individual_chars: "cfg_groupchat_individual_chars",
|
||||||
|
negative_insertion_depth: "cfg_negative_insertion_depth"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the CFG value from hierarchy of chat -> character -> global
|
// Gets the CFG value from hierarchy of chat -> character -> global
|
||||||
// Returns undefined values which should be handled in the respective backend APIs
|
// Returns undefined values which should be handled in the respective backend APIs
|
||||||
export function getCfg() {
|
// TODO: Include a custom negative separator
|
||||||
|
// TODO: Maybe use existing prompt building/substitution?
|
||||||
|
export function getCfg(prompt) {
|
||||||
|
const splitPrompt = prompt?.split("\n") ?? [];
|
||||||
let splitNegativePrompt = [];
|
let splitNegativePrompt = [];
|
||||||
const charaCfg = extension_settings.cfg.chara?.find((e) => e.name === getCharaFilename(this_chid));
|
const charaCfg = extension_settings.cfg.chara?.find((e) => e.name === getCharaFilename(this_chid));
|
||||||
const guidanceScale = getGuidanceScale(charaCfg);
|
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 there's a guidance scale, continue. Otherwise assume undefined
|
||||||
|
// TODO: Run substitute params
|
||||||
if (guidanceScale?.value && guidanceScale?.value !== 1) {
|
if (guidanceScale?.value && guidanceScale?.value !== 1) {
|
||||||
if (guidanceScale.type === cfgType.chat || chatNegativeCombine.includes(cfgType.chat)) {
|
if (guidanceScale.type === cfgType.chat || chatNegativeCombine.includes(cfgType.chat)) {
|
||||||
splitNegativePrompt.push(chat_metadata[metadataKeys.negative_prompt]?.trim());
|
splitNegativePrompt.push(chat_metadata[metadataKeys.negative_prompt]?.trim());
|
||||||
@ -37,12 +42,15 @@ export function getCfg() {
|
|||||||
splitNegativePrompt.push(extension_settings.cfg.global.negative_prompt?.trim());
|
splitNegativePrompt.push(extension_settings.cfg.global.negative_prompt?.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
const combinedNegatives = splitNegativePrompt.filter((e) => e.length > 0).join(", ");
|
// TODO: use a custom separator for join
|
||||||
console.debug(`Setting CFG with guidance scale: ${guidanceScale.value}, negatives: ${combinedNegatives}`)
|
const combinedNegatives = splitNegativePrompt.filter((e) => e.length > 0).join("\n");
|
||||||
|
const insertionDepth = chat_metadata[metadataKeys.negative_insertion_depth] ?? 1;
|
||||||
|
splitPrompt.splice(splitPrompt.length - insertionDepth, 0, combinedNegatives);
|
||||||
|
console.log(`Setting CFG with guidance scale: ${guidanceScale.value}, negatives: ${combinedNegatives}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
guidanceScale: guidanceScale.value,
|
guidanceScale: guidanceScale.value,
|
||||||
negativePrompt: combinedNegatives
|
negativePrompt: splitPrompt.join("\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,3 +78,12 @@ function getGuidanceScale(charaCfg) {
|
|||||||
value: extension_settings.cfg.global.guidance_scale
|
value: extension_settings.cfg.global.guidance_scale
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getNegativePrompt(prompt) {
|
||||||
|
const splitPrompt = prompt.split("\n");
|
||||||
|
const insertionDepth = chat_metadata[metadataKeys.negative_insertion_depth] ?? 1;
|
||||||
|
splitPrompt.splice(splitPrompt.length - insertionDepth, 0, "Test negative list");
|
||||||
|
console.log(splitPrompt);
|
||||||
|
const negativePrompt = splitPrompt.join("\n");
|
||||||
|
//console.log(negativePrompt);
|
||||||
|
}
|
||||||
|
@ -235,9 +235,7 @@ async function generateTextGenWithStreaming(generate_data, signal) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTextGenGenerationData(finalPromt, this_amount_gen, isImpersonate) {
|
export function getTextGenGenerationData(finalPromt, this_amount_gen, isImpersonate, cfgValues) {
|
||||||
const cfgValues = getCfg();
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'prompt': finalPromt,
|
'prompt': finalPromt,
|
||||||
'max_new_tokens': this_amount_gen,
|
'max_new_tokens': this_amount_gen,
|
||||||
|
Reference in New Issue
Block a user