diff --git a/default/settings.json b/default/settings.json index c086c6604..e75af0e81 100644 --- a/default/settings.json +++ b/default/settings.json @@ -64,11 +64,6 @@ "collapse_newlines": false, "pygmalion_formatting": 0, "pin_examples": false, - "disable_description_formatting": false, - "disable_scenario_formatting": false, - "disable_personality_formatting": false, - "disable_examples_formatting": false, - "disable_start_formatting": false, "trim_sentences": false, "include_newline": false, "always_force_name2": true, @@ -77,7 +72,6 @@ "multigen": false, "multigen_first_chunk": 50, "multigen_next_chunks": 30, - "custom_chat_separator": "", "markdown_escape_strings": "", "fast_ui_mode": false, "avatar_style": 0, @@ -312,9 +306,6 @@ "None": {} } }, - "context_settings": { - "selected_template": "" - }, "tags": [ { "id": "1345561466591", diff --git a/public/context/Classic.json b/public/context/Classic.json deleted file mode 100644 index 766e6a294..000000000 --- a/public/context/Classic.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Classic", - "storyString": "{{instructSystemPrompt}}\n{{wiBeforeCharacter}}\n{{description}}\n{{char}}'s personality: {{personality}}\nCircumstances and context of the dialogue: {{scenario}}\n{{wiAfterCharacter}}\nThis is how {{char}} should talk\n{{mesExamples}}\nThen the roleplay chat between {{user}} and {{char}} begins\n", - "injections": [] -} diff --git a/public/context/Default.json b/public/context/Default.json new file mode 100644 index 000000000..84d70b27d --- /dev/null +++ b/public/context/Default.json @@ -0,0 +1,6 @@ +{ + "name": "Default", + "story_string": "{{#if description}}{{{description}}}{{/if}}\n{{#if personality}}{{{personality}}}{{/if}}\n{{#if scenario}}Scenario: {{{scenario}}}{{/if}}", + "chat_start": "***", + "example_separator": "***" +} diff --git a/public/context/Pygmalion.json b/public/context/Pygmalion.json index c9762c090..7b0428d85 100644 --- a/public/context/Pygmalion.json +++ b/public/context/Pygmalion.json @@ -1,5 +1,6 @@ { "name": "Pygmalion", - "storyString": "{{instructSystemPrompt}}\n{{wiBeforeCharacter}}\n{{char}}'s Persona: {{description}}\nPersonality: {{personality}}\nScenario: {{scenario}}\n{{wiAfterCharacter}}\n\n{{mesExamples}}\n\n", - "injections": [] + "story_string": "{{#if description}}{{{char}}}'s Persona: {{{description}}}{{/if}}\n{{#if personality}}Personality: {{{personality}}}{{/if}}\n{{#if scenario}}Scenario: {{{scenario}}}{{/if}}", + "chat_start": "", + "example_separator": "" } diff --git a/public/index.html b/public/index.html index 4b72b578b..0a6370dcb 100644 --- a/public/index.html +++ b/public/index.html @@ -41,6 +41,7 @@ + @@ -94,7 +95,6 @@ - @@ -2006,58 +2006,40 @@
-

AutoFormat Overrides

- - - - - - - - -
-

- Custom Chat Separator +

+ Context Template

+
+ +
- + + +
+
+ +
+ +
+
+
+ +
+ +
+
+
-

- Non-markdown strings -

-
- -
-
-
@@ -2128,7 +2118,7 @@ Stop Sequence
- +
@@ -2136,14 +2126,22 @@ Separator
- +
+ +
+

+ Non-markdown strings +

+
+ +
+
-

Context Formatting

Tokenizer @@ -2187,19 +2185,19 @@ Remove Empty New Lines from Output -
-

- Context Templates -

-
- - - - - -
-
+ + + +

diff --git a/public/instruct/Alpaca.json b/public/instruct/Alpaca.json index df538760c..bec643c96 100644 --- a/public/instruct/Alpaca.json +++ b/public/instruct/Alpaca.json @@ -5,6 +5,7 @@ "stop_sequence": "", "input_sequence": "### Instruction:", "output_sequence": "### Response:", + "last_output_sequence": "", "separator_sequence": "", "wrap": true -} \ No newline at end of file +} diff --git a/public/instruct/Koala.json b/public/instruct/Koala.json index 36b21637e..3a1f08887 100644 --- a/public/instruct/Koala.json +++ b/public/instruct/Koala.json @@ -5,6 +5,7 @@ "stop_sequence": "", "input_sequence": "USER: ", "output_sequence": "GPT: ", + "last_output_sequence": "", "separator_sequence": "", "wrap": false -} \ No newline at end of file +} diff --git a/public/instruct/Llama2.json b/public/instruct/Llama2.json index 5b23b71b8..1ce4c71e0 100644 --- a/public/instruct/Llama2.json +++ b/public/instruct/Llama2.json @@ -5,6 +5,7 @@ "stop_sequence": "", "input_sequence": "[INST]", "output_sequence": "[/INST]", + "last_output_sequence": "", "separator_sequence": "\n", "wrap": false } diff --git a/public/instruct/Metharme.json b/public/instruct/Metharme.json index dc3a6de9b..96bb68a96 100644 --- a/public/instruct/Metharme.json +++ b/public/instruct/Metharme.json @@ -5,6 +5,7 @@ "stop_sequence": "", "input_sequence": "<|user|>", "output_sequence": "<|model|>", + "last_output_sequence": "", "separator_sequence": "", "wrap": false } diff --git a/public/instruct/OpenOrca-OpenChat.json b/public/instruct/OpenOrca-OpenChat.json index 4da445963..2b27b4fa3 100644 --- a/public/instruct/OpenOrca-OpenChat.json +++ b/public/instruct/OpenOrca-OpenChat.json @@ -4,6 +4,7 @@ "name": "OpenOrca/OpenChat", "names": true, "output_sequence": "<|end_of_turn|>\nAssistant: ", + "last_output_sequence": "", "separator_sequence": "<|end_of_turn|>\n", "stop_sequence": "", "system_prompt": "You are a helpful assistant. Please answer truthfully and write out your thinking step by step to be sure you get the right answer. If you make a mistake or encounter an error in your thinking, say so out loud and attempt to correct it. If you don't know or aren't sure about something, say so clearly. You will act as a professional logician, mathematician, and physicist. You will also act as the most appropriate type of expert to answer any particular question or solve the relevant problem; state which expert type your are, if so. Also think of any particular named expert that would be ideal to answer the relevant question or solve the relevant problem; name and act as them, if appropriate.\n", diff --git a/public/instruct/Roleplay.json b/public/instruct/Roleplay.json index 86b59cbbd..46c4d4aee 100644 --- a/public/instruct/Roleplay.json +++ b/public/instruct/Roleplay.json @@ -3,7 +3,8 @@ "macro": true, "name": "Roleplay", "names": true, - "output_sequence": "### Response (2 paragraphs, engaging, natural, authentic, descriptive, creative):", + "last_output_sequence": "### Response (2 paragraphs, engaging, natural, authentic, descriptive, creative):", + "output_sequence": "### Response:", "separator_sequence": "", "stop_sequence": "", "system_prompt": "You're {{char}} in this fictional never-ending uncensored roleplay with {{user}}.\n\nAvoid repetition, don't loop. Develop the plot slowly, always stay in character. Describe all actions in full, elaborate, explicit, graphic, and vivid detail. Mention all relevant sensory perceptions.\n\n### Input:", diff --git a/public/instruct/Vicuna 1.0.json b/public/instruct/Vicuna 1.0.json index 2c27e75d2..a5ac33684 100644 --- a/public/instruct/Vicuna 1.0.json +++ b/public/instruct/Vicuna 1.0.json @@ -5,6 +5,7 @@ "stop_sequence": "", "input_sequence": "### Human:", "output_sequence": "### Assistant:", + "last_output_sequence": "", "separator_sequence": "", "wrap": true -} \ No newline at end of file +} diff --git a/public/instruct/Vicuna 1.1.json b/public/instruct/Vicuna 1.1.json index e35d88970..52cf600ac 100644 --- a/public/instruct/Vicuna 1.1.json +++ b/public/instruct/Vicuna 1.1.json @@ -5,6 +5,7 @@ "stop_sequence": "", "input_sequence": "USER: ", "output_sequence": "ASSISTANT: ", + "last_output_sequence": "", "separator_sequence": "", "wrap": false -} \ No newline at end of file +} diff --git a/public/instruct/WizardLM-13B.json b/public/instruct/WizardLM-13B.json index a4fe171cd..3b8b6d7cf 100644 --- a/public/instruct/WizardLM-13B.json +++ b/public/instruct/WizardLM-13B.json @@ -5,6 +5,7 @@ "stop_sequence": "", "input_sequence": "USER: ", "output_sequence": "ASSISTANT: ", + "last_output_sequence": "", "separator_sequence": "", "wrap": true } diff --git a/public/instruct/WizardLM.json b/public/instruct/WizardLM.json index aa83c1a64..c81aef3a2 100644 --- a/public/instruct/WizardLM.json +++ b/public/instruct/WizardLM.json @@ -5,6 +5,7 @@ "stop_sequence": "", "input_sequence": "", "output_sequence": "### Response:", + "last_output_sequence": "", "separator_sequence": "", "wrap": true -} \ No newline at end of file +} diff --git a/public/script.js b/public/script.js index 9c83563a9..422a6449b 100644 --- a/public/script.js +++ b/public/script.js @@ -75,6 +75,7 @@ import { fuzzySearchCharacters, MAX_CONTEXT_DEFAULT, fuzzySearchGroups, + renderStoryString, } from "./scripts/power-user.js"; import { @@ -159,7 +160,6 @@ import { writeSecret } from "./scripts/secrets.js"; import { EventEmitter } from './scripts/eventemitter.js'; -import { context_settings, loadContextTemplatesFromSettings } from "./scripts/context-template.js"; import { markdownExclusionExt } from "./scripts/showdown-exclusion.js"; import { NOTE_MODULE_NAME, metadata_keys, setFloatingPrompt, shouldWIAddPrompt } from "./scripts/authors-note.js"; import { deviceInfo } from "./scripts/RossAscends-mods.js"; @@ -301,7 +301,6 @@ let firstRun = false; const default_ch_mes = "Hello"; let count_view_mes = 0; -let mesStr = ""; let generatedPromtCache = ""; let generation_started = new Date(); let characters = []; @@ -311,8 +310,6 @@ const default_avatar = "img/ai4.png"; export const system_avatar = "img/five.png"; export const comment_avatar = "img/quill.png"; export let CLIENT_VERSION = 'SillyTavern:UNKNOWN:Cohee#1207'; // For Horde header -let is_colab = false; -let is_checked_colab = false; let optionsPopper = Popper.createPopper(document.getElementById('options_button'), document.getElementById('options'), { placement: 'top-start' }); @@ -331,10 +328,6 @@ let is_delete_mode = false; let fav_ch_checked = false; let scrollLock = false; - -//initialize global var for future cropped blobs -let currentCroppedAvatar = ''; - const durationSaveEdit = 1000; const saveSettingsDebounced = debounce(() => saveSettings(), durationSaveEdit); export const saveCharacterDebounced = debounce(() => $("#create_button").trigger('click'), durationSaveEdit); @@ -1095,30 +1088,6 @@ function getBackgroundFromTemplate(bg) { return template; } -async function isColab() { - is_checked_colab = true; - const response = await fetch("/iscolab", { - method: "POST", - headers: getRequestHeaders(), - body: JSON.stringify({ - "": "", - }), - }); - if (response.ok === true) { - const getData = await response.json(); - if (getData.colaburl != false) { - $("#colab_shadow_popup").css("display", "none"); - is_colab = true; - let url = String(getData.colaburl).split("flare.com")[0] + "flare.com"; - url = String(url).split("loca.lt")[0] + "loca.lt"; - $("#api_url_text").val(url); - setTimeout(function () { - $("#api_button").click(); - }, 2000); - } - } -} - async function setBackground(bg) { jQuery.ajax({ @@ -2067,13 +2036,6 @@ function baseChatReplace(value, name1, name2) { return value; } -function appendToStoryString(value, prefix) { - if (value !== undefined && value.length > 0) { - return prefix + value + '\n'; - } - return ''; -} - function isStreamingEnabled() { return ((main_api == 'openai' && oai_settings.stream_openai && oai_settings.chat_completion_source !== chat_completion_sources.SCALE) || (main_api == 'kobold' && kai_settings.streaming_kobold && kai_settings.can_use_streaming) @@ -2479,11 +2441,9 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, if (mesExamples.replace(//gi, '').trim().length === 0) { mesExamples = ''; } - const blockHeading = - main_api === 'openai' ? '' : // OpenAI handler always expects it - power_user.custom_chat_separator ? power_user.custom_chat_separator : - power_user.disable_examples_formatting ? '' : - is_pygmalion ? '' : `This is how ${name2} should talk`; + + // OpenAI handler always expects it + const blockHeading = main_api === 'openai' ? '' : (power_user.context.example_separator || ''); let mesExamplesArray = mesExamples.split(//gi).slice(1).map(block => `${blockHeading}\n${block.trim()}\n`); // First message in fresh 1-on-1 chat reacts to user/character settings changes @@ -2509,17 +2469,15 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, console.log(`Core/all messages: ${coreChat.length}/${chat.length}`); - let storyString = ""; + const storyStringParams = { + description: charDescription, + personality: charPersonality, + scenario: Scenario, + char: name2, + user: name1, + }; - if (is_pygmalion) { - storyString += appendToStoryString(charDescription, power_user.disable_description_formatting ? '' : name2 + "'s Persona: "); - storyString += appendToStoryString(charPersonality, power_user.disable_personality_formatting ? '' : 'Personality: '); - storyString += appendToStoryString(Scenario, power_user.disable_scenario_formatting ? '' : 'Scenario: '); - } else { - storyString += appendToStoryString(charDescription, ''); - storyString += appendToStoryString(charPersonality, power_user.disable_personality_formatting ? '' : name2 + "'s personality: "); - storyString += appendToStoryString(Scenario, power_user.disable_scenario_formatting ? '' : 'Circumstances and context of the dialogue: '); - } + let storyString = renderStoryString(storyStringParams); // kingbri MARK: - Make sure the prompt bias isn't the same as the user bias if ((promptBias && !isUserPromptBias) || power_user.always_force_name2 || is_pygmalion) { @@ -3368,31 +3326,17 @@ function addChatsPreamble(mesSendString) { } function addChatsSeparator(mesSendString) { - if (power_user.custom_chat_separator && power_user.custom_chat_separator.length) { - mesSendString = power_user.custom_chat_separator + '\n' + mesSendString; + if (main_api === 'novel') { + return '***\n' + mesSendString; } - // if chat start formatting is disabled - else if (power_user.disable_start_formatting) { - mesSendString = mesSendString; + else if (power_user.context.chat_start) { + return power_user.context.chat_start + '\n' + mesSendString; } - else if (main_api === 'novel') { - mesSendString = '***\n' + mesSendString; - } - - // add non-pygma dingus - else if (!is_pygmalion) { - mesSendString = '\nThen the roleplay chat between ' + name1 + ' and ' + name2 + ' begins.\n' + mesSendString; - } - - // add pygma else { - mesSendString = '\n' + mesSendString; - //mesSendString = mesSendString; //This edit simply removes the first "" that is prepended to all context prompts + return mesSendString; } - - return mesSendString; } function appendZeroDepthAnchor(force_name2, zeroDepthAnchor, finalPromt) { @@ -5290,9 +5234,6 @@ async function getSettings(type) { // Load character tags loadTagsSettings(settings); - // Load context templates - loadContextTemplatesFromSettings(data, settings); - // Allow subscribers to mutate settings eventSource.emit(event_types.SETTINGS_LOADED_AFTER, settings); @@ -5360,8 +5301,6 @@ async function getSettings(type) { } } - if (!is_checked_colab) isColab(); - eventSource.emit(event_types.SETTINGS_LOADED); } @@ -5396,7 +5335,6 @@ async function saveSettings(type) { horde_settings: horde_settings, power_user: power_user, extension_settings: extension_settings, - context_settings: context_settings, tags: tags, tag_map: tag_map, nai_settings: nai_settings, @@ -8285,7 +8223,6 @@ $(document).ready(function () { const formattedValue = slider.format(value); slider.setValue(value); $(slider.counterId).text(formattedValue); - console.log('saving'); saveSettingsDebounced(); }); }); diff --git a/public/scripts/context-template.js b/public/scripts/context-template.js deleted file mode 100644 index 2452adbf4..000000000 --- a/public/scripts/context-template.js +++ /dev/null @@ -1,214 +0,0 @@ -import { - callPopup, - getRequestHeaders, - saveSettingsDebounced, -} from '../script.js'; -import { debounce } from './utils.js'; - -export let context_templates = []; -export let context_settings = { - selected_template: '', -}; - -const saveTemplateDebounced = debounce((name) => alert('implement me', name), 2000); - -export function loadContextTemplatesFromSettings(data, settings) { - context_templates = data.context || []; - context_settings = Object.assign(context_settings, (settings.context_settings || {})); - - const dropdown = $('#context_template'); - dropdown.empty(); - dropdown.append('') - - for (const template of context_templates) { - const name = template.name; - const option = document.createElement('option'); - option.innerText = name; - option.value = name; - option.selected = context_settings.selected_template == name; - dropdown.append(option); - } -} - -function onContextTemplateChange() { - const value = $(this).find(':selected').val(); - context_settings.selected_template = value; - saveSettingsDebounced(); -} - -function openContextTemplateEditor() { - const template = context_templates.find(x => x.name == context_settings.selected_template); - - if (!template || !context_settings.selected_template) { - toastr.info('No context template selected'); - return; - } - - const editor = $('#context_editor_template .context_editor').clone(); - const injectionsContainer = editor.find('.chat_injections_list'); - editor.find('.template_name').text(template.name); - editor.find('.story_string_template').text(template.storyString).on('input', function () { - const value = $(this).val(); - template.storyString = value; - saveTemplateDebounced(template.name); - }); - editor.find('.chat_injection_add').on('click', function () { - const injection = { id: Date.now(), text: '', depth: 0 }; - template.injections.push(injection); - addChatInjection(injectionsContainer, injection, template); - saveTemplateDebounced(template.name); - }); - - for (const injection of template.injections) { - addChatInjection(injectionsContainer, injection, template); - } - - $('#dialogue_popup').addClass('large_dialogue_popup wide_dialogue_popup'); - callPopup(editor, 'text'); -} - -async function onRenameContextTemplateClick() { - const oldName = context_settings.selected_template; - const newName = await inputTemplateName(); - const template = context_templates.find(x => x.name === oldName); - - if (!template || !newName || oldName === newName) { - return; - } - - await saveContextTemplate(newName); - context_settings.selected_template = newName; - saveSettingsDebounced(); - await deleteContextTemplate(oldName); - toastr.success('Context template renamed', newName); -} - -async function deleteContextTemplate(name) { - const response = await fetch('/delete_context_template', { - method: 'POST', - headers: getRequestHeaders(), - body: JSON.stringify({ name }), - }); - - if (!response.ok) { - throw new Error('Context template not deleted'); - } -} - -async function saveContextTemplate(name) { - const template = context_templates.find(x => x.name === name); - - if (!template) { - throw new Error(`Context template not found: ${name}`); - } - - const response = await fetch('/save_context_template', { - method: 'POST', - headers: getRequestHeaders(), - body: JSON.stringify({ name, template }), - }); - - if (!response.ok) { - throw new Error('Context template not saved'); - } -} - -async function inputTemplateName() { - let name = await callPopup('Enter a template name:', 'input'); - - if (!name) { - return false; - } - - name = DOMPurify.sanitize(name.trim()); - - if (context_templates.findIndex(x => x.name == name) > -1) { - toastr.warning('Template with that name already exists', 'Pick a unique name'); - return false; - } - - return name; -} - -function addChatInjection(container, model, parent) { - const template = $('#chat_injection_template .chat_injection').clone(); - template.attr('id', model.id); - template.find('.chat_injection_text').val(model.text).on('input', function () { - const value = $(this).val(); - model.text = value; - saveTemplateDebounced(parent.name); - }); - template.find('.chat_injection_depth').val(model.depth).on('input', function () { - const value = Math.abs(Number($(this).val())); - model.depth = value; - saveTemplateDebounced(parent.name); - }); - template.find('.chat_injection_remove').on('click', function () { - if (!confirm('Are you sure?')) { - return; - } - - const index = parent.injections.findIndex(x => x == model); - - if (index === -1) { - console.error('Does not compute, injection index was lost'); - return; - } - - parent.injections.splice(index, 1); - template.remove(); - saveTemplateDebounced(parent.name); - }); - container.append(template); -} - -function copyTemplateParameter(event) { - const text = $(event.target).text(); - navigator.clipboard.writeText(text); - toastr.info('Copied!', '', { timeOut: 2000 }); -} - -async function onNewContextTemplateClick() { - const name = await inputTemplateName(); - - if (!name) { - return; - } - - const template = { name: name, injections: [], storyString: '' }; - context_templates.push(template); - const option = document.createElement('option'); - option.innerText = name; - option.value = name; - option.selected = true; - $('#context_template').append(option).val(name).trigger('change'); - saveTemplateDebounced(name); -} - -async function onDeleteContextTemplateClick() { - const template = context_templates.find(x => x.name == context_settings.selected_template); - - if (!template || !context_settings.selected_template) { - toastr.info('No context template selected'); - return; - } - - const confirm = await callPopup('Are you sure?', 'confirm'); - - if (!confirm) { - return; - } - - await deleteContextTemplate(context_settings.selected_template); - $(`#context_template option[value="${context_settings.selected_template}"]`).remove(); - $('#context_template').trigger('change'); -} - -jQuery(() => { - $('#context_template_edit').on('click', openContextTemplateEditor); - $('#context_template').on('change', onContextTemplateChange); - $('#context_template_new').on('click', onNewContextTemplateClick); - $('#context_template_rename').on('click', onRenameContextTemplateClick); - $('#context_template_delete').on('click', onDeleteContextTemplateClick); - $(document).on('pointerup', '.template_parameters_list code', copyTemplateParameter); -}) diff --git a/public/scripts/extensions/backgrounds/index.js b/public/scripts/extensions/backgrounds/index.js index 440454999..73cdfa688 100644 --- a/public/scripts/extensions/backgrounds/index.js +++ b/public/scripts/extensions/backgrounds/index.js @@ -8,6 +8,11 @@ const MODULE_NAME = 'backgrounds'; const METADATA_KEY = 'custom_background'; const UPDATE_INTERVAL = 1000; +function forceSetBackground(background) { + saveBackgroundMetadata(background); + setCustomBackground(); +} + async function moduleWorker() { if (hasCustomBackground()) { $('#unlock_background').show(); @@ -167,4 +172,5 @@ $(document).ready(function () { registerSlashCommand('lockbg', onLockBackgroundClick, ['bglock'], " – locks a background for the currently selected chat", true, true); registerSlashCommand('unlockbg', onUnlockBackgroundClick, ['bgunlock'], ' – unlocks a background for the currently selected chat', true, true); registerSlashCommand('autobg', autoBackgroundCommand, ['bgauto'], ' – automatically changes the background based on the chat context using the AI request prompt', true, true); + window['forceSetBackground'] = forceSetBackground; }); diff --git a/public/scripts/extensions/stable-diffusion/index.js b/public/scripts/extensions/stable-diffusion/index.js index e6adef5eb..41accbb12 100644 --- a/public/scripts/extensions/stable-diffusion/index.js +++ b/public/scripts/extensions/stable-diffusion/index.js @@ -40,6 +40,7 @@ const generationMode = { NOW: 4, FACE: 5, FREE: 6, + BACKGROUND: 7, } const modeLabels = { @@ -49,6 +50,7 @@ const modeLabels = { [generationMode.SCENARIO]: 'Scenario ("The Whole Story")', [generationMode.NOW]: 'Last Message', [generationMode.RAW_LAST]: 'Raw Last Message', + [generationMode.BACKGROUND]: 'Background', } const triggerWords = { @@ -58,6 +60,7 @@ const triggerWords = { [generationMode.RAW_LAST]: ['raw_last'], [generationMode.NOW]: ['last'], [generationMode.FACE]: ['face'], + [generationMode.BACKGROUND]: ['background'], } const promptTemplates = { @@ -94,6 +97,7 @@ const promptTemplates = { '(location),(character list by gender),(primary action), (relative character position) POV, (character 1's description and actions), (character 2's description and actions)']`, [generationMode.RAW_LAST]: "[Pause your roleplay and provide ONLY the last chat message string back to me verbatim. Do not write anything after the string. Do not roleplay at all in your response. Do not continue the roleplay story.]", + [generationMode.BACKGROUND]: "[Pause your roleplay and provide a detailed description of {{char}}'s surroundings in the form of a comma-delimited list of keywords and phrases. The list must include all of the following items in this order: location, time of day, weather, lighting, and any other relevant details. Do not include descriptions of characters and non-visual qualities such as names, personality, movements, scents, mental traits, or anything which could not be seen in a still photograph. Do not write in full sentences. Prefix your description with the phrase 'background,'. Ignore the rest of the story when crafting this description. Do not roleplay as {{user}} when writing this description, and do not attempt to continue the story.]", } const helpString = [ @@ -105,6 +109,7 @@ const helpString = [ `
  • ${m(j(triggerWords[generationMode.SCENARIO]))} – visual recap of the whole chat scenario
  • `, `
  • ${m(j(triggerWords[generationMode.NOW]))} – visual recap of the last chat message
  • `, `
  • ${m(j(triggerWords[generationMode.RAW_LAST]))} – visual recap of the last chat message with no summary
  • `, + `
  • ${m(j(triggerWords[generationMode.BACKGROUND]))} – generate a background for this chat based on the chat's context
  • `, '', `Anything else would trigger a "free mode" to make SD generate whatever you prompted.
    example: '/sd apple tree' would generate a picture of an apple tree.`, @@ -159,6 +164,13 @@ async function loadSettings() { extension_settings.sd.prompts = promptTemplates; } + // Insert missing templates + for (const [key, value] of Object.entries(promptTemplates)) { + if (extension_settings.sd.prompts[key] === undefined) { + extension_settings.sd.prompts[key] = value; + } + } + if (extension_settings.sd.character_prompts === undefined) { extension_settings.sd.character_prompts = {}; } @@ -554,9 +566,35 @@ async function generatePicture(_, trigger, message, callback) { const context = getContext(); const prevSDHeight = extension_settings.sd.height; - if (generationType == generationMode.FACE) { + const prevSDWidth = extension_settings.sd.width; + const aspectRatio = extension_settings.sd.width / extension_settings.sd.height; + + // Face images are always portrait (pun intended) + if (generationType == generationMode.FACE && aspectRatio >= 1) { // Round to nearest multiple of 64 - extension_settings.sd.height = Math.round(extension_settings.sd.height * 1.5 / 64) * 64; + extension_settings.sd.height = Math.round(extension_settings.sd.width * 1.5 / 64) * 64; + } + + // Background images are always landscape + if (generationType == generationMode.BACKGROUND && aspectRatio <= 1) { + // Round to nearest multiple of 64 + extension_settings.sd.width = Math.round(extension_settings.sd.height * 1.8 / 64) * 64; + const callbackOriginal = callback; + callback = function (prompt, base64Image) { + const imgUrl = `url(${base64Image})`; + if ('forceSetBackground' in window) { + forceSetBackground(imgUrl); + } else { + toastr.info('Background image will not be preserved.', '"Chat backgrounds" extension is disabled.'); + $('#bg_custom').css('background-image', imgUrl); + } + + if (typeof callbackOriginal === 'function') { + callbackOriginal(prompt, base64Image); + } else { + sendMessage(prompt, base64Image); + } + } } try { @@ -566,13 +604,14 @@ async function generatePicture(_, trigger, message, callback) { context.deactivateSendButtons(); hideSwipeButtons(); - await sendGenerationRequest(prompt, callback); + await sendGenerationRequest(generationType, prompt, callback); } catch (err) { console.trace(err); throw new Error('SD prompt text generation failed.') } finally { extension_settings.sd.height = prevSDHeight; + extension_settings.sd.width = prevSDWidth; context.activateSendButtons(); showSwipeButtons(); } @@ -605,16 +644,20 @@ async function generatePrompt(quiet_prompt) { return processReply(reply); } -async function sendGenerationRequest(prompt, callback) { +async function sendGenerationRequest(generationType, prompt, callback) { + const prefix = generationType !== generationMode.BACKGROUND + ? combinePrefixes(extension_settings.sd.prompt_prefix, getCharacterPrefix()) + : extension_settings.sd.prompt_prefix; + if (extension_settings.sd.horde) { - await generateHordeImage(prompt, callback); + await generateHordeImage(prompt, prefix, callback); } else { - await generateExtrasImage(prompt, callback); + await generateExtrasImage(prompt, prefix, callback); } } -async function generateExtrasImage(prompt, callback) { - console.log(extension_settings.sd); +async function generateExtrasImage(prompt, prefix, callback) { + console.debug(extension_settings.sd); const url = new URL(getApiUrl()); url.pathname = '/api/image'; const result = await doExtrasFetch(url, { @@ -627,7 +670,7 @@ async function generateExtrasImage(prompt, callback) { scale: extension_settings.sd.scale, width: extension_settings.sd.width, height: extension_settings.sd.height, - prompt_prefix: combinePrefixes(extension_settings.sd.prompt_prefix, getCharacterPrefix()), + prompt_prefix: prefix, negative_prompt: extension_settings.sd.negative_prompt, restore_faces: !!extension_settings.sd.restore_faces, enable_hr: !!extension_settings.sd.enable_hr, @@ -644,7 +687,7 @@ async function generateExtrasImage(prompt, callback) { } } -async function generateHordeImage(prompt, callback) { +async function generateHordeImage(prompt, prefix, callback) { const result = await fetch('/horde_generateimage', { method: 'POST', headers: getRequestHeaders(), @@ -655,7 +698,7 @@ async function generateHordeImage(prompt, callback) { scale: extension_settings.sd.scale, width: extension_settings.sd.width, height: extension_settings.sd.height, - prompt_prefix: combinePrefixes(extension_settings.sd.prompt_prefix, getCharacterPrefix()), + prompt_prefix: prefix, negative_prompt: extension_settings.sd.negative_prompt, model: extension_settings.sd.model, nsfw: extension_settings.sd.horde_nsfw, @@ -680,6 +723,7 @@ async function sendMessage(prompt, image) { name: context.groupId ? systemUserName : context.name2, is_system: context.groupId ? true : false, is_user: false, + is_system: true, is_name: true, send_date: timestampToMoment(Date.now()).format('LL LT'), mes: context.groupId ? p(messageText) : messageText, @@ -715,6 +759,7 @@ function addSDGenButtons() {
  • The Whole Story
  • The Last Message
  • Raw Last Message
  • +
  • Background
  • `; @@ -797,7 +842,7 @@ async function sdMessageButton(e) { message.extra.title = prompt; console.log('Regenerating an image, using existing prompt:', prompt); - await sendGenerationRequest(prompt, saveGeneratedImage); + await sendGenerationRequest(generationMode.FREE, prompt, saveGeneratedImage); } else { console.log("doing /sd raw last"); @@ -828,36 +873,22 @@ async function sdMessageButton(e) { }; $("#sd_dropdown [id]").on("click", function () { - var id = $(this).attr("id"); - if (id == "sd_you") { - console.log("doing /sd you"); - generatePicture('sd', 'you'); - } + const id = $(this).attr("id"); + const idParamMap = { + "sd_you": "you", + "sd_face": "face", + "sd_me": "me", + "sd_world": "scene", + "sd_last": "last", + "sd_raw_last": "raw_last", + "sd_background": "background" + }; - else if (id == "sd_face") { - console.log("doing /sd face"); - generatePicture('sd', 'face'); + const param = idParamMap[id]; - } - - else if (id == "sd_me") { - console.log("doing /sd me"); - generatePicture('sd', 'me'); - } - - else if (id == "sd_world") { - console.log("doing /sd scene"); - generatePicture('sd', 'scene'); - } - - else if (id == "sd_last") { - console.log("doing /sd last"); - generatePicture('sd', 'last'); - } - - else if (id == "sd_raw_last") { - console.log("doing /sd raw last"); - generatePicture('sd', 'raw_last'); + if (param) { + console.log("doing /sd " + param) + generatePicture('sd', param); } }); diff --git a/public/scripts/extensions/tts/coqui.js b/public/scripts/extensions/tts/coqui.js index ce7ac9ab1..cfaf83fec 100644 --- a/public/scripts/extensions/tts/coqui.js +++ b/public/scripts/extensions/tts/coqui.js @@ -14,6 +14,7 @@ const UPDATE_INTERVAL = 1000; let inApiCall = false; let charactersList = []; // Updated with module worker let coquiApiModels = {}; // Initialized only once +let coquiApiModelsFull = {}; // Initialized only once let coquiLocalModels = []; // Initialized only once let coquiLocalModelsReceived = false; /* @@ -104,7 +105,8 @@ class CoquiTtsProvider { @@ -128,8 +130,7 @@ class CoquiTtsProvider { Model installed on extras server

    - - +