diff --git a/public/css/mobile-styles.css b/public/css/mobile-styles.css index a53758a8f..0a720b00d 100644 --- a/public/css/mobile-styles.css +++ b/public/css/mobile-styles.css @@ -91,7 +91,7 @@ #top-settings-holder, #top-bar { position: fixed; - padding-top: 8px; + padding-top: 3px; width: 100vw; width: 100svw; } @@ -114,14 +114,14 @@ /* , #world_popup */ { - max-height: calc(100vh - 40px); - max-height: calc(100svh - 40px); + max-height: calc(100vh - 36px); + max-height: calc(100svh - 36px); width: 100% !important; margin: 0 auto; max-width: 100%; left: 0 !important; resize: none !important; - top: 40px; + top: 36px; } .wi-settings { @@ -179,7 +179,7 @@ border-right: 1px solid var(--grey30); border-bottom: 1px solid var(--grey30); border-radius: 0 0 20px 20px; - top: 40px !important; + top: 36px !important; left: 0 !important; backdrop-filter: blur(calc(var(--SmartThemeBlurStrength) * 2)); } @@ -354,8 +354,8 @@ max-height: unset; width: 100vw; width: 100svw; - height: calc(100vh - 40px); - height: calc(100svh - 40px); + height: calc(100vh - 36px); + height: calc(100svh - 36px); padding-right: max(env(safe-area-inset-right), 0px); padding-left: max(env(safe-area-inset-left), 0px); padding-bottom: 0; @@ -396,7 +396,7 @@ #character_popup, #world_popup, .drawer-content { - margin-top: 40px; + margin-top: 36px; } .scrollableInner { @@ -407,4 +407,4 @@ #horde_model { height: unset; } -} +} \ No newline at end of file diff --git a/public/css/st-tailwind.css b/public/css/st-tailwind.css index 5a0c1c52d..b505fccd6 100644 --- a/public/css/st-tailwind.css +++ b/public/css/st-tailwind.css @@ -349,7 +349,7 @@ } .textarea_compact { - font-size: calc(var(--mainFontSize) * 0.9); + font-size: calc(var(--mainFontSize) * 0.95); line-height: 1.2; } @@ -416,4 +416,4 @@ .opacity1 { opacity: 1 !important; -} \ No newline at end of file +} diff --git a/public/script.js b/public/script.js index 3389cc096..dc26d9670 100644 --- a/public/script.js +++ b/public/script.js @@ -165,6 +165,7 @@ import { formatInstructModeExamples, getInstructStoppingSequences, autoSelectInstructPreset, + formatInstructModeSystemPrompt, } from "./scripts/instruct-mode.js"; import { applyLocale } from "./scripts/i18n.js"; import { getTokenCount, getTokenizerModel, saveTokenCache } from "./scripts/tokenizers.js"; @@ -322,6 +323,7 @@ let generatedPromtCache = ""; let generation_started = new Date(); let characters = []; let this_chid; +let saveCharactersPage = 0; let backgrounds = []; const default_avatar = "img/ai4.png"; export const system_avatar = "img/five.png"; @@ -893,6 +895,7 @@ async function printCharacters(fullRefresh = false) { pageSize: Number(localStorage.getItem(storageKey)) || 50, sizeChangerOptions: [10, 25, 50, 100, 250, 500, 1000], pageRange: 1, + pageNumber: saveCharactersPage || 1, position: 'top', showPageNumbers: false, showSizeChanger: true, @@ -913,10 +916,14 @@ async function printCharacters(fullRefresh = false) { }, afterSizeSelectorChange: function (e) { localStorage.setItem(storageKey, e.target.value); - } + }, + afterPaging: function (e) { + saveCharactersPage = e; + }, }); favsToHotswap(); + saveCharactersPage = 0; if (fullRefresh) { printTagFilters(tag_filter_types.character); @@ -2354,6 +2361,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, if (isInstruct) { systemPrompt = power_user.prefer_character_prompt && systemPrompt ? systemPrompt : baseChatReplace(power_user.instruct.system_prompt, name1, name2); + systemPrompt = formatInstructModeSystemPrompt(substituteParams(systemPrompt, name1, name2, power_user.instruct.system_prompt)); } // Parse example messages @@ -2733,6 +2741,12 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, // Fetches the combined prompt for both negative and positive prompts const cfgGuidanceScale = getGuidanceScale(); function getCombinedPrompt(isNegative) { + // Only return if the guidance scale doesn't exist or the value is 1 + // Also don't return if constructing the neutral prompt + if (isNegative && (!cfgGuidanceScale || cfgGuidanceScale?.value === 1)) { + return; + } + let finalMesSend = [...mesSend]; let cfgPrompt = {}; if (cfgGuidanceScale && cfgGuidanceScale?.value !== 1) { @@ -2746,7 +2760,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, ? cfgPrompt.value : ` ${cfgPrompt.value}`; } else { - // TODO: Switch from splice method to insertion depth method + // TODO: Make all extension prompts use an array/splice method finalMesSend.splice(mesSend.length - cfgPrompt.depth, 0, `${cfgPrompt.value}\n`); } } @@ -2809,12 +2823,9 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, let finalPromt = getCombinedPrompt(false); // Include the entire guidance scale object - const cfgValues = { - guidanceScale: cfgGuidanceScale, - negativePrompt: negativePrompt - }; + const cfgValues = cfgGuidanceScale && cfgGuidanceScale?.value !== 1 ? ({guidanceScale: cfgGuidanceScale, negativePrompt: negativePrompt }) : null; - let this_amount_gen = parseInt(amount_gen); // how many tokens the AI will be requested to generate + let this_amount_gen = Number(amount_gen); // how many tokens the AI will be requested to generate let this_settings = koboldai_settings[koboldai_setting_names[preset_settings]]; if (isMultigenEnabled() && type !== 'quiet') { @@ -2991,8 +3002,6 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, return; } - hideStopButton(); - is_send_press = false; if (!data.error) { //const getData = await response.json(); let getMessage = extractMessageFromData(data); @@ -3113,6 +3122,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, } if (generatedTextFiltered(getMessage)) { console.debug('swiping right automatically'); + is_send_press = false; swipe_right(); return } @@ -3132,7 +3142,9 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, } console.debug('/savechat called by /Generate'); - saveChatConditional(); + await saveChatConditional(); + is_send_press = false; + hideStopButton(); activateSendButtons(); showSwipeButtons(); setGenerationProgress(0); @@ -6113,7 +6125,7 @@ async function deleteMessageImage() { delete message.extra.inline_image; mesBlock.find('.mes_img_container').removeClass('img_extra'); mesBlock.find('.mes_img').attr('src', ''); - saveChatConditional(); + await saveChatConditional(); } function enlargeMessageImage() { @@ -7908,7 +7920,7 @@ $(document).ready(function () { }); //confirms message deletion with the "ok" button - $("#dialogue_del_mes_ok").click(function () { + $("#dialogue_del_mes_ok").click(async function () { $("#dialogue_del_mes").css("display", "none"); $("#send_form").css("display", css_send_form_display); $(".del_checkbox").each(function () { @@ -7924,7 +7936,7 @@ $(document).ready(function () { $(".mes[mesid='" + this_del_mes + "']").remove(); chat.length = this_del_mes; count_view_mes = this_del_mes; - saveChatConditional(); + await saveChatConditional(); var $textchat = $("#chat"); $textchat.scrollTop($textchat[0].scrollHeight); eventSource.emit(event_types.MESSAGE_DELETED, chat.length); @@ -8199,7 +8211,7 @@ $(document).ready(function () { this_edit_mes_id = undefined; }); - $(document).on("click", ".mes_edit_up", function () { + $(document).on("click", ".mes_edit_up", async function () { if (is_send_press || this_edit_mes_id <= 0) { return; } @@ -8224,11 +8236,11 @@ $(document).ready(function () { this_edit_mes_id = targetId; updateViewMessageIds(); - saveChatConditional(); + await saveChatConditional(); showSwipeButtons(); }); - $(document).on("click", ".mes_edit_down", function () { + $(document).on("click", ".mes_edit_down", async function () { if (is_send_press || this_edit_mes_id >= chat.length - 1) { return; } @@ -8253,7 +8265,7 @@ $(document).ready(function () { this_edit_mes_id = targetId; updateViewMessageIds(); - saveChatConditional(); + await saveChatConditional(); showSwipeButtons(); }); @@ -8277,14 +8289,14 @@ $(document).ready(function () { addOneMessage(clone, { insertAfter: this_edit_mes_id }); updateViewMessageIds(); - saveChatConditional(); + await saveChatConditional(); $('#chat')[0].scrollTop = oldScroll; showSwipeButtons(); }); $(document).on("click", ".mes_edit_delete", async function (event, customData) { const fromSlashCommand = customData?.fromSlashCommand || false; - const swipeExists = (!chat[this_edit_mes_id].swipes || chat[this_edit_mes_id].swipes.length <= 1 || chat.is_user || parseInt(this_edit_mes_id) !== chat.length - 1); + const swipeExists = (!Array.isArray(chat[this_edit_mes_id].swipes) || chat[this_edit_mes_id].swipes.length <= 1 || chat[this_edit_mes_id].is_user || parseInt(this_edit_mes_id) !== chat.length - 1); if (power_user.confirm_message_delete && fromSlashCommand !== true) { const confirmation = swipeExists ? await callPopup("Are you sure you want to delete this message?", 'confirm') : await callPopup("

