diff --git a/public/scripts/extensions/memory/index.js b/public/scripts/extensions/memory/index.js index be805d379..90a4d5991 100644 --- a/public/scripts/extensions/memory/index.js +++ b/public/scripts/extensions/memory/index.js @@ -1,4 +1,4 @@ -import { getStringHash, debounce, waitUntilCondition } from "../../utils.js"; +import { getStringHash, debounce, waitUntilCondition, extractAllWords } from "../../utils.js"; import { getContext, getApiUrl, extension_settings, doExtrasFetch, modules } from "../../extensions.js"; import { eventSource, event_types, extension_prompt_types, generateQuietPrompt, is_send_press, saveSettingsDebounced, substituteParams } from "../../../script.js"; export { MODULE_NAME }; @@ -12,7 +12,21 @@ let lastMessageHash = null; let lastMessageId = null; let inApiCall = false; -const formatMemoryValue = (value) => value ? `Summary: ${value.trim()}` : ''; +const formatMemoryValue = function (value) { + if (!value) { + return ''; + } + + value = value.trim(); + + if (extension_settings.memory.template) { + let result = extension_settings.memory.template.replace(/{{summary}}/i, value); + return substituteParams(result); + } else { + return `Summary: ${value}`; + } +} + const saveChatDebounced = debounce(() => getContext().saveChat(), 2000); const summary_sources = { @@ -21,6 +35,7 @@ const summary_sources = { }; const defaultPrompt = '[Pause your roleplay. Summarize the most important facts and events that have happened in the chat so far. If a summary already exists in your memory, use that as a base and expand with new facts. Limit the summary to {{words}} words or less. Your response should include nothing but the summary.]'; +const defaultTemplate = '[Summary: {{summary}}]'; const defaultSettings = { minLongMemory: 16, @@ -46,6 +61,9 @@ const defaultSettings = { memoryFrozen: false, source: summary_sources.extras, prompt: defaultPrompt, + template: defaultTemplate, + position: extension_prompt_types.AFTER_SCENARIO, + depth: 2, promptWords: 200, promptMinWords: 25, promptMaxWords: 1000, @@ -54,6 +72,10 @@ const defaultSettings = { promptMinInterval: 1, promptMaxInterval: 100, promptIntervalStep: 1, + promptForceWords: 0, + promptForceWordsStep: 100, + promptMinForceWords: 0, + promptMaxForceWords: 10000, }; function loadSettings() { @@ -61,20 +83,10 @@ function loadSettings() { Object.assign(extension_settings.memory, defaultSettings); } - if (extension_settings.memory.source === undefined) { - extension_settings.memory.source = defaultSettings.source; - } - - if (extension_settings.memory.prompt === undefined) { - extension_settings.memory.prompt = defaultSettings.prompt; - } - - if (extension_settings.memory.promptWords === undefined) { - extension_settings.memory.promptWords = defaultSettings.promptWords; - } - - if (extension_settings.memory.promptInterval === undefined) { - extension_settings.memory.promptInterval = defaultSettings.promptInterval; + for (const key of Object.keys(defaultSettings)) { + if (extension_settings.memory[key] === undefined) { + extension_settings.memory[key] = defaultSettings[key]; + } } $('#summary_source').val(extension_settings.memory.source).trigger('change'); @@ -87,6 +99,10 @@ function loadSettings() { $('#memory_prompt').val(extension_settings.memory.prompt).trigger('input'); $('#memory_prompt_words').val(extension_settings.memory.promptWords).trigger('input'); $('#memory_prompt_interval').val(extension_settings.memory.promptInterval).trigger('input'); + $('#memory_template').val(extension_settings.memory.template).trigger('input'); + $('#memory_depth').val(extension_settings.memory.depth).trigger('input'); + $(`input[name="memory_position"][value="${extension_settings.memory.position}"]`).prop('checked', true).trigger('input'); + $('#memory_prompt_words_force').val(extension_settings.memory.promptForceWords).trigger('input'); } function onSummarySourceChange(event) { @@ -170,6 +186,31 @@ function onMemoryPromptInput() { saveSettingsDebounced(); } +function onMemoryTemplateInput() { + const value = $(this).val(); + extension_settings.memory.template = value; + saveSettingsDebounced(); +} + +function onMemoryDepthInput() { + const value = $(this).val(); + extension_settings.memory.depth = Number(value); + saveSettingsDebounced(); +} + +function onMemoryPositionChange(e) { + const value = e.target.value; + extension_settings.memory.position = value; + saveSettingsDebounced(); +} + +function onMemoryPromptWordsForceInput() { + const value = $(this).val(); + extension_settings.memory.promptForceWords = Number(value); + $('#memory_prompt_words_force_value').text(extension_settings.memory.promptForceWords); + saveSettingsDebounced(); +} + function saveLastValues() { const context = getContext(); lastGroupId = context.groupId; @@ -310,19 +351,30 @@ async function summarizeChatMain(context, force) { } let messagesSinceLastSummary = 0; + let wordsSinceLastSummary = 0; + let conditionSatisfied = false; for (let i = context.chat.length - 1; i >= 0; i--) { if (context.chat[i].extra && context.chat[i].extra.memory) { break; } messagesSinceLastSummary++; + wordsSinceLastSummary += extractAllWords(context.chat[i].mes).length; } - if (messagesSinceLastSummary < extension_settings.memory.promptInterval && !force) { - console.debug(`Not enough messages since last summary (messages: ${messagesSinceLastSummary}, interval: ${extension_settings.memory.promptInterval}`); + if (messagesSinceLastSummary >= extension_settings.memory.promptInterval) { + conditionSatisfied = true; + } + + if (extension_settings.memory.promptForceWords && wordsSinceLastSummary >= extension_settings.memory.promptForceWords) { + conditionSatisfied = true; + } + + if (!conditionSatisfied && !force) { + console.debug(`Summary conditions not satisfied (messages: ${messagesSinceLastSummary}, interval: ${extension_settings.memory.promptInterval}, words: ${wordsSinceLastSummary}, force words: ${extension_settings.memory.promptForceWords})`); return; } - console.log('Summarizing chat, messages since last summary: ' + messagesSinceLastSummary); + console.log('Summarizing chat, messages since last summary: ' + messagesSinceLastSummary, 'words since last summary: ' + wordsSinceLastSummary); const prompt = substituteParams(extension_settings.memory.prompt) .replace(/{{words}}/gi, extension_settings.memory.promptWords); @@ -458,9 +510,11 @@ function onMemoryContentInput() { function setMemoryContext(value, saveToMessage) { const context = getContext(); - context.setExtensionPrompt(MODULE_NAME, formatMemoryValue(value), extension_prompt_types.AFTER_SCENARIO); + context.setExtensionPrompt(MODULE_NAME, formatMemoryValue(value), extension_settings.memory.position, extension_settings.memory.depth); $('#memory_contents').val(value); - console.log('Memory set to: ' + value); + console.log('Summary set to: ' + value); + console.debug('Position: ' + extension_settings.memory.position); + console.debug('Depth: ' + extension_settings.memory.depth); if (saveToMessage && context.chat.length) { const idx = context.chat.length - 2; @@ -496,6 +550,21 @@ jQuery(function () { +