Add advanced vector controls

This commit is contained in:
Cohee 2023-09-09 21:26:04 +03:00
parent 4cf6a1f7da
commit 2fa038f91d
3 changed files with 98 additions and 16 deletions

View File

@ -1,18 +1,21 @@
import { eventSource, event_types, extension_prompt_types, getCurrentChatId, getRequestHeaders, saveSettingsDebounced, setExtensionPrompt } from "../../../script.js"; import { eventSource, event_types, extension_prompt_types, getCurrentChatId, getRequestHeaders, saveSettingsDebounced, setExtensionPrompt, substituteParams } from "../../../script.js";
import { ModuleWorkerWrapper, extension_settings, getContext, renderExtensionTemplate } from "../../extensions.js"; import { ModuleWorkerWrapper, extension_settings, getContext, renderExtensionTemplate } from "../../extensions.js";
import { collapseNewlines } from "../../power-user.js"; import { collapseNewlines, power_user, ui_mode } from "../../power-user.js";
import { debounce, getStringHash as calculateHash } from "../../utils.js"; import { debounce, getStringHash as calculateHash } from "../../utils.js";
const MODULE_NAME = 'vectors'; const MODULE_NAME = 'vectors';
const AMOUNT_TO_LEAVE = 5;
const INSERT_AMOUNT = 3;
const QUERY_TEXT_AMOUNT = 2;
export const EXTENSION_PROMPT_TAG = '3_vectors'; export const EXTENSION_PROMPT_TAG = '3_vectors';
const settings = { const settings = {
enabled: false, enabled: false,
source: 'local', source: 'local',
template: `Past events: {{text}}`,
depth: 2,
position: extension_prompt_types.IN_PROMPT,
protect: 5,
insert: 3,
query: 2,
}; };
const moduleWorker = new ModuleWorkerWrapper(synchronizeChat); const moduleWorker = new ModuleWorkerWrapper(synchronizeChat);
@ -138,8 +141,8 @@ async function rearrangeChat(chat) {
return; return;
} }
if (chat.length < AMOUNT_TO_LEAVE) { if (chat.length < settings.protect) {
console.debug(`Vectors: Not enough messages to rearrange (less than ${AMOUNT_TO_LEAVE})`); console.debug(`Vectors: Not enough messages to rearrange (less than ${settings.protect})`);
return; return;
} }
@ -151,9 +154,9 @@ async function rearrangeChat(chat) {
} }
// Get the most relevant messages, excluding the last few // Get the most relevant messages, excluding the last few
const queryHashes = await queryCollection(chatId, queryText, INSERT_AMOUNT); const queryHashes = await queryCollection(chatId, queryText, settings.insert);
const queriedMessages = []; const queriedMessages = [];
const retainMessages = chat.slice(-AMOUNT_TO_LEAVE); const retainMessages = chat.slice(-settings.protect);
for (const message of chat) { for (const message of chat) {
if (retainMessages.includes(message)) { if (retainMessages.includes(message)) {
@ -181,15 +184,23 @@ async function rearrangeChat(chat) {
} }
// Format queried messages into a single string // Format queried messages into a single string
const queriedText = queriedMessages.map(x => collapseNewlines(`${x.name}: ${x.mes}`).trim()).join('\n\n'); const insertedText = getPromptText(queriedMessages);
console.log('Vectors: relevant past messages found.\n', queriedText); setExtensionPrompt(EXTENSION_PROMPT_TAG, insertedText, settings.position, settings.depth);
const insertedText = `Past events: ${queriedText}`;
setExtensionPrompt(EXTENSION_PROMPT_TAG, insertedText, extension_prompt_types.IN_PROMPT, 0);
} catch (error) { } catch (error) {
console.error('Vectors: Failed to rearrange chat', error); console.error('Vectors: Failed to rearrange chat', error);
} }
} }
/**
* @param {any[]} queriedMessages
* @returns {string}
*/
function getPromptText(queriedMessages) {
const queriedText = queriedMessages.map(x => collapseNewlines(`${x.name}: ${x.mes}`).trim()).join('\n\n');
console.log('Vectors: relevant past messages found.\n', queriedText);
return substituteParams(settings.template.replace(/{{text}}/i, queriedText));
}
window['vectors_rearrangeChat'] = rearrangeChat; window['vectors_rearrangeChat'] = rearrangeChat;
const onChatEvent = debounce(async () => await moduleWorker.update(), 500); const onChatEvent = debounce(async () => await moduleWorker.update(), 500);
@ -209,7 +220,7 @@ function getQueryText(chat) {
i++; i++;
} }
if (i === QUERY_TEXT_AMOUNT) { if (i === settings.query) {
break; break;
} }
} }
@ -327,6 +338,39 @@ jQuery(async () => {
Object.assign(extension_settings.vectors, settings); Object.assign(extension_settings.vectors, settings);
saveSettingsDebounced(); saveSettingsDebounced();
}); });
$('#vectors_template').val(settings.template).on('input', () => {
settings.template = String($('#vectors_template').val());
Object.assign(extension_settings.vectors, settings);
saveSettingsDebounced();
});
$('#vectors_depth').val(settings.depth).on('input', () => {
settings.depth = Number($('#vectors_depth').val());
Object.assign(extension_settings.vectors, settings);
saveSettingsDebounced();
});
$('#vectors_protect').val(settings.protect).on('input', () => {
settings.protect = Number($('#vectors_protect').val());
Object.assign(extension_settings.vectors, settings);
saveSettingsDebounced();
});
$('#vectors_insert').val(settings.insert).on('input', () => {
settings.insert = Number($('#vectors_insert').val());
Object.assign(extension_settings.vectors, settings);
saveSettingsDebounced();
});
$('#vectors_query').val(settings.query).on('input', () => {
settings.query = Number($('#vectors_query').val());
Object.assign(extension_settings.vectors, settings);
saveSettingsDebounced();
});
$(`input[name="vectors_position"][value="${settings.position}"]`).prop('checked', true);
$('input[name="vectors_position"]').on('change', () => {
settings.position = Number($('input[name="vectors_position"]:checked').val());
Object.assign(extension_settings.vectors, settings);
saveSettingsDebounced();
});
$('#vectors_advanced_settings').toggleClass('displayNone', power_user.ui_mode === ui_mode.SIMPLE);
$('#vectors_vectorize_all').on('click', onVectorizeAllClick); $('#vectors_vectorize_all').on('click', onVectorizeAllClick);
eventSource.on(event_types.CHAT_CHANGED, onChatEvent); eventSource.on(event_types.CHAT_CHANGED, onChatEvent);

