diff --git a/public/index.html b/public/index.html index 78903a5ad..53b51a072 100644 --- a/public/index.html +++ b/public/index.html @@ -1837,6 +1837,12 @@ Remove Empty New Lines from Output +

Context Templates @@ -3474,6 +3480,10 @@ Impersonate + + + Continue + Regenerate @@ -3542,4 +3552,4 @@ - \ No newline at end of file + diff --git a/public/script.js b/public/script.js index a03054ec8..6feac6274 100644 --- a/public/script.js +++ b/public/script.js @@ -1995,6 +1995,10 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, } } + if (!type && !textareaText && power_user.continue_on_send && !selected_group && chat.length && !chat[chat.length - 1]['is_user']) { + type = 'continue'; + } + deactivateSendButtons(); let { messageBias, promptBias, isUserPromptBias } = getBiasStrings(textareaText, type); @@ -2096,6 +2100,11 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, } chat2[i] = formatMessageHistoryItem(coreChat[j], isInstruct); + + // Do not format the message for continuation + if (i === 0 && type == 'continue') { + chat2[i] = coreChat[j].mes; + } } // Adjust token limit for Horde @@ -2163,6 +2172,11 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, pinExmString = examplesString = mesExamplesArray.join(''); } + let cyclePrompt = ''; + if (type == 'continue') { + cyclePrompt = chat2.shift(); + } + // Collect enough messages to fill the context let arrMes = []; let tokenCount = getMessagesTokenCount(); @@ -2207,13 +2221,25 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, let mesSend = []; console.debug('calling runGenerate'); streamingProcessor = isStreamingEnabled() ? new StreamingProcessor(type, force_name2) : false; - runGenerate(); + + if (type == 'continue') { + // Coping mechanism for OAI spacing + if (main_api === 'openai' && !cyclePrompt.endsWith(' ')) { + cyclePrompt += ' '; + } + + streamingProcessor && (streamingProcessor.firstMessageText = cyclePrompt); + message_already_generated = cyclePrompt; + tokens_already_generated = 1; // Multigen copium + } + + runGenerate(cyclePrompt); async function runGenerate(cycleGenerationPromt = '') { is_send_press = true; generatedPromtCache += cycleGenerationPromt; - if (generatedPromtCache.length == 0) { + if (generatedPromtCache.length == 0 || type === 'continue') { if (main_api === 'openai') { generateOpenAIPromptCache(); } @@ -2553,6 +2579,10 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, hideSwipeButtons(); let getMessage = await streamingProcessor.generate(); + if (type == 'continue') { + getMessage = message_already_generated + getMessage; + } + if (streamingProcessor && !streamingProcessor.isStopped && streamingProcessor.isFinished) { streamingProcessor.onFinishStreaming(streamingProcessor.messageId, getMessage); streamingProcessor = null; @@ -2607,7 +2637,12 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, tokens_already_generated = 0; generatedPromtCache = ""; - getMessage = message_already_generated.substring(magFirst.length); + const substringStart = type !== 'continue' ? magFirst.length : 0; + getMessage = message_already_generated.substring(substringStart); + } + + if (type == 'continue') { + getMessage = message_already_generated + getMessage; } //Formating @@ -3252,7 +3287,7 @@ function promptItemize(itemizedPrompts, requestedMesId) { function setInContextMessages(lastmsg, type) { $("#chat .mes").removeClass('lastInContext'); - if (type === 'swipe' || type === 'regenerate') { + if (type === 'swipe' || type === 'regenerate' || type === 'continue') { lastmsg++; } @@ -3437,7 +3472,7 @@ function cleanUpMessage(getMessage, isImpersonate, displayIncompleteSentences = } function saveReply(type, getMessage, this_mes_is_name, title) { - if (type != 'append' && type != 'appendFinal' && chat.length && (chat[chat.length - 1]['swipe_id'] === undefined || + if (type != 'append' && type != 'continue' && type != 'appendFinal' && chat.length && (chat[chat.length - 1]['swipe_id'] === undefined || chat[chat.length - 1]['is_user'])) { type = 'normal'; } @@ -3457,7 +3492,7 @@ function saveReply(type, getMessage, this_mes_is_name, title) { } else { chat[chat.length - 1]['mes'] = getMessage; } - } else if (type === 'append') { + } else if (type === 'append' || type === 'continue') { console.debug("Trying to append.") chat[chat.length - 1]['title'] = title; chat[chat.length - 1]['mes'] += getMessage; @@ -7132,6 +7167,13 @@ $(document).ready(function () { } } + else if (id == 'option_continue') { + if (is_send_press == false) { + is_send_press = true; + Generate("continue"); + } + } + else if (id == "option_delete_mes") { setTimeout(openMessageDelete, animation_duration); } diff --git a/public/scripts/group-chats.js b/public/scripts/group-chats.js index 53947c288..f6a9e08fd 100644 --- a/public/scripts/group-chats.js +++ b/public/scripts/group-chats.js @@ -501,7 +501,7 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { activatedMembers = activateListOrder(group.members.slice(0, 1)); } } - else if (type === "swipe") { + else if (type === "swipe" || type === 'continue') { activatedMembers = activateSwipe(group.members); if (activatedMembers.length === 0) { @@ -534,7 +534,7 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { for (const chId of activatedMembers) { deactivateSendButtons(); isGenerationDone = false; - const generateType = type == "swipe" || type == "impersonate" || type == "quiet" ? type : "group_chat"; + const generateType = type == "swipe" || type == "impersonate" || type == "quiet" || type == 'continue' ? type : "group_chat"; setCharacterId(chId); setCharacterName(characters[chId].name) diff --git a/public/scripts/openai.js b/public/scripts/openai.js index e48debf82..8caadfc9a 100644 --- a/public/scripts/openai.js +++ b/public/scripts/openai.js @@ -411,6 +411,14 @@ async function prepareOpenAIMessages({ systemPrompt, name2, storyString, worldIn await delay(1); } + if (type == 'continue') { + const continueNudge = { "role": "system", "content": '[Continue the last assistant message]' }; + openai_msgs.push(continueNudge); + + total_count += handler_instance.count([continueNudge], true, 'continue'); + await delay(1); + } + // The user wants to always have all example messages in the context if (power_user.pin_examples) { // first we send *all* example messages diff --git a/public/scripts/power-user.js b/public/scripts/power-user.js index a42ab447a..b8acf84bc 100644 --- a/public/scripts/power-user.js +++ b/public/scripts/power-user.js @@ -162,6 +162,7 @@ let power_user = { max_context_unlocked: false, prefer_character_prompt: true, prefer_character_jailbreak: true, + continue_on_send: false, instruct: { enabled: false, @@ -608,6 +609,7 @@ function loadPowerUserSettings(settings, data) { power_user.font_scale = Number(localStorage.getItem(storage_keys.font_scale) ?? 1); power_user.blur_strength = Number(localStorage.getItem(storage_keys.blur_strength) ?? 10); + $('#continue_on_send').prop("checked", power_user.continue_on_send); $('#auto_swipe').prop("checked", power_user.auto_swipe); $('#auto_swipe_minimum_length').val(power_user.auto_swipe_minimum_length); $('#auto_swipe_blacklist').val(power_user.auto_swipe_blacklist.join(", ")); @@ -1078,7 +1080,7 @@ async function doDelMode(_, text) { let lastMesID = $('.last_mes').attr('mesid') let oldestMesIDToDel = lastMesID - numMesToDel + 1; - //disallow targeting first message + //disallow targeting first message if (oldestMesIDToDel <= 0) { oldestMesIDToDel = 1 } @@ -1507,6 +1509,12 @@ $(document).ready(() => { saveSettingsDebounced(); }); + $("#continue_on_send").on("input", function () { + const value = !!$(this).prop('checked'); + power_user.continue_on_send = value; + saveSettingsDebounced(); + }); + $(window).on('focus', function () { browser_has_focus = true; });