Fix off-by-one cases in user prompt filler logic (#4648) * Fix off-by-one cases in user prompt filler logic Fixes #4645 * Skip inject pre-allocation in CC prompts * Fix filler insert on continuing on user message

a559f45ad4025263c083752cc5870541c6bc784c

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
2 files changed, +19 -5Showing whitespace changes
public/script.js+16 -5
@@ -177,6 +177,8 @@ import {
177 renderPaginationDropdown,177 renderPaginationDropdown,
178 paginationDropdownChangeHandler,178 paginationDropdownChangeHandler,
179 importFromExternalUrl,179 importFromExternalUrl,
180 shiftUpByOne,
181 shiftDownByOne,
180} from './scripts/utils.js';182} from './scripts/utils.js';
181import { debounce_timeout, GENERATION_TYPE_TRIGGERS, IGNORE_SYMBOL, inject_ids } from './scripts/constants.js';183import { debounce_timeout, GENERATION_TYPE_TRIGGERS, IGNORE_SYMBOL, inject_ids } from './scripts/constants.js';
182184
@@ -3910,14 +3912,14 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
3910 // This operation will result in the injectedIndices indexes being off by one3912 // This operation will result in the injectedIndices indexes being off by one
3911 coreChat.push({ mes: jailbreak, is_user: true });3913 coreChat.push({ mes: jailbreak, is_user: true });
3912 // Add +1 to the elements to correct for the new PHI/Jailbreak message.3914 // Add +1 to the elements to correct for the new PHI/Jailbreak message.
3913 injectedIndices.forEach((e, idx) => injectedIndices[idx] = e + 1);3915 injectedIndices.forEach(shiftUpByOne);
3914 }3916 }
3915 }3917 }
3916 }3918 }
39173919
3918 let chat2 = [];3920 let chat2 = [];
3919 let continue_mag = '';3921 let continue_mag = '';
3920 const userMessageIndices = [];3922 let userMessageIndices = [];
3921 const lastUserMessageIndex = coreChat.findLastIndex(x => x.is_user);3923 const lastUserMessageIndex = coreChat.findLastIndex(x => x.is_user);
39223924
3923 for (let i = coreChat.length - 1, j = 0; i >= 0; i--, j++) {3925 for (let i = coreChat.length - 1, j = 0; i >= 0; i--, j++) {
@@ -4016,16 +4018,24 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
4016 // Only add the chat in context if past the greeting message4018 // Only add the chat in context if past the greeting message
4017 if (isContinue && (chat2.length > 1 || main_api === 'openai')) {4019 if (isContinue && (chat2.length > 1 || main_api === 'openai')) {
4018 cyclePrompt = chat2.shift();4020 cyclePrompt = chat2.shift();
4021 // Adjust indices to account for the shift
4022 injectedIndices = injectedIndices.map(shiftDownByOne).filter(x => x >= 0);
4023 userMessageIndices = userMessageIndices.map(shiftDownByOne).filter(x => x >= 0);
4019 }4024 }
40204025
4021 // Collect enough messages to fill the context4026 // Collect enough messages to fill the context
4022 let arrMes = new Array(chat2.length);4027 let arrMes = new Array(chat2.length);
4023 let tokenCount = await getMessagesTokenCount();4028 let tokenCount = await getMessagesTokenCount();
4024 let lastAddedIndex = -1;4029 let lastAddedIndex = 0;
40254030
4026 // Pre-allocate all injections first.4031 // Pre-allocate all injections first.
4027 // If it doesn't fit - user shot himself in the foot4032 // If it doesn't fit - user shot himself in the foot
4028 for (const index of injectedIndices) {4033 for (const index of injectedIndices) {
4034 // not needed for OAI prompting
4035 if (main_api == 'openai') {
4036 break;
4037 }
4038
4029 const item = chat2[index];4039 const item = chat2[index];
40304040
4031 if (typeof item !== 'string') {4041 if (typeof item !== 'string') {
@@ -4768,7 +4778,7 @@ export function stopGeneration() {
4768 * @returns {Promise<number[]>} Array of indices where the extension prompts were injected4778 * @returns {Promise<number[]>} Array of indices where the extension prompts were injected
4769 */4779 */
4770async function doChatInject(messages, isContinue) {4780async function doChatInject(messages, isContinue) {
4771 const injectedIndices = [];4781 const injectedMessages = [];
4772 let totalInsertedMessages = 0;4782 let totalInsertedMessages = 0;
4773 messages.reverse();4783 messages.reverse();
47744784
@@ -4808,10 +4818,11 @@ async function doChatInject(messages, isContinue) {
4808 const injectIdx = Math.min(depth + totalInsertedMessages, messages.length);4818 const injectIdx = Math.min(depth + totalInsertedMessages, messages.length);
4809 messages.splice(injectIdx, 0, ...roleMessages);4819 messages.splice(injectIdx, 0, ...roleMessages);
4810 totalInsertedMessages += roleMessages.length;4820 totalInsertedMessages += roleMessages.length;
4811 injectedIndices.push(...Array.from({ length: roleMessages.length }, (_, i) => injectIdx + i));4821 injectedMessages.push(...roleMessages);
4812 }4822 }
4813 }4823 }
48144824
4825 const injectedIndices = injectedMessages.map(msg => messages.indexOf(msg));
4815 messages.reverse();4826 messages.reverse();
4816 return injectedIndices;4827 return injectedIndices;
4817}4828}
public/scripts/utils.js+3 -0
@@ -18,6 +18,9 @@ import { groups, selected_group } from './group-chats.js';
18import { getCurrentLocale, t } from './i18n.js';18import { getCurrentLocale, t } from './i18n.js';
19import { importWorldInfo } from './world-info.js';19import { importWorldInfo } from './world-info.js';
2020
21export const shiftUpByOne = (e, i, a) => a[i] = e + 1;
22export const shiftDownByOne = (e, i, a) => a[i] = e - 1;
23
21/**24/**
22 * Pagination status string template.25 * Pagination status string template.
23 * @type {string}26 * @type {string}