mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge remote-tracking branch 'upstream/staging' into improve-bulk-edit-and-fixes
This commit is contained in:
132
public/script.js
132
public/script.js
@ -2867,20 +2867,22 @@ class StreamingProcessor {
|
||||
* @param {string} prompt Prompt to generate a message from
|
||||
* @param {string} api API to use. Main API is used if not specified.
|
||||
* @param {boolean} instructOverride true to override instruct mode, false to use the default value
|
||||
* @param {boolean} quietToLoud true to generate a message in system mode, false to generate a message in character mode
|
||||
* @returns {Promise<string>} Generated message
|
||||
*/
|
||||
export async function generateRaw(prompt, api, instructOverride) {
|
||||
export async function generateRaw(prompt, api, instructOverride, quietToLoud) {
|
||||
if (!api) {
|
||||
api = main_api;
|
||||
}
|
||||
|
||||
const abortController = new AbortController();
|
||||
const isInstruct = power_user.instruct.enabled && main_api !== 'openai' && main_api !== 'novel' && !instructOverride;
|
||||
const isQuiet = true;
|
||||
|
||||
prompt = substituteParams(prompt);
|
||||
prompt = api == 'novel' ? adjustNovelInstructionPrompt(prompt) : prompt;
|
||||
prompt = isInstruct ? formatInstructModeChat(name1, prompt, false, true, '', name1, name2, false) : prompt;
|
||||
prompt = isInstruct ? (prompt + formatInstructModePrompt(name2, false, '', name1, name2)) : (prompt + '\n');
|
||||
prompt = isInstruct ? (prompt + formatInstructModePrompt(name2, false, '', name1, name2, isQuiet, quietToLoud)) : (prompt + '\n');
|
||||
|
||||
let generateData = {};
|
||||
|
||||
@ -3150,10 +3152,6 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
||||
mesExamples = '';
|
||||
}
|
||||
const mesExamplesRaw = mesExamples;
|
||||
if (mesExamples && isInstruct) {
|
||||
mesExamples = formatInstructModeExamples(mesExamples, name1, name2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a block heading to the examples string.
|
||||
* @param {string} examplesStr
|
||||
@ -3161,13 +3159,17 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
||||
*/
|
||||
function addBlockHeading(examplesStr) {
|
||||
const exampleSeparator = power_user.context.example_separator ? `${substituteParams(power_user.context.example_separator)}\n` : '';
|
||||
const blockHeading = main_api === 'openai' ? '<START>\n' : exampleSeparator;
|
||||
const blockHeading = main_api === 'openai' ? '<START>\n' : (exampleSeparator || (isInstruct ? '<START>\n' : ''));
|
||||
return examplesStr.split(/<START>/gi).slice(1).map(block => `${blockHeading}${block.trim()}\n`);
|
||||
}
|
||||
|
||||
let mesExamplesArray = addBlockHeading(mesExamples);
|
||||
let mesExamplesRawArray = addBlockHeading(mesExamplesRaw);
|
||||
|
||||
if (mesExamplesArray && isInstruct) {
|
||||
mesExamplesArray = formatInstructModeExamples(mesExamplesArray, name1, name2);
|
||||
}
|
||||
|
||||
// First message in fresh 1-on-1 chat reacts to user/character settings changes
|
||||
if (chat.length) {
|
||||
chat[0].mes = substituteParams(chat[0].mes);
|
||||
@ -3281,6 +3283,8 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
||||
|
||||
let chat2 = [];
|
||||
let continue_mag = '';
|
||||
const userMessageIndices = [];
|
||||
|
||||
for (let i = coreChat.length - 1, j = 0; i >= 0; i--, j++) {
|
||||
if (main_api == 'openai') {
|
||||
chat2[i] = coreChat[j].mes;
|
||||
@ -3308,6 +3312,22 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
||||
chat2[i] = chat2[i].slice(0, chat2[i].lastIndexOf(coreChat[j].mes) + coreChat[j].mes.length);
|
||||
continue_mag = coreChat[j].mes;
|
||||
}
|
||||
|
||||
if (coreChat[j].is_user) {
|
||||
userMessageIndices.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
let addUserAlignment = isInstruct && power_user.instruct.user_alignment_message;
|
||||
let userAlignmentMessage = '';
|
||||
|
||||
if (addUserAlignment) {
|
||||
const alignmentMessage = {
|
||||
name: name1,
|
||||
mes: power_user.instruct.user_alignment_message,
|
||||
is_user: true,
|
||||
};
|
||||
userAlignmentMessage = formatMessageHistoryItem(alignmentMessage, isInstruct, false);
|
||||
}
|
||||
|
||||
// Add persona description to prompt
|
||||
@ -3366,6 +3386,7 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
||||
allAnchors,
|
||||
quiet_prompt,
|
||||
cyclePrompt,
|
||||
userAlignmentMessage,
|
||||
].join('').replace(/\r/gm, '');
|
||||
return getTokenCount(encodeString, power_user.token_padding);
|
||||
}
|
||||
@ -3382,18 +3403,24 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
||||
}
|
||||
|
||||
// Collect enough messages to fill the context
|
||||
let arrMes = [];
|
||||
let arrMes = new Array(chat2.length);
|
||||
let tokenCount = getMessagesTokenCount();
|
||||
for (let item of chat2) {
|
||||
// not needed for OAI prompting
|
||||
if (main_api == 'openai') {
|
||||
break;
|
||||
let lastAddedIndex = -1;
|
||||
|
||||
// Pre-allocate all injections first.
|
||||
// If it doesn't fit - user shot himself in the foot
|
||||
for (const index of injectedIndices) {
|
||||
const item = chat2[index];
|
||||
|
||||
if (typeof item !== 'string') {
|
||||
continue;
|
||||
}
|
||||
|
||||
tokenCount += getTokenCount(item.replace(/\r/gm, ''));
|
||||
chatString = item + chatString;
|
||||
if (tokenCount < this_max_context) {
|
||||
arrMes[arrMes.length] = item;
|
||||
arrMes[index] = item;
|
||||
lastAddedIndex = Math.max(lastAddedIndex, index);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -3402,8 +3429,62 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
||||
await delay(1);
|
||||
}
|
||||
|
||||
for (let i = 0; i < chat2.length; i++) {
|
||||
// not needed for OAI prompting
|
||||
if (main_api == 'openai') {
|
||||
break;
|
||||
}
|
||||
|
||||
// Skip already injected messages
|
||||
if (arrMes[i] !== undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const item = chat2[i];
|
||||
|
||||
if (typeof item !== 'string') {
|
||||
continue;
|
||||
}
|
||||
|
||||
tokenCount += getTokenCount(item.replace(/\r/gm, ''));
|
||||
chatString = item + chatString;
|
||||
if (tokenCount < this_max_context) {
|
||||
arrMes[i] = item;
|
||||
lastAddedIndex = Math.max(lastAddedIndex, i);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
// Prevent UI thread lock on tokenization
|
||||
await delay(1);
|
||||
}
|
||||
|
||||
// Add user alignment message if last message is not a user message
|
||||
const stoppedAtUser = userMessageIndices.includes(lastAddedIndex);
|
||||
if (addUserAlignment && !stoppedAtUser) {
|
||||
tokenCount += getTokenCount(userAlignmentMessage.replace(/\r/gm, ''));
|
||||
chatString = userAlignmentMessage + chatString;
|
||||
arrMes.push(userAlignmentMessage);
|
||||
injectedIndices.push(arrMes.length - 1);
|
||||
}
|
||||
|
||||
// Unsparse the array. Adjust injected indices
|
||||
const newArrMes = [];
|
||||
const newInjectedIndices = [];
|
||||
for (let i = 0; i < arrMes.length; i++) {
|
||||
if (arrMes[i] !== undefined) {
|
||||
newArrMes.push(arrMes[i]);
|
||||
if (injectedIndices.includes(i)) {
|
||||
newInjectedIndices.push(newArrMes.length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arrMes = newArrMes;
|
||||
injectedIndices = newInjectedIndices;
|
||||
|
||||
if (main_api !== 'openai') {
|
||||
setInContextMessages(arrMes.length, type);
|
||||
setInContextMessages(arrMes.length - injectedIndices.length, type);
|
||||
}
|
||||
|
||||
// Estimate how many unpinned example messages fit in the context
|
||||
@ -3446,15 +3527,19 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
||||
console.debug('generating prompt');
|
||||
chatString = '';
|
||||
arrMes = arrMes.reverse();
|
||||
arrMes.forEach(function (item, i, arr) {// For added anchors and others
|
||||
arrMes.forEach(function (item, i, arr) {
|
||||
// OAI doesn't need all of this
|
||||
if (main_api === 'openai') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Cohee: I'm not even sure what this is for anymore
|
||||
// Cohee: This removes a newline from the end of the last message in the context
|
||||
// Last prompt line will add a newline if it's not a continuation
|
||||
// In instruct mode it only removes it if wrap is enabled and it's not a quiet generation
|
||||
if (i === arrMes.length - 1 && type !== 'continue') {
|
||||
item = item.replace(/\n?$/, '');
|
||||
if (!isInstruct || (power_user.instruct.wrap && type !== 'quiet')) {
|
||||
item = item.replace(/\n?$/, '');
|
||||
}
|
||||
}
|
||||
|
||||
mesSend[mesSend.length] = { message: item, extensionPrompts: [] };
|
||||
@ -3493,7 +3578,7 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
||||
//TODO: respect output_sequence vs last_output_sequence settings
|
||||
//TODO: decide how to prompt this to clarify who is talking 'Narrator', 'System', etc.
|
||||
if (isInstruct) {
|
||||
lastMesString += '\n' + quietAppend; // + power_user.instruct.output_sequence + '\n';
|
||||
lastMesString += quietAppend; // + power_user.instruct.output_sequence + '\n';
|
||||
} else {
|
||||
lastMesString += quietAppend;
|
||||
}
|
||||
@ -3514,7 +3599,8 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
||||
// Get instruct mode line
|
||||
if (isInstruct && !isContinue) {
|
||||
const name = (quiet_prompt && !quietToLoud) ? (quietName ?? 'System') : (isImpersonate ? name1 : name2);
|
||||
lastMesString += formatInstructModePrompt(name, isImpersonate, promptBias, name1, name2);
|
||||
const isQuiet = quiet_prompt && type == 'quiet';
|
||||
lastMesString += formatInstructModePrompt(name, isImpersonate, promptBias, name1, name2, isQuiet, quietToLoud);
|
||||
}
|
||||
|
||||
// Get non-instruct impersonation line
|
||||
@ -3681,7 +3767,7 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
||||
};
|
||||
|
||||
finalMesSend.forEach((item, i) => {
|
||||
item.injected = Array.isArray(injectedIndices) && injectedIndices.includes(i);
|
||||
item.injected = injectedIndices.includes(finalMesSend.length - i - 1);
|
||||
});
|
||||
|
||||
let data = {
|
||||
@ -4049,10 +4135,6 @@ function doChatInject(messages, isContinue) {
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < injectedIndices.length; i++) {
|
||||
injectedIndices[i] = messages.length - injectedIndices[i] - 1;
|
||||
}
|
||||
|
||||
messages.reverse();
|
||||
return injectedIndices;
|
||||
}
|
||||
@ -8309,7 +8391,7 @@ function addDebugFunctions() {
|
||||
registerDebugFunction('generationTest', 'Send a generation request', 'Generates text using the currently selected API.', async () => {
|
||||
const text = prompt('Input text:', 'Hello');
|
||||
toastr.info('Working on it...');
|
||||
const message = await generateRaw(text, null, '');
|
||||
const message = await generateRaw(text, null, false, false);
|
||||
alert(message);
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user