View File

@ -16,10 +16,47 @@
<option value="local">Local</option> <option value="local">Local</option>
<option value="openai">OpenAI</option> <option value="openai">OpenAI</option>
</select> </select>
<div> <div id="vectors_advanced_settings" data-newbie-hidden>
<label for="vectors_template">
Insertion template:
</label>
<textarea id="vectors_template" class="text_pole textarea_compact" rows="2" placeholder="Use {{text}} macro to specify the position of retrieved text."></textarea>
<label for="vectors_position">Injection position:</label>
<div class="radio_group">
<label>
<input type="radio" name="vectors_position" value="0" />
After Main Prompt / Story String
</label>
<label>
<input type="radio" name="vectors_position" value="1" />
In-chat @ Depth <input id="vectors_depth" class="text_pole widthUnset" type="number" min="0" max="99" />
</label>
</div>
<div class="flex-container">
<div class="flex1" title="Prevents last N messages from being placed out of order.">
<label for="vectors_protect">
<small>Retain#</small>
</label>
<input type="number" id="vectors_protect" class="text_pole widthUnset" min="1" max="99" />
</div>
<div class="flex1" title="How many last messages will be matched for relevance.">
<label for="vectors_query">
<small>Query#</small>
</label>
<input type="number" id="vectors_query" class="text_pole widthUnset" min="1" max="99" />
</div>
<div class="flex1" title="How many past messages to insert as memories.">
<label for="vectors_insert">
<small>Insert#</small>
</label>
<input type="number" id="vectors_insert" class="text_pole widthUnset" min="1" max="99" />
</div>
</div>
</div>
<small>
Old messages are vectorized gradually as you chat. Old messages are vectorized gradually as you chat.
To process all previous messages, click the button below. To process all previous messages, click the button below.
</div> </small>
<div id="vectors_vectorize_all" class="menu_button menu_button_icon"> <div id="vectors_vectorize_all" class="menu_button menu_button_icon">
Vectorize All Vectorize All
</div> </div>

View File

@ -1209,6 +1209,7 @@ input[type="file"] {
.radio_group { .radio_group {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin-top: 5px;
} }
#extension_floating_counter { #extension_floating_counter {