Delete this...

", 'confirm') @@ -8316,7 +8328,7 @@ $(document).ready(function () { this_edit_mes_id = undefined; updateViewMessageIds(); - saveChatConditional(); + await saveChatConditional(); eventSource.emit(event_types.MESSAGE_DELETED, count_view_mes); diff --git a/public/scripts/RossAscends-mods.js b/public/scripts/RossAscends-mods.js index 1f7cdcfe9..1afb36030 100644 --- a/public/scripts/RossAscends-mods.js +++ b/public/scripts/RossAscends-mods.js @@ -521,7 +521,7 @@ export function dragElement(elmnt) { } //prevent resizing from top left into the top bar - if (top < 40 && maxX >= topBarFirstX && left <= topBarFirstX + if (top < 35 && maxX >= topBarFirstX && left <= topBarFirstX ) { console.debug('prevent topbar underlap resize') elmnt.css('width', width - 1 + "px"); @@ -556,7 +556,7 @@ export function dragElement(elmnt) { } //prevent underlap with topbar div - if (top < 40 + if (top < 35 && (maxX >= topBarFirstX && left <= topBarFirstX //elmnt is hitting topbar from left side || left <= topBarLastX && maxX >= topBarLastX //elmnt is hitting topbar from right side || left >= topBarFirstX && maxX <= topBarLastX) //elmnt hitting topbar in the middle @@ -841,7 +841,7 @@ jQuery(async function () { //this makes the chat input text area resize vertically to match the text size (limited by CSS at 50% window height) $('#send_textarea').on('input', function () { - this.style.height = '40px'; + this.style.height = '30px'; this.style.height = (this.scrollHeight) + 'px'; }); diff --git a/public/scripts/extensions/cfg/index.js b/public/scripts/extensions/cfg/index.js index c850ca6d6..f572d2c63 100644 --- a/public/scripts/extensions/cfg/index.js +++ b/public/scripts/extensions/cfg/index.js @@ -348,7 +348,7 @@ jQuery(async () => { .filter(":checked") .map(function() { return parseInt($(this).val()) }) .get() - .filter((e) => e !== NaN) || []; + .filter((e) => !Number.isNaN(e)) || []; chat_metadata[metadataKeys.prompt_combine] = values; saveMetadataDebounced(); diff --git a/public/scripts/extensions/cfg/util.js b/public/scripts/extensions/cfg/util.js index 850978884..6e156d5d9 100644 --- a/public/scripts/extensions/cfg/util.js +++ b/public/scripts/extensions/cfg/util.js @@ -39,10 +39,12 @@ export function getGuidanceScale() { }; } - return { - type: cfgType.global, - value: extension_settings.cfg.global.guidance_scale - }; + if (extension_settings.cfg.global && extension_settings.cfg.global?.guidance_scale !== 1) { + return { + type: cfgType.global, + value: extension_settings.cfg.global.guidance_scale + }; + } } // Gets the CFG prompt diff --git a/public/scripts/extensions/translate/index.js b/public/scripts/extensions/translate/index.js index ac477ffe3..6a10b787d 100644 --- a/public/scripts/extensions/translate/index.js +++ b/public/scripts/extensions/translate/index.js @@ -217,6 +217,10 @@ async function translateProviderDeepl(text, lang) { async function translate(text, lang) { try { + if (text == '') { + return ''; + } + switch (extension_settings.translate.provider) { case 'google': return await translateProviderGoogle(text, lang); diff --git a/public/scripts/instruct-mode.js b/public/scripts/instruct-mode.js index bc75e266d..d15274d2f 100644 --- a/public/scripts/instruct-mode.js +++ b/public/scripts/instruct-mode.js @@ -189,6 +189,20 @@ export function formatInstructModeChat(name, mes, isUser, isNarrator, forceAvata return text; } +/** + * Formats instruct mode system prompt. + * @param {string} systemPrompt System prompt string. + * @returns {string} Formatted instruct mode system prompt. + */ +export function formatInstructModeSystemPrompt(systemPrompt){ + if (power_user.instruct.system_sequence) { + const separator = power_user.instruct.wrap ? '\n' : ''; + return power_user.instruct.system_sequence + separator + systemPrompt; + } + + return systemPrompt; +} + /** * Formats example messages according to instruct mode settings. * @param {string} mesExamples Example messages string. diff --git a/public/scripts/nai-settings.js b/public/scripts/nai-settings.js index 41fc87791..3ebc435e9 100644 --- a/public/scripts/nai-settings.js +++ b/public/scripts/nai-settings.js @@ -128,8 +128,8 @@ function loadNovelPreset(preset) { function loadNovelSettings(settings) { //load the rest of the Novel settings without any checks nai_settings.model_novel = settings.model_novel; - $(`#model_novel_select option[value=${nai_settings.model_novel}]`).attr("selected", true); $('#model_novel_select').val(nai_settings.model_novel); + $(`#model_novel_select option[value=${nai_settings.model_novel}]`).attr("selected", true); if (settings.nai_preamble !== undefined) { nai_settings.preamble = settings.nai_preamble; @@ -396,7 +396,7 @@ function getBadWordPermutations(text) { } export function getNovelGenerationData(finalPrompt, this_settings, this_amount_gen, isImpersonate, cfgValues) { - if (cfgValues.guidanceScale && cfgValues.guidanceScale?.value !== 1) { + if (cfgValues && cfgValues.guidanceScale && cfgValues.guidanceScale?.value !== 1) { cfgValues.negativePrompt = (getCfgPrompt(cfgValues.guidanceScale, true))?.value; } @@ -425,22 +425,22 @@ export function getNovelGenerationData(finalPrompt, this_settings, this_amount_g "input": finalPrompt, "model": nai_settings.model_novel, "use_string": true, - "temperature": parseFloat(nai_settings.temperature), + "temperature": Number(nai_settings.temperature), "max_length": this_amount_gen < maximum_output_length ? this_amount_gen : maximum_output_length, - "min_length": parseInt(nai_settings.min_length), - "tail_free_sampling": parseFloat(nai_settings.tail_free_sampling), - "repetition_penalty": parseFloat(nai_settings.repetition_penalty), - "repetition_penalty_range": parseInt(nai_settings.repetition_penalty_range), - "repetition_penalty_slope": parseFloat(nai_settings.repetition_penalty_slope), - "repetition_penalty_frequency": parseFloat(nai_settings.repetition_penalty_frequency), - "repetition_penalty_presence": parseFloat(nai_settings.repetition_penalty_presence), - "top_a": parseFloat(nai_settings.top_a), - "top_p": parseFloat(nai_settings.top_p), - "top_k": parseInt(nai_settings.top_k), - "typical_p": parseFloat(nai_settings.typical_p), - "mirostat_lr": parseFloat(nai_settings.mirostat_lr), - "mirostat_tau": parseFloat(nai_settings.mirostat_tau), - "cfg_scale": cfgValues?.guidanceScale?.value ?? parseFloat(nai_settings.cfg_scale), + "min_length": Number(nai_settings.min_length), + "tail_free_sampling": Number(nai_settings.tail_free_sampling), + "repetition_penalty": Number(nai_settings.repetition_penalty), + "repetition_penalty_range": Number(nai_settings.repetition_penalty_range), + "repetition_penalty_slope": Number(nai_settings.repetition_penalty_slope), + "repetition_penalty_frequency": Number(nai_settings.repetition_penalty_frequency), + "repetition_penalty_presence": Number(nai_settings.repetition_penalty_presence), + "top_a": Number(nai_settings.top_a), + "top_p": Number(nai_settings.top_p), + "top_k": Number(nai_settings.top_k), + "typical_p": Number(nai_settings.typical_p), + "mirostat_lr": Number(nai_settings.mirostat_lr), + "mirostat_tau": Number(nai_settings.mirostat_tau), + "cfg_scale": cfgValues?.guidanceScale?.value ?? Number(nai_settings.cfg_scale), "cfg_uc": cfgValues?.negativePrompt ?? nai_settings.cfg_uc ?? "", "phrase_rep_pen": nai_settings.phrase_rep_pen, "stop_sequences": stopSequences, @@ -448,7 +448,6 @@ export function getNovelGenerationData(finalPrompt, this_settings, this_amount_g "logit_bias_exp": logitBias, "generate_until_sentence": true, "use_cache": false, - "use_string": true, "return_full_text": false, "prefix": prefix, "order": nai_settings.order || this_settings.order || default_order, @@ -640,7 +639,7 @@ export async function generateNovelWithStreaming(generate_data, signal) { } $("#nai_preamble_textarea").on('input', function () { - nai_settings.preamble = $('#nai_preamble_textarea').val(); + nai_settings.preamble = String($('#nai_preamble_textarea').val()); saveSettingsDebounced(); }); @@ -668,7 +667,7 @@ jQuery(function () { }); $("#model_novel_select").change(function () { - nai_settings.model_novel = $("#model_novel_select").find(":selected").val(); + nai_settings.model_novel = String($("#model_novel_select").find(":selected").val()); saveSettingsDebounced(); // Update the selected preset to something appropriate @@ -679,12 +678,12 @@ jQuery(function () { }); $("#nai_prefix").on('change', function () { - nai_settings.prefix = $("#nai_prefix").find(":selected").val(); + nai_settings.prefix = String($("#nai_prefix").find(":selected").val()); saveSettingsDebounced(); }); $("#phrase_rep_pen_novel").on('change', function () { - nai_settings.phrase_rep_pen = $("#phrase_rep_pen_novel").find(":selected").val(); + nai_settings.phrase_rep_pen = String($("#phrase_rep_pen_novel").find(":selected").val()); saveSettingsDebounced(); }); diff --git a/public/scripts/openai.js b/public/scripts/openai.js index aef41beb8..e85506649 100644 --- a/public/scripts/openai.js +++ b/public/scripts/openai.js @@ -165,6 +165,7 @@ const default_settings = { new_group_chat_prompt: default_new_group_chat_prompt, new_example_chat_prompt: default_new_example_chat_prompt, continue_nudge_prompt: default_continue_nudge_prompt, + nsfw_avoidance_prompt: default_nsfw_avoidance_prompt, bias_preset_selected: default_bias, bias_presets: default_bias_presets, wi_format: default_wi_format, @@ -228,6 +229,7 @@ const oai_settings = { use_ai21_tokenizer: false, exclude_assistant: false, use_alt_scale: false, + nsfw_avoidance_prompt: default_nsfw_avoidance_prompt, }; let openai_setting_names; @@ -772,6 +774,7 @@ function preparePromptsForChatCompletion(Scenario, charPersonality, name2, world * @param {string} content.bias - The bias to be added in the conversation. * @param {string} content.type - The type of the chat, can be 'impersonate'. * @param {string} content.quietPrompt - The quiet prompt to be used in the conversation. + * @param {string} content.cyclePrompt - The last prompt used for chat message continuation. * @param {Array} content.extensionPrompts - An array of additional prompts. * @param dryRun - Whether this is a live call or not. * @returns {(*[]|boolean)[]} An array where the first element is the prepared chat and the second element is a boolean flag. @@ -882,7 +885,7 @@ async function sendWindowAIRequest(openai_msgs_tosend, signal, stream) { let finished = false; const currentModel = await window.ai.getCurrentModel(); - let temperature = parseFloat(oai_settings.temp_openai); + let temperature = Number(oai_settings.temp_openai); if ((currentModel.includes('claude') || currentModel.includes('palm-2')) && temperature > claude_max_temp) { console.warn(`Claude and PaLM models only supports temperature up to ${claude_max_temp}. Clamping ${temperature} to ${claude_max_temp}.`); @@ -1014,7 +1017,7 @@ function saveModelList(data) { $('#model_openrouter_select').empty(); $('#model_openrouter_select').append($('