Add ability to insert role-typed prompt injections
This commit is contained in:
parent
76cde592ad
commit
607df2f555
|
@ -4646,12 +4646,28 @@
|
|||
<div class="WIEnteryHeaderControls flex-container">
|
||||
<div name="PositionBlock" class="world_entry_form_control world_entry_form_radios wi-enter-footer-text">
|
||||
<label for="position" class="WIEntryHeaderTitleMobile" data-i18n="Position:">Position:</label>
|
||||
<select name="position" class="text_pole widthNatural margin0" data-i18n="[title]T_Position" title="↑Char: Before Character Definitions ↓Char: After Character Definitions ↑AN: Before Author's Note ↓AN: After Author's Note @D: at Depth ">
|
||||
<option value="0" data-i18n="[title]T_Position" title="↑Char: Before Character Definitions ↓Char: After Character Definitions ↑AN: Before Author's Note ↓AN: After Author's Note @D: at Depth "><span data-i18n="Before Char Defs">↑Char</span></option>
|
||||
<option value="1" data-i18n="[title]T_Position" title="↑Char: Before Character Definitions ↓Char: After Character Definitions ↑AN: Before Author's Note ↓AN: After Author's Note @D: at Depth "><span data-i18n="After Char Defs">↓Char</span></option>
|
||||
<option value="2" data-i18n="[title]T_Position" title="↑Char: Before Character Definitions ↓Char: After Character Definitions ↑AN: Before Author's Note ↓AN: After Author's Note @D: at Depth "><span data-i18n="Before AN">↑AN</span></option>
|
||||
<option value="3" data-i18n="[title]T_Position" title="↑Char: Before Character Definitions ↓Char: After Character Definitions ↑AN: Before Author's Note ↓AN: After Author's Note @D: at Depth "><span data-i18n="After AN">↓AN</span></option>
|
||||
<option value="4" data-i18n="[title]T_Position" title="↑Char: Before Character Definitions ↓Char: After Character Definitions ↑AN: Before Author's Note ↓AN: After Author's Note @D: at Depth "><span data-i18n="at Depth">@D</span></option>
|
||||
<select name="position" class="text_pole widthNatural margin0" data-i18n="[title]T_Position" title="↑Char: Before Character Definitions ↓Char: After Character Definitions ↑AN: Before Author's Note ↓AN: After Author's Note @D ⚙️: at Depth (System) @D 👤: at Depth (User) @D 🤖: at Depth (Assistant)">
|
||||
<option value="0" data-role="" data-i18n="Before Char Defs">
|
||||
↑Char
|
||||
</option>
|
||||
<option value="1" data-role="" data-i18n="After Char Defs">
|
||||
↓Char
|
||||
</option>
|
||||
<option value="2" data-role="" data-i18n="Before AN">
|
||||
↑AN
|
||||
</option>
|
||||
<option value="3" data-role="" data-i18n="After AN">
|
||||
↓AN
|
||||
</option>
|
||||
<option value="4" data-role="0" data-i18n="at Depth System" >
|
||||
@D ⚙️
|
||||
</option>
|
||||
<option value="4" data-role="1" data-i18n="at Depth User">
|
||||
@D 👤
|
||||
</option>
|
||||
<option value="4" data-role="2" data-i18n="at Depth AI">
|
||||
@D 🤖
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap">
|
||||
|
|
233
public/script.js
233
public/script.js
|
@ -495,6 +495,9 @@ const durationSaveEdit = 1000;
|
|||
const saveSettingsDebounced = debounce(() => saveSettings(), durationSaveEdit);
|
||||
export const saveCharacterDebounced = debounce(() => $('#create_button').trigger('click'), durationSaveEdit);
|
||||
|
||||
/**
|
||||
* @enum {string} System message types
|
||||
*/
|
||||
const system_message_types = {
|
||||
HELP: 'help',
|
||||
WELCOME: 'welcome',
|
||||
|
@ -511,12 +514,24 @@ const system_message_types = {
|
|||
MACROS: 'macros',
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum {number} Extension prompt types
|
||||
*/
|
||||
const extension_prompt_types = {
|
||||
IN_PROMPT: 0,
|
||||
IN_CHAT: 1,
|
||||
BEFORE_PROMPT: 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum {number} Extension prompt roles
|
||||
*/
|
||||
export const extension_prompt_roles = {
|
||||
SYSTEM: 0,
|
||||
USER: 1,
|
||||
ASSISTANT: 2,
|
||||
};
|
||||
|
||||
export const MAX_INJECTION_DEPTH = 1000;
|
||||
|
||||
let system_messages = {};
|
||||
|
@ -2462,11 +2477,22 @@ function getExtensionPromptByName(moduleName) {
|
|||
}
|
||||
}
|
||||
|
||||
function getExtensionPrompt(position = 0, depth = undefined, separator = '\n') {
|
||||
/**
|
||||
* Returns the extension prompt for the given position, depth, and role.
|
||||
* If multiple prompts are found, they are joined with a separator.
|
||||
* @param {number} [position] Position of the prompt
|
||||
* @param {number} [depth] Depth of the prompt
|
||||
* @param {string} [separator] Separator for joining multiple prompts
|
||||
* @param {number} [role] Role of the prompt
|
||||
* @returns {string} Extension prompt
|
||||
*/
|
||||
function getExtensionPrompt(position = extension_prompt_types.IN_PROMPT, depth = undefined, separator = '\n', role = undefined) {
|
||||
let extension_prompt = Object.keys(extension_prompts)
|
||||
.sort()
|
||||
.map((x) => extension_prompts[x])
|
||||
.filter(x => x.position == position && x.value && (depth === undefined || x.depth == depth))
|
||||
.filter(x => x.position == position && x.value)
|
||||
.filter(x => x.depth === undefined || x.depth === depth)
|
||||
.filter(x => x.role === undefined || x.role === role)
|
||||
.map(x => x.value.trim())
|
||||
.join(separator);
|
||||
if (extension_prompt.length && !extension_prompt.startsWith(separator)) {
|
||||
|
@ -3160,6 +3186,21 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
|||
console.debug('Skipping extension interceptors for dry run');
|
||||
}
|
||||
|
||||
// Adjust token limit for Horde
|
||||
let adjustedParams;
|
||||
if (main_api == 'koboldhorde' && (horde_settings.auto_adjust_context_length || horde_settings.auto_adjust_response_length)) {
|
||||
try {
|
||||
adjustedParams = await adjustHordeGenerationParams(max_context, amount_gen);
|
||||
}
|
||||
catch {
|
||||
unblockGeneration();
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (horde_settings.auto_adjust_context_length) {
|
||||
this_max_context = (adjustedParams.maxContextLength - adjustedParams.maxLength);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Core/all messages: ${coreChat.length}/${chat.length}`);
|
||||
|
||||
// kingbri MARK: - Make sure the prompt bias isn't the same as the user bias
|
||||
|
@ -3172,6 +3213,32 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
|||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// Extension added strings
|
||||
// Set non-WI AN
|
||||
setFloatingPrompt();
|
||||
// Add WI to prompt (and also inject WI to AN value via hijack)
|
||||
|
||||
const chatForWI = coreChat.map(x => `${x.name}: ${x.mes}`).reverse();
|
||||
let { worldInfoString, worldInfoBefore, worldInfoAfter, worldInfoDepth } = await getWorldInfoPrompt(chatForWI, this_max_context, dryRun);
|
||||
|
||||
if (skipWIAN !== true) {
|
||||
console.log('skipWIAN not active, adding WIAN');
|
||||
// Add all depth WI entries to prompt
|
||||
flushWIDepthInjections();
|
||||
if (Array.isArray(worldInfoDepth)) {
|
||||
worldInfoDepth.forEach((e) => {
|
||||
const joinedEntries = e.entries.join('\n');
|
||||
setExtensionPrompt(`customDepthWI-${e.depth}-${e.role}`, joinedEntries, extension_prompt_types.IN_CHAT, e.depth, false, e.role);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log('skipping WIAN');
|
||||
}
|
||||
|
||||
// Inject all Depth prompts. Chat Completion does it separately
|
||||
if (main_api !== 'openai') {
|
||||
doChatInject(coreChat, isContinue);
|
||||
}
|
||||
|
||||
// Insert character jailbreak as the last user message (if exists, allowed, preferred, and not using Chat Completion)
|
||||
if (power_user.context.allow_jailbreak && power_user.prefer_character_jailbreak && main_api !== 'openai' && jailbreak) {
|
||||
|
@ -3190,9 +3257,7 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
|||
let chat2 = [];
|
||||
let continue_mag = '';
|
||||
for (let i = coreChat.length - 1, j = 0; i >= 0; i--, j++) {
|
||||
// For OpenAI it's only used in WI
|
||||
if (main_api == 'openai' && (!world_info || world_info.length === 0)) {
|
||||
console.debug('No WI, skipping chat2 for OAI');
|
||||
if (main_api == 'openai') {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3215,49 +3280,12 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
|||
}
|
||||
}
|
||||
|
||||
// Adjust token limit for Horde
|
||||
let adjustedParams;
|
||||
if (main_api == 'koboldhorde' && (horde_settings.auto_adjust_context_length || horde_settings.auto_adjust_response_length)) {
|
||||
try {
|
||||
adjustedParams = await adjustHordeGenerationParams(max_context, amount_gen);
|
||||
}
|
||||
catch {
|
||||
unblockGeneration();
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (horde_settings.auto_adjust_context_length) {
|
||||
this_max_context = (adjustedParams.maxContextLength - adjustedParams.maxLength);
|
||||
}
|
||||
}
|
||||
|
||||
// Extension added strings
|
||||
// Set non-WI AN
|
||||
setFloatingPrompt();
|
||||
// Add WI to prompt (and also inject WI to AN value via hijack)
|
||||
|
||||
let { worldInfoString, worldInfoBefore, worldInfoAfter, worldInfoDepth } = await getWorldInfoPrompt(chat2, this_max_context, dryRun);
|
||||
|
||||
if (skipWIAN !== true) {
|
||||
console.log('skipWIAN not active, adding WIAN');
|
||||
// Add all depth WI entries to prompt
|
||||
flushWIDepthInjections();
|
||||
if (Array.isArray(worldInfoDepth)) {
|
||||
worldInfoDepth.forEach((e) => {
|
||||
const joinedEntries = e.entries.join('\n');
|
||||
setExtensionPrompt(`customDepthWI-${e.depth}`, joinedEntries, extension_prompt_types.IN_CHAT, e.depth);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log('skipping WIAN');
|
||||
}
|
||||
|
||||
// Add persona description to prompt
|
||||
addPersonaDescriptionExtensionPrompt();
|
||||
// Call combined AN into Generate
|
||||
let allAnchors = getAllExtensionPrompts();
|
||||
const beforeScenarioAnchor = getExtensionPrompt(extension_prompt_types.BEFORE_PROMPT).trimStart();
|
||||
const afterScenarioAnchor = getExtensionPrompt(extension_prompt_types.IN_PROMPT);
|
||||
let zeroDepthAnchor = getExtensionPrompt(extension_prompt_types.IN_CHAT, 0, ' ');
|
||||
|
||||
const storyStringParams = {
|
||||
description: description,
|
||||
|
@ -3560,40 +3588,6 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
|||
// Deep clone
|
||||
let finalMesSend = structuredClone(mesSend);
|
||||
|
||||
// TODO: Rewrite getExtensionPrompt to not require multiple for loops
|
||||
// Set all extension prompts where insertion depth > mesSend length
|
||||
if (finalMesSend.length) {
|
||||
for (let upperDepth = MAX_INJECTION_DEPTH; upperDepth >= finalMesSend.length; upperDepth--) {
|
||||
const upperAnchor = getExtensionPrompt(extension_prompt_types.IN_CHAT, upperDepth);
|
||||
if (upperAnchor && upperAnchor.length) {
|
||||
finalMesSend[0].extensionPrompts.push(upperAnchor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finalMesSend.forEach((mesItem, index) => {
|
||||
if (index === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const anchorDepth = Math.abs(index - finalMesSend.length);
|
||||
// NOTE: Depth injected here!
|
||||
const extensionAnchor = getExtensionPrompt(extension_prompt_types.IN_CHAT, anchorDepth);
|
||||
|
||||
if (anchorDepth >= 0 && extensionAnchor && extensionAnchor.length) {
|
||||
mesItem.extensionPrompts.push(extensionAnchor);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Move zero-depth anchor append to work like CFG and bias appends
|
||||
if (zeroDepthAnchor?.length && !isContinue) {
|
||||
console.debug(/\s/.test(finalMesSend[finalMesSend.length - 1].message.slice(-1)));
|
||||
finalMesSend[finalMesSend.length - 1].message +=
|
||||
/\s/.test(finalMesSend[finalMesSend.length - 1].message.slice(-1))
|
||||
? zeroDepthAnchor
|
||||
: `${zeroDepthAnchor}`;
|
||||
}
|
||||
|
||||
let cfgPrompt = {};
|
||||
if (cfgGuidanceScale && cfgGuidanceScale?.value !== 1) {
|
||||
cfgPrompt = getCfgPrompt(cfgGuidanceScale, isNegative);
|
||||
|
@ -3969,6 +3963,57 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects extension prompts into chat messages.
|
||||
* @param {object[]} messages Array of chat messages
|
||||
* @param {boolean} isContinue Whether the generation is a continuation. If true, the extension prompts of depth 0 are injected at position 1.
|
||||
* @returns {void}
|
||||
*/
|
||||
function doChatInject(messages, isContinue) {
|
||||
let totalInsertedMessages = 0;
|
||||
messages.reverse();
|
||||
|
||||
for (let i = 0; i <= MAX_INJECTION_DEPTH; i++) {
|
||||
// Order of priority (most important go lower)
|
||||
const roles = [extension_prompt_roles.SYSTEM, extension_prompt_roles.USER, extension_prompt_roles.ASSISTANT];
|
||||
const names = {
|
||||
[extension_prompt_roles.SYSTEM]: '',
|
||||
[extension_prompt_roles.USER]: name1,
|
||||
[extension_prompt_roles.ASSISTANT]: name2,
|
||||
}
|
||||
const roleMessages = [];
|
||||
const separator = '\n';
|
||||
|
||||
for (const role of roles) {
|
||||
// Get extension prompt
|
||||
const extensionPrompt = String(getExtensionPrompt(extension_prompt_types.IN_CHAT, i, separator, role)).trimStart();
|
||||
const isNarrator = role === extension_prompt_roles.SYSTEM;
|
||||
const isUser = role === extension_prompt_roles.USER;
|
||||
const name = names[role];
|
||||
|
||||
if (extensionPrompt) {
|
||||
roleMessages.push({
|
||||
name: name,
|
||||
is_user: isUser,
|
||||
mes: extensionPrompt,
|
||||
extra: {
|
||||
type: isNarrator ? system_message_types.NARRATOR : null,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (roleMessages.length) {
|
||||
const depth = isContinue && i === 0 ? 1 : i;
|
||||
const injectIdx = depth + totalInsertedMessages;
|
||||
messages.splice(injectIdx, 0, ...roleMessages);
|
||||
totalInsertedMessages += roleMessages.length;
|
||||
}
|
||||
}
|
||||
|
||||
messages.reverse();
|
||||
}
|
||||
|
||||
function flushWIDepthInjections() {
|
||||
//prevent custom depth WI entries (which have unique random key names) from duplicating
|
||||
for (const key of Object.keys(extension_prompts)) {
|
||||
|
@ -4229,25 +4274,6 @@ function addChatsSeparator(mesSendString) {
|
|||
}
|
||||
}
|
||||
|
||||
// There's a TODO related to zero-depth anchors; not removing this function until that's resolved
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function appendZeroDepthAnchor(force_name2, zeroDepthAnchor, finalPrompt) {
|
||||
const trimBothEnds = !force_name2;
|
||||
let trimmedPrompt = (trimBothEnds ? zeroDepthAnchor.trim() : zeroDepthAnchor.trimEnd());
|
||||
|
||||
if (trimBothEnds && !finalPrompt.endsWith('\n')) {
|
||||
finalPrompt += '\n';
|
||||
}
|
||||
|
||||
finalPrompt += trimmedPrompt;
|
||||
|
||||
if (force_name2) {
|
||||
finalPrompt += ' ';
|
||||
}
|
||||
|
||||
return finalPrompt;
|
||||
}
|
||||
|
||||
async function DupeChar() {
|
||||
if (!this_chid) {
|
||||
toastr.warning('You must first select a character to duplicate!');
|
||||
|
@ -5715,7 +5741,7 @@ async function uploadUserAvatar(e) {
|
|||
}
|
||||
|
||||
const rawFile = formData.get('avatar');
|
||||
if (rawFile instanceof File){
|
||||
if (rawFile instanceof File) {
|
||||
const convertedFile = await ensureImageFormatSupported(rawFile);
|
||||
formData.set('avatar', convertedFile);
|
||||
}
|
||||
|
@ -6656,10 +6682,17 @@ function select_rm_characters() {
|
|||
* @param {string} value Prompt injection value.
|
||||
* @param {number} position Insertion position. 0 is after story string, 1 is in-chat with custom depth.
|
||||
* @param {number} depth Insertion depth. 0 represets the last message in context. Expected values up to MAX_INJECTION_DEPTH.
|
||||
* @param {number} role Extension prompt role. Defaults to SYSTEM.
|
||||
* @param {boolean} scan Should the prompt be included in the world info scan.
|
||||
*/
|
||||
export function setExtensionPrompt(key, value, position, depth, scan = false) {
|
||||
extension_prompts[key] = { value: String(value), position: Number(position), depth: Number(depth), scan: !!scan };
|
||||
export function setExtensionPrompt(key, value, position, depth, scan = false, role = extension_prompt_roles.SYSTEM) {
|
||||
extension_prompts[key] = {
|
||||
value: String(value),
|
||||
position: Number(position),
|
||||
depth: Number(depth),
|
||||
scan: !!scan,
|
||||
role: Number(role ?? extension_prompt_roles.SYSTEM),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -7223,7 +7256,7 @@ async function createOrEditCharacter(e) {
|
|||
formData.set('fav', fav_ch_checked);
|
||||
|
||||
const rawFile = formData.get('avatar');
|
||||
if (rawFile instanceof File){
|
||||
if (rawFile instanceof File) {
|
||||
const convertedFile = await ensureImageFormatSupported(rawFile);
|
||||
formData.set('avatar', convertedFile);
|
||||
}
|
||||
|
@ -8450,7 +8483,7 @@ jQuery(async function () {
|
|||
$('#advanced_div').click(function () {
|
||||
if (!is_advanced_char_open) {
|
||||
is_advanced_char_open = true;
|
||||
$('#character_popup').css({'display': 'flex', 'opacity': 0.0}).addClass('open');
|
||||
$('#character_popup').css({ 'display': 'flex', 'opacity': 0.0 }).addClass('open');
|
||||
$('#character_popup').transition({
|
||||
opacity: 1.0,
|
||||
duration: animation_duration,
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
characters,
|
||||
event_types,
|
||||
eventSource,
|
||||
extension_prompt_roles,
|
||||
extension_prompt_types,
|
||||
Generate,
|
||||
getExtensionPrompt,
|
||||
|
@ -648,6 +649,12 @@ function formatWorldInfo(value) {
|
|||
function populationInjectionPrompts(prompts, messages) {
|
||||
let totalInsertedMessages = 0;
|
||||
|
||||
const roleTypes = {
|
||||
'system': extension_prompt_roles.SYSTEM,
|
||||
'user': extension_prompt_roles.USER,
|
||||
'assistant': extension_prompt_roles.ASSISTANT,
|
||||
};
|
||||
|
||||
for (let i = 0; i <= MAX_INJECTION_DEPTH; i++) {
|
||||
// Get prompts for current depth
|
||||
const depthPrompts = prompts.filter(prompt => prompt.injection_depth === i && prompt.content);
|
||||
|
@ -655,14 +662,15 @@ function populationInjectionPrompts(prompts, messages) {
|
|||
// Order of priority (most important go lower)
|
||||
const roles = ['system', 'user', 'assistant'];
|
||||
const roleMessages = [];
|
||||
const separator = '\n';
|
||||
|
||||
for (const role of roles) {
|
||||
// Get prompts for current role
|
||||
const rolePrompts = depthPrompts.filter(prompt => prompt.role === role).map(x => x.content).join('\n');
|
||||
// Get extension prompt (only for system role)
|
||||
const extensionPrompt = role === 'system' ? getExtensionPrompt(extension_prompt_types.IN_CHAT, i) : '';
|
||||
const rolePrompts = depthPrompts.filter(prompt => prompt.role === role).map(x => x.content).join(separator);
|
||||
// Get extension prompt
|
||||
const extensionPrompt = getExtensionPrompt(extension_prompt_types.IN_CHAT, i, separator, roleTypes[role]);
|
||||
|
||||
const jointPrompt = [rolePrompts, extensionPrompt].filter(x => x).map(x => x.trim()).join('\n');
|
||||
const jointPrompt = [rolePrompts, extensionPrompt].filter(x => x).map(x => x.trim()).join(separator);
|
||||
|
||||
if (jointPrompt && jointPrompt.length) {
|
||||
roleMessages.push({ 'role': role, 'content': jointPrompt });
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { saveSettings, callPopup, substituteParams, getRequestHeaders, chat_metadata, this_chid, characters, saveCharacterDebounced, menu_type, eventSource, event_types, getExtensionPromptByName, saveMetadata, getCurrentChatId } from '../script.js';
|
||||
import { saveSettings, callPopup, substituteParams, getRequestHeaders, chat_metadata, this_chid, characters, saveCharacterDebounced, menu_type, eventSource, event_types, getExtensionPromptByName, saveMetadata, getCurrentChatId, extension_prompt_roles } from '../script.js';
|
||||
import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition, isTrueBoolean, setValueByPath } from './utils.js';
|
||||
import { extension_settings, getContext } from './extensions.js';
|
||||
import { NOTE_MODULE_NAME, metadata_keys, shouldWIAddPrompt } from './authors-note.js';
|
||||
|
@ -931,6 +931,7 @@ const originalDataKeyMap = {
|
|||
'depth': 'extensions.depth',
|
||||
'probability': 'extensions.probability',
|
||||
'position': 'extensions.position',
|
||||
'role': 'extensions.role',
|
||||
'content': 'content',
|
||||
'enabled': 'enabled',
|
||||
'key': 'keys',
|
||||
|
@ -1375,9 +1376,12 @@ function getWorldEntry(name, data, entry) {
|
|||
depthInput.prop('disabled', false);
|
||||
depthInput.css('visibility', 'visible');
|
||||
//depthInput.parent().show();
|
||||
const role = Number($(this).find(':selected').data('role'));
|
||||
data.entries[uid].role = role;
|
||||
} else {
|
||||
depthInput.prop('disabled', true);
|
||||
depthInput.css('visibility', 'hidden');
|
||||
data.entries[uid].role = null;
|
||||
//depthInput.parent().hide();
|
||||
}
|
||||
updatePosOrdDisplay(uid);
|
||||
|
@ -1385,11 +1389,13 @@ function getWorldEntry(name, data, entry) {
|
|||
setOriginalDataValue(data, uid, 'position', data.entries[uid].position == 0 ? 'before_char' : 'after_char');
|
||||
// Write the original value as extensions field
|
||||
setOriginalDataValue(data, uid, 'extensions.position', data.entries[uid].position);
|
||||
setOriginalDataValue(data, uid, 'extensions.role', data.entries[uid].role);
|
||||
saveWorldInfo(name, data);
|
||||
});
|
||||
|
||||
const roleValue = entry.position === world_info_position.atDepth ? String(entry.role ?? extension_prompt_roles.SYSTEM) : '';
|
||||
template
|
||||
.find(`select[name="position"] option[value=${entry.position}]`)
|
||||
.find(`select[name="position"] option[value=${entry.position}][data-role="${roleValue}"]`)
|
||||
.prop('selected', true)
|
||||
.trigger('input');
|
||||
|
||||
|
@ -1610,7 +1616,7 @@ function getWorldEntry(name, data, entry) {
|
|||
* @returns {(input: any, output: any) => any} Callback function for the autocomplete
|
||||
*/
|
||||
function getInclusionGroupCallback(data) {
|
||||
return function(input, output) {
|
||||
return function (input, output) {
|
||||
const groups = new Set();
|
||||
for (const entry of Object.values(data.entries)) {
|
||||
if (entry.group) {
|
||||
|
@ -1633,7 +1639,7 @@ function getInclusionGroupCallback(data) {
|
|||
}
|
||||
|
||||
function getAutomationIdCallback(data) {
|
||||
return function(input, output) {
|
||||
return function (input, output) {
|
||||
const ids = new Set();
|
||||
for (const entry of Object.values(data.entries)) {
|
||||
if (entry.automationId) {
|
||||
|
@ -1714,6 +1720,7 @@ const newEntryTemplate = {
|
|||
caseSensitive: null,
|
||||
matchWholeWords: null,
|
||||
automationId: '',
|
||||
role: 0,
|
||||
};
|
||||
|
||||
function createWorldInfoEntry(name, data, fromSlashCommand = false) {
|
||||
|
@ -2255,13 +2262,14 @@ async function checkWorldInfo(chat, maxContext) {
|
|||
ANBottomEntries.unshift(entry.content);
|
||||
break;
|
||||
case world_info_position.atDepth: {
|
||||
const existingDepthIndex = WIDepthEntries.findIndex((e) => e.depth === entry.depth ?? DEFAULT_DEPTH);
|
||||
const existingDepthIndex = WIDepthEntries.findIndex((e) => e.depth === (entry.depth ?? DEFAULT_DEPTH) && e.role === (entry.role ?? extension_prompt_roles.SYSTEM));
|
||||
if (existingDepthIndex !== -1) {
|
||||
WIDepthEntries[existingDepthIndex].entries.unshift(entry.content);
|
||||
} else {
|
||||
WIDepthEntries.push({
|
||||
depth: entry.depth,
|
||||
entries: [entry.content],
|
||||
role: entry.role ?? extension_prompt_roles.SYSTEM,
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
@ -2358,6 +2366,7 @@ function convertAgnaiMemoryBook(inputObj) {
|
|||
|
||||
inputObj.entries.forEach((entry, index) => {
|
||||
outputObj.entries[index] = {
|
||||
...newEntryTemplate,
|
||||
uid: index,
|
||||
key: entry.keywords,
|
||||
keysecondary: [],
|
||||
|
@ -2375,6 +2384,11 @@ function convertAgnaiMemoryBook(inputObj) {
|
|||
probability: null,
|
||||
useProbability: false,
|
||||
group: '',
|
||||
scanDepth: entry.extensions?.scan_depth ?? null,
|
||||
caseSensitive: entry.extensions?.case_sensitive ?? null,
|
||||
matchWholeWords: entry.extensions?.match_whole_words ?? null,
|
||||
automationId: entry.extensions?.automation_id ?? '',
|
||||
role: entry.extensions?.role ?? extension_prompt_roles.SYSTEM,
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -2386,6 +2400,7 @@ function convertRisuLorebook(inputObj) {
|
|||
|
||||
inputObj.data.forEach((entry, index) => {
|
||||
outputObj.entries[index] = {
|
||||
...newEntryTemplate,
|
||||
uid: index,
|
||||
key: entry.key.split(',').map(x => x.trim()),
|
||||
keysecondary: entry.secondkey ? entry.secondkey.split(',').map(x => x.trim()) : [],
|
||||
|
@ -2403,6 +2418,11 @@ function convertRisuLorebook(inputObj) {
|
|||
probability: entry.activationPercent ?? null,
|
||||
useProbability: entry.activationPercent ?? false,
|
||||
group: '',
|
||||
scanDepth: entry.extensions?.scan_depth ?? null,
|
||||
caseSensitive: entry.extensions?.case_sensitive ?? null,
|
||||
matchWholeWords: entry.extensions?.match_whole_words ?? null,
|
||||
automationId: entry.extensions?.automation_id ?? '',
|
||||
role: entry.extensions?.role ?? extension_prompt_roles.SYSTEM,
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -2419,6 +2439,7 @@ function convertNovelLorebook(inputObj) {
|
|||
const addMemo = displayName !== undefined && displayName.trim() !== '';
|
||||
|
||||
outputObj.entries[index] = {
|
||||
...newEntryTemplate,
|
||||
uid: index,
|
||||
key: entry.keys,
|
||||
keysecondary: [],
|
||||
|
@ -2436,6 +2457,11 @@ function convertNovelLorebook(inputObj) {
|
|||
probability: null,
|
||||
useProbability: false,
|
||||
group: '',
|
||||
scanDepth: entry.extensions?.scan_depth ?? null,
|
||||
caseSensitive: entry.extensions?.case_sensitive ?? null,
|
||||
matchWholeWords: entry.extensions?.match_whole_words ?? null,
|
||||
automationId: entry.extensions?.automation_id ?? '',
|
||||
role: entry.extensions?.role ?? extension_prompt_roles.SYSTEM,
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -2452,6 +2478,7 @@ function convertCharacterBook(characterBook) {
|
|||
}
|
||||
|
||||
result.entries[entry.id] = {
|
||||
...newEntryTemplate,
|
||||
uid: entry.id,
|
||||
key: entry.keys,
|
||||
keysecondary: entry.secondary_keys || [],
|
||||
|
@ -2475,6 +2502,7 @@ function convertCharacterBook(characterBook) {
|
|||
caseSensitive: entry.extensions?.case_sensitive ?? null,
|
||||
matchWholeWords: entry.extensions?.match_whole_words ?? null,
|
||||
automationId: entry.extensions?.automation_id ?? '',
|
||||
role: entry.extensions?.role ?? extension_prompt_roles.SYSTEM,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -406,6 +406,7 @@ function convertWorldInfoToCharacterBook(name, entries) {
|
|||
match_whole_words: entry.matchWholeWords ?? null,
|
||||
case_sensitive: entry.caseSensitive ?? null,
|
||||
automation_id: entry.automationId ?? '',
|
||||
role: entry.role ?? 0,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue