mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge branch 'staging' into smol-tag-improvements
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
<div id="assets_ui">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Download Extensions & Assets</b>
|
||||
<b data-i18n="Download Extensions & Assets">Download Extensions & Assets</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<label for="assets-json-url-field">Assets URL</label>
|
||||
<label for="assets-json-url-field" data-i18n="Assets URL">Assets URL</label>
|
||||
<div class="assets-connect-div">
|
||||
<input id="assets-json-url-field" class="text_pole widthUnset flex1">
|
||||
<i id="assets-connect-button" class="menu_button fa-solid fa-plug-circle-exclamation fa-xl redOverlayGlow"></i>
|
||||
@@ -16,7 +16,7 @@
|
||||
<input id="assets_search" class="text_pole flex1" placeholder="Search" type="search">
|
||||
<div id="assets-characters-button" class="menu_button menu_button_icon">
|
||||
<i class="fa-solid fa-image-portrait"></i>
|
||||
Characters
|
||||
<span data-i18n="Characters">Characters</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline-drawer-content" id="assets_menu">
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { getBase64Async, isTrueBoolean, saveBase64AsFile } from '../../utils.js';
|
||||
import { getContext, getApiUrl, doExtrasFetch, extension_settings, modules, renderExtensionTemplateAsync } from '../../extensions.js';
|
||||
import { callPopup, getRequestHeaders, saveSettingsDebounced, substituteParams } from '../../../script.js';
|
||||
import { callPopup, getRequestHeaders, saveSettingsDebounced, substituteParamsExtended } from '../../../script.js';
|
||||
import { getMessageTimeStamp } from '../../RossAscends-mods.js';
|
||||
import { SECRET_KEYS, secret_state } from '../../secrets.js';
|
||||
import { getMultimodalCaption } from '../shared.js';
|
||||
@@ -95,7 +95,7 @@ async function sendCaptionedMessage(caption, image) {
|
||||
template += ' {{caption}}';
|
||||
}
|
||||
|
||||
let messageText = substituteParams(template).replace(/{{caption}}/i, caption);
|
||||
let messageText = substituteParamsExtended(template, { caption: caption });
|
||||
|
||||
if (extension_settings.caption.refine_mode) {
|
||||
messageText = await callPopup(
|
||||
|
@@ -2,34 +2,34 @@
|
||||
<div class="caption_settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Image Captioning</b>
|
||||
<b data-i18n="Image Captioning">Image Captioning</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<label for="caption_source">Source</label>
|
||||
<label for="caption_source" data-i18n="Source">Source</label>
|
||||
<select id="caption_source" class="text_pole">
|
||||
<option value="local">Local</option>
|
||||
<option value="multimodal">Multimodal (OpenAI / Anthropic / llama / Google)</option>
|
||||
<option value="extras">Extras</option>
|
||||
<option value="horde">Horde</option>
|
||||
<option value="local" data-i18n="Local">Local</option>
|
||||
<option value="multimodal" data-i18n="Multimodal (OpenAI / Anthropic / llama / Google)">Multimodal (OpenAI / Anthropic / llama / Google)</option>
|
||||
<option value="extras" data-i18n="Extras">Extras</option>
|
||||
<option value="horde" data-i18n="Horde">Horde</option>
|
||||
</select>
|
||||
<div id="caption_multimodal_block" class="flex-container wide100p">
|
||||
<div class="flex1 flex-container flexFlowColumn flexNoGap">
|
||||
<label for="caption_multimodal_api">API</label>
|
||||
<label for="caption_multimodal_api" data-i18n="API">API</label>
|
||||
<select id="caption_multimodal_api" class="flex1 text_pole">
|
||||
<option value="anthropic">Anthropic</option>
|
||||
<option value="custom">Custom (OpenAI-compatible)</option>
|
||||
<option value="custom" data-i18n="Custom (OpenAI-compatible)">Custom (OpenAI-compatible)</option>
|
||||
<option value="google">Google MakerSuite</option>
|
||||
<option value="koboldcpp">KoboldCpp</option>
|
||||
<option value="llamacpp">llama.cpp</option>
|
||||
<option value="ollama">Ollama</option>
|
||||
<option value="openai">OpenAI</option>
|
||||
<option value="openrouter">OpenRouter</option>
|
||||
<option value="ooba">Text Generation WebUI (oobabooga)</option>
|
||||
<option value="ooba" data-i18n="Text Generation WebUI (oobabooga)">Text Generation WebUI (oobabooga)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex1 flex-container flexFlowColumn flexNoGap">
|
||||
<label for="caption_multimodal_model">Model</label>
|
||||
<label for="caption_multimodal_model" data-i18n="Model">Model</label>
|
||||
<select id="caption_multimodal_model" class="flex1 text_pole">
|
||||
<option data-type="openai" value="gpt-4-vision-preview">gpt-4-vision-preview</option>
|
||||
<option data-type="openai" value="gpt-4-turbo">gpt-4-turbo</option>
|
||||
@@ -54,36 +54,36 @@
|
||||
<option data-type="openrouter" value="google/gemini-pro-vision">google/gemini-pro-vision</option>
|
||||
<option data-type="openrouter" value="google/gemini-flash-1.5">google/gemini-flash-1.5</option>
|
||||
<option data-type="openrouter" value="liuhaotian/llava-yi-34b">liuhaotian/llava-yi-34b</option>
|
||||
<option data-type="ollama" value="ollama_current">[Currently selected]</option>
|
||||
<option data-type="ollama" value="ollama_current" data-i18n="currently_selected">[Currently selected]</option>
|
||||
<option data-type="ollama" value="bakllava:latest">bakllava:latest</option>
|
||||
<option data-type="ollama" value="llava:latest">llava:latest</option>
|
||||
<option data-type="llamacpp" value="llamacpp_current">[Currently loaded]</option>
|
||||
<option data-type="ooba" value="ooba_current">[Currently loaded]</option>
|
||||
<option data-type="koboldcpp" value="koboldcpp_current">[Currently loaded]</option>
|
||||
<option data-type="custom" value="custom_current">[Currently selected]</option>
|
||||
<option data-type="llamacpp" value="llamacpp_current" data-i18n="currently_loaded">[Currently loaded]</option>
|
||||
<option data-type="ooba" value="ooba_current" data-i18n="currently_loaded">[Currently loaded]</option>
|
||||
<option data-type="koboldcpp" value="koboldcpp_current" data-i18n="currently_loaded">[Currently loaded]</option>
|
||||
<option data-type="custom" value="custom_current" data-i18n="currently_selected">[Currently selected]</option>
|
||||
</select>
|
||||
</div>
|
||||
<label data-type="openai,anthropic,google" class="checkbox_label flexBasis100p" for="caption_allow_reverse_proxy" title="Allow using reverse proxy if defined and valid.">
|
||||
<input id="caption_allow_reverse_proxy" type="checkbox" class="checkbox">
|
||||
Allow reverse proxy
|
||||
<span data-i18n="Allow reverse proxy">Allow reverse proxy</span>
|
||||
</label>
|
||||
<div class="flexBasis100p m-b-1">
|
||||
<small><b>Hint:</b> Set your API keys and endpoints in the 'API Connections' tab first.</small>
|
||||
<small><b data-i18n="Hint:">Hint:</b> <span data-i18n="Set your API keys and endpoints in the 'API Connections' tab first.">Set your API keys and endpoints in the 'API Connections' tab first.</span></small>
|
||||
</div>
|
||||
</div>
|
||||
<div id="caption_prompt_block">
|
||||
<label for="caption_prompt">Caption Prompt</label>
|
||||
<label for="caption_prompt" data-i18n="Caption Prompt">Caption Prompt</label>
|
||||
<textarea id="caption_prompt" class="text_pole" rows="1" placeholder="< Use default >">${PROMPT_DEFAULT}</textarea>
|
||||
<label class="checkbox_label margin-bot-10px" for="caption_prompt_ask" title="Ask for a custom prompt every time an image is captioned.">
|
||||
<input id="caption_prompt_ask" type="checkbox" class="checkbox">
|
||||
Ask every time
|
||||
<span data-i18n="Ask every time">Ask every time</span>
|
||||
</label>
|
||||
</div>
|
||||
<label for="caption_template">Message Template <small>(use <code>{{caption}}</code> macro)</small></label>
|
||||
<label for="caption_template"><span data-i18n="Message Template">Message Template</span> <small><span data-i18n="(use _space">(use </span> <code>{{caption}}</code> <span data-i18n="macro)">macro)</span></small></label>
|
||||
<textarea id="caption_template" class="text_pole" rows="2" placeholder="< Use default >">${TEMPLATE_DEFAULT}</textarea>
|
||||
<label class="checkbox_label margin-bot-10px" for="caption_refine_mode">
|
||||
<input id="caption_refine_mode" type="checkbox" class="checkbox">
|
||||
Edit captions before saving
|
||||
<span data-i18n="Edit captions before saving">Edit captions before saving</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { callPopup, eventSource, event_types, generateQuietPrompt, getRequestHeaders, online_status, saveSettingsDebounced, substituteParams } from '../../../script.js';
|
||||
import { callPopup, eventSource, event_types, generateQuietPrompt, getRequestHeaders, online_status, saveSettingsDebounced, substituteParams, substituteParamsExtended, system_message_types } from '../../../script.js';
|
||||
import { dragElement, isMobile } from '../../RossAscends-mods.js';
|
||||
import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch, renderExtensionTemplateAsync } from '../../extensions.js';
|
||||
import { loadMovingUIState, power_user } from '../../power-user.js';
|
||||
@@ -10,6 +10,7 @@ import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
|
||||
import { SlashCommand } from '../../slash-commands/SlashCommand.js';
|
||||
import { ARGUMENT_TYPE, SlashCommandArgument } from '../../slash-commands/SlashCommandArgument.js';
|
||||
import { isFunctionCallingSupported } from '../../openai.js';
|
||||
import { SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js';
|
||||
export { MODULE_NAME };
|
||||
|
||||
const MODULE_NAME = 'expressions';
|
||||
@@ -87,6 +88,7 @@ function getFallbackExpression() {
|
||||
*/
|
||||
function toggleTalkingHeadCommand(_) {
|
||||
setTalkingHeadState(!extension_settings.expressions.talkinghead);
|
||||
return String(extension_settings.expressions.talkinghead);
|
||||
}
|
||||
|
||||
function isVisualNovelMode() {
|
||||
@@ -914,6 +916,7 @@ async function setSpriteSetCommand(_, folder) {
|
||||
// moduleWorker();
|
||||
const vnMode = isVisualNovelMode();
|
||||
await sendExpressionCall(folder, lastExpression, true, vnMode);
|
||||
return '';
|
||||
}
|
||||
|
||||
async function classifyCommand(_, text) {
|
||||
@@ -935,7 +938,7 @@ async function classifyCommand(_, text) {
|
||||
async function setSpriteSlashCommand(_, spriteId) {
|
||||
if (!spriteId) {
|
||||
console.log('No sprite id provided');
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
|
||||
spriteId = spriteId.trim().toLowerCase();
|
||||
@@ -955,7 +958,7 @@ async function setSpriteSlashCommand(_, spriteId) {
|
||||
|
||||
if (!spriteItem) {
|
||||
console.log('No sprite found for search term ' + spriteId);
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
|
||||
label = spriteItem.label;
|
||||
@@ -963,6 +966,7 @@ async function setSpriteSlashCommand(_, spriteId) {
|
||||
|
||||
const vnMode = isVisualNovelMode();
|
||||
await sendExpressionCall(spriteFolderName, label, true, vnMode);
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1008,8 +1012,7 @@ async function getLlmPrompt(labels) {
|
||||
}
|
||||
|
||||
const labelsString = labels.map(x => `"${x}"`).join(', ');
|
||||
const prompt = substituteParams(String(extension_settings.expressions.llmPrompt))
|
||||
.replace(/{{labels}}/gi, labelsString);
|
||||
const prompt = substituteParamsExtended(String(extension_settings.expressions.llmPrompt), { labels: labelsString });
|
||||
return prompt;
|
||||
}
|
||||
|
||||
@@ -1187,7 +1190,7 @@ function getLastCharacterMessage() {
|
||||
const reversedChat = context.chat.slice().reverse();
|
||||
|
||||
for (let mes of reversedChat) {
|
||||
if (mes.is_user || mes.is_system) {
|
||||
if (mes.is_user || mes.is_system || mes.extra?.type === system_message_types.NARRATOR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1326,10 +1329,18 @@ async function renderFallbackExpressionPicker() {
|
||||
}
|
||||
}
|
||||
|
||||
function getCachedExpressions() {
|
||||
if (!Array.isArray(expressionsList)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [...expressionsList, ...extension_settings.expressions.custom].filter(onlyUnique);
|
||||
}
|
||||
|
||||
async function getExpressionsList() {
|
||||
// Return cached list if available
|
||||
if (Array.isArray(expressionsList)) {
|
||||
return [...expressionsList, ...extension_settings.expressions.custom].filter(onlyUnique);
|
||||
return getCachedExpressions();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2033,17 +2044,23 @@ function migrateSettings() {
|
||||
});
|
||||
eventSource.on(event_types.MOVABLE_PANELS_RESET, updateVisualNovelModeDebounced);
|
||||
eventSource.on(event_types.GROUP_UPDATED, updateVisualNovelModeDebounced);
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'sprite',
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||
name: 'sprite',
|
||||
aliases: ['emote'],
|
||||
callback: setSpriteSlashCommand,
|
||||
unnamedArgumentList: [
|
||||
new SlashCommandArgument(
|
||||
'spriteId', [ARGUMENT_TYPE.STRING], true,
|
||||
),
|
||||
SlashCommandArgument.fromProps({
|
||||
description: 'spriteId',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
isRequired: true,
|
||||
enumProvider: () => getCachedExpressions().map((x) => new SlashCommandEnumValue(x)),
|
||||
}),
|
||||
],
|
||||
helpString: 'Force sets the sprite for the current character.',
|
||||
returns: 'label',
|
||||
}));
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'spriteoverride',
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||
name: 'spriteoverride',
|
||||
aliases: ['costume'],
|
||||
callback: setSpriteSetCommand,
|
||||
unnamedArgumentList: [
|
||||
@@ -2053,8 +2070,9 @@ function migrateSettings() {
|
||||
],
|
||||
helpString: 'Sets an override sprite folder for the current character. If the name starts with a slash or a backslash, selects a sub-folder in the character-named folder. Empty value to reset to default.',
|
||||
}));
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'lastsprite',
|
||||
callback: (_, value) => lastExpression[value.trim()] ?? '',
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||
name: 'lastsprite',
|
||||
callback: (_, value) => lastExpression[String(value).trim()] ?? '',
|
||||
returns: 'sprite',
|
||||
unnamedArgumentList: [
|
||||
new SlashCommandArgument(
|
||||
@@ -2063,12 +2081,15 @@ function migrateSettings() {
|
||||
],
|
||||
helpString: 'Returns the last set sprite / expression for the named character.',
|
||||
}));
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'th',
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||
name: 'th',
|
||||
callback: toggleTalkingHeadCommand,
|
||||
aliases: ['talkinghead'],
|
||||
helpString: 'Character Expressions: toggles <i>Image Type - talkinghead (extras)</i> on/off.',
|
||||
returns: ARGUMENT_TYPE.BOOLEAN,
|
||||
}));
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'classify',
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||
name: 'classify',
|
||||
callback: classifyCommand,
|
||||
unnamedArgumentList: [
|
||||
new SlashCommandArgument(
|
||||
|
@@ -1,65 +1,65 @@
|
||||
<div class="expression_settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Character Expressions</b>
|
||||
<b data-i18n="Character Expressions">Character Expressions</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
|
||||
<div class="inline-drawer-content">
|
||||
<label class="checkbox_label" for="expression_translate" title="Use the selected API from Chat Translation extension settings.">
|
||||
<input id="expression_translate" type="checkbox">
|
||||
<span>Translate text to English before classification</span>
|
||||
<span data-i18n="Translate text to English before classification">Translate text to English before classification</span>
|
||||
</label>
|
||||
<label class="checkbox_label" for="expressions_show_default">
|
||||
<input id="expressions_show_default" type="checkbox">
|
||||
<span>Show default images (emojis) if sprite missing</span>
|
||||
<span data-i18n="Show default images (emojis) if sprite missing">Show default images (emojis) if sprite missing</span>
|
||||
</label>
|
||||
<label id="image_type_block" class="checkbox_label" for="image_type_toggle">
|
||||
<input id="image_type_toggle" type="checkbox">
|
||||
<span>Image Type - talkinghead (extras)</span>
|
||||
<span data-i18n="Image Type - talkinghead (extras)">Image Type - talkinghead (extras)</span>
|
||||
</label>
|
||||
<div class="expression_api_block m-b-1 m-t-1">
|
||||
<label for="expression_api">Classifier API</label>
|
||||
<small>Select the API for classifying expressions.</small>
|
||||
<label for="expression_api" data-i18n="Classifier API">Classifier API</label>
|
||||
<small data-i18n="Select the API for classifying expressions.">Select the API for classifying expressions.</small>
|
||||
<select id="expression_api" class="flex1 margin0" data-i18n="Expression API" placeholder="Expression API">
|
||||
<option value="0">Local</option>
|
||||
<option value="1">Extras</option>
|
||||
<option value="2">LLM</option>
|
||||
<option value="0" data-i18n="Local">Local</option>
|
||||
<option value="1" data-i18n="Extras">Extras</option>
|
||||
<option value="2" data-i18n="LLM">LLM</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="expression_llm_prompt_block m-b-1 m-t-1">
|
||||
<label for="expression_llm_prompt" class="title_restorable">
|
||||
<span>LLM Prompt</span>
|
||||
<span data-i18n="LLM Prompt">LLM Prompt</span>
|
||||
<div id="expression_llm_prompt_restore" title="Restore default value" class="right_menu_button">
|
||||
<i class="fa-solid fa-clock-rotate-left fa-sm"></i>
|
||||
</div>
|
||||
</label>
|
||||
<small>Will be used if the API doesn't support JSON schemas or function calling.</small>
|
||||
<small data-i18n="Will be used if the API doesn't support JSON schemas or function calling.">Will be used if the API doesn't support JSON schemas or function calling.</small>
|
||||
<textarea id="expression_llm_prompt" type="text" class="text_pole textarea_compact" rows="2" placeholder="Use {{labels}} special macro."></textarea>
|
||||
</div>
|
||||
<div class="expression_fallback_block m-b-1 m-t-1">
|
||||
<label for="expression_fallback">Default / Fallback Expression</label>
|
||||
<small>Set the default and fallback expression being used when no matching expression is found.</small>
|
||||
<label for="expression_fallback" data-i18n="Default / Fallback Expression">Default / Fallback Expression</label>
|
||||
<small data-i18n="Set the default and fallback expression being used when no matching expression is found.">Set the default and fallback expression being used when no matching expression is found.</small>
|
||||
<select id="expression_fallback" class="flex1 margin0" data-i18n="Fallback Expression" placeholder="Fallback Expression"></select>
|
||||
</div>
|
||||
<div class="expression_custom_block m-b-1 m-t-1">
|
||||
<label for="expression_custom">Custom Expressions</label>
|
||||
<small>Can be set manually or with an <tt>/emote</tt> slash command.</small>
|
||||
<label for="expression_custom" data-i18n="Custom Expressions">Custom Expressions</label>
|
||||
<small><span data-i18n="Can be set manually or with an _space">Can be set manually or with an </span><tt>/emote</tt><span data-i18n="space_ slash command."> slash command.</span></small>
|
||||
<div class="flex-container">
|
||||
<select id="expression_custom" class="flex1 margin0"><select>
|
||||
<i id="expression_custom_add" class="menu_button fa-solid fa-plus margin0" title="Add"></i>
|
||||
<i id="expression_custom_remove" class="menu_button fa-solid fa-xmark margin0" title="Remove"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div id="no_chat_expressions">
|
||||
<div id="no_chat_expressions" data-i18n="Open a chat to see the character expressions.">
|
||||
Open a chat to see the character expressions.
|
||||
</div>
|
||||
<div id="open_chat_expressions">
|
||||
<div class="offline_mode">
|
||||
<small>You are in offline mode. Click on the image below to set the expression.</small>
|
||||
<small data-i18n="You are in offline mode. Click on the image below to set the expression.">You are in offline mode. Click on the image below to set the expression.</small>
|
||||
</div>
|
||||
<label for="expression_override">Sprite Folder Override</label>
|
||||
<small>Use a forward slash to specify a subfolder. Example: <tt>Bob/formal</tt></small>
|
||||
<label for="expression_override" data-i18n="Sprite Folder Override">Sprite Folder Override</label>
|
||||
<small><span data-i18n="Use a forward slash to specify a subfolder. Example: _space">Use a forward slash to specify a subfolder. Example: </span><tt>Bob/formal</tt></small>
|
||||
<div class="flex-container flexnowrap">
|
||||
<input id="expression_override" type="text" class="text_pole" placeholder="Override folder name" />
|
||||
<input id="expression_override_button" class="menu_button" type="submit" value="Submit" />
|
||||
@@ -67,17 +67,17 @@
|
||||
<div class="expression_buttons flex-container spaceEvenly">
|
||||
<div id="expression_upload_pack_button" class="menu_button">
|
||||
<i class="fa-solid fa-file-zipper"></i>
|
||||
<span>Upload sprite pack (ZIP)</span>
|
||||
<span data-i18n="Upload sprite pack (ZIP)">Upload sprite pack (ZIP)</span>
|
||||
</div>
|
||||
<div id="expression_override_cleanup_button" class="menu_button">
|
||||
<i class="fa-solid fa-trash-can"></i>
|
||||
<span>Remove all image overrides</span>
|
||||
<span data-i18n="Remove all image overrides">Remove all image overrides</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="hint"><b>Hint:</b> <i>Create new folder in the <b>/characters/</b> folder of your user data directory and name it as the name of the character.
|
||||
Put images with expressions there. File names should follow the pattern: <tt>[expression_label].[image_format]</tt></i></p>
|
||||
<p class="hint"><b data-i18n="Hint:">Hint:</b> <i><span data-i18n="Create new folder in the _space">Create new folder in the </span><b>/characters/</b> <span data-i18n="folder of your user data directory and name it as the name of the character.">folder of your user data directory and name it as the name of the character.</span>
|
||||
<span data-i18n="Put images with expressions there. File names should follow the pattern:">Put images with expressions there. File names should follow the pattern: </span><tt data-i18n="expression_label_pattern">[expression_label].[image_format]</tt></i></p>
|
||||
<h3 id="image_list_header">
|
||||
<strong>Sprite set:</strong> <span id="image_list_header_name"></span>
|
||||
<strong data-i18n="Sprite set:">Sprite set:</strong> <span id="image_list_header_name"></span>
|
||||
</h3>
|
||||
<div id="image_list"></div>
|
||||
|
||||
|
@@ -11,7 +11,7 @@ import {
|
||||
generateQuietPrompt,
|
||||
is_send_press,
|
||||
saveSettingsDebounced,
|
||||
substituteParams,
|
||||
substituteParamsExtended,
|
||||
generateRaw,
|
||||
getMaxContextSize,
|
||||
} from '../../../script.js';
|
||||
@@ -43,8 +43,7 @@ const formatMemoryValue = function (value) {
|
||||
value = value.trim();
|
||||
|
||||
if (extension_settings.memory.template) {
|
||||
let result = extension_settings.memory.template.replace(/{{summary}}/i, value);
|
||||
return substituteParams(result);
|
||||
return substituteParamsExtended(extension_settings.memory.template, { summary: value });
|
||||
} else {
|
||||
return `Summary: ${value}`;
|
||||
}
|
||||
@@ -447,7 +446,7 @@ async function summarizeCallback(args, text) {
|
||||
}
|
||||
|
||||
const source = args.source || extension_settings.memory.source;
|
||||
const prompt = substituteParams((resolveVariable(args.prompt) || extension_settings.memory.prompt)?.replace(/{{words}}/gi, extension_settings.memory.promptWords));
|
||||
const prompt = substituteParamsExtended((resolveVariable(args.prompt) || extension_settings.memory.prompt), { words: extension_settings.memory.promptWords });
|
||||
|
||||
try {
|
||||
switch (source) {
|
||||
@@ -534,7 +533,7 @@ async function summarizeChatMain(context, force, skipWIAN) {
|
||||
}
|
||||
|
||||
console.log('Summarizing chat, messages since last summary: ' + messagesSinceLastSummary, 'words since last summary: ' + wordsSinceLastSummary);
|
||||
const prompt = extension_settings.memory.prompt?.replace(/{{words}}/gi, extension_settings.memory.promptWords);
|
||||
const prompt = substituteParamsExtended(extension_settings.memory.prompt, { words: extension_settings.memory.promptWords });
|
||||
|
||||
if (!prompt) {
|
||||
console.debug('Summarization prompt is empty. Skipping summarization.');
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<div class="flex-container alignitemscenter margin0">
|
||||
<b>Summarize</b>
|
||||
<b data-i18n="ext_sum_title">Summarize</b>
|
||||
<i id="summaryExtensionPopoutButton" class="fa-solid fa-window-restore menu_button margin0"></i>
|
||||
</div>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
<textarea id="memory_contents" class="text_pole textarea_compact" rows="6" data-i18n="[placeholder]ext_sum_memory_placeholder" placeholder="Summary will be generated here..."></textarea>
|
||||
<div class="memory_contents_controls">
|
||||
<div id="memory_force_summarize" data-summary-source="main" class="menu_button menu_button_icon" data-i18n="[title]ext_sum_force_tip" title="Trigger a summary update right now." data-i18n="Trigger a summary update right now.">
|
||||
<div id="memory_force_summarize" data-summary-source="main" class="menu_button menu_button_icon" title="Trigger a summary update right now." data-i18n="[title]ext_sum_force_tip">
|
||||
<i class="fa-solid fa-database"></i>
|
||||
<span data-i18n="ext_sum_force_text">Summarize now</span>
|
||||
</div>
|
||||
|
@@ -1,33 +1,33 @@
|
||||
<div id="qr--modalEditor">
|
||||
<div id="qr--main">
|
||||
<h3>Labels and Message</h3>
|
||||
<h3 data-i18n="Labels and Message">Labels and Message</h3>
|
||||
<div class="qr--labels">
|
||||
<label>
|
||||
<span class="qr--labelText">Label</span>
|
||||
<span class="qr--labelText" data-i18n="Label">Label</span>
|
||||
<input type="text" class="text_pole" id="qr--modal-label">
|
||||
</label>
|
||||
<label>
|
||||
<span class="qr--labelText">Title</span>
|
||||
<small class="qr--labelHint">(tooltip, leave empty to show message or /command)</small>
|
||||
<span class="qr--labelText" data-i18n="Title">Title</span>
|
||||
<small class="qr--labelHint" data-i18n="(tooltip, leave empty to show message or /command)">(tooltip, leave empty to show message or /command)</small>
|
||||
<input type="text" class="text_pole" id="qr--modal-title">
|
||||
</label>
|
||||
</div>
|
||||
<div class="qr--modal-messageContainer">
|
||||
<label for="qr--modal-message">
|
||||
<label for="qr--modal-message" data-i18n="Message / Command:">
|
||||
Message / Command:
|
||||
</label>
|
||||
<div class="qr--modal-editorSettings">
|
||||
<label class="checkbox_label">
|
||||
<input type="checkbox" id="qr--modal-wrap">
|
||||
<span>Word wrap</span>
|
||||
<span data-i18n="Word wrap">Word wrap</span>
|
||||
</label>
|
||||
<label class="checkbox_label">
|
||||
<span>Tab size:</span>
|
||||
<span data-i18n="Tab size:">Tab size:</span>
|
||||
<input type="number" min="1" max="9" id="qr--modal-tabSize" class="text_pole">
|
||||
</label>
|
||||
<label class="checkbox_label">
|
||||
<input type="checkbox" id="qr--modal-executeShortcut">
|
||||
<span>Ctrl+Enter to execute</span>
|
||||
<span data-i18n="Ctrl+Enter to execute">Ctrl+Enter to execute</span>
|
||||
</label>
|
||||
<label class="checkbox_label">
|
||||
<input type="checkbox" id="qr--modal-syntax">
|
||||
@@ -44,14 +44,14 @@
|
||||
|
||||
|
||||
<div id="qr--qrOptions">
|
||||
<h3>Context Menu</h3>
|
||||
<h3 data-i18n="Context Menu">Context Menu</h3>
|
||||
<div id="qr--ctxEditor">
|
||||
<template id="qr--ctxItem">
|
||||
<div class="qr--ctxItem" data-order="0">
|
||||
<div class="drag-handle ui-sortable-handle">☰</div>
|
||||
<select class="qr--set"></select>
|
||||
<label class="qr--isChainedLabel checkbox_label" title="When enabled, the current Quick Reply will be sent together with (before) the clicked QR from the context menu.">
|
||||
Chaining:
|
||||
<span data-i18n="Chaining:">Chaining:</span>
|
||||
<input type="checkbox" class="qr--isChained">
|
||||
</label>
|
||||
<div class="qr--delete menu_button menu_button_icon fa-solid fa-trash-can" title="Remove entry"></div>
|
||||
@@ -63,48 +63,48 @@
|
||||
</div>
|
||||
|
||||
|
||||
<h3>Auto-Execute</h3>
|
||||
<h3 data-i18n="Auto-Execute">Auto-Execute</h3>
|
||||
<div class="flex-container flexFlowColumn">
|
||||
<label class="checkbox_label" title="Prevent this quick reply from triggering other auto-executed quick replies while auto-executing (i.e., prevent recursive auto-execution)">
|
||||
<input type="checkbox" id="qr--preventAutoExecute" >
|
||||
<span><i class="fa-solid fa-fw fa-plane-slash"></i> Don't trigger auto-execute</span>
|
||||
<span><i class="fa-solid fa-fw fa-plane-slash"></i><span data-i18n="Don't trigger auto-execute">Don't trigger auto-execute</span></span>
|
||||
</label>
|
||||
<label class="checkbox_label">
|
||||
<input type="checkbox" id="qr--isHidden" >
|
||||
<span><i class="fa-solid fa-fw fa-eye-slash"></i> Invisible (auto-execute only)</span>
|
||||
<span><i class="fa-solid fa-fw fa-eye-slash"></i><span data-i18n="Invisible (auto-execute only)">Invisible (auto-execute only)</span></span>
|
||||
</label>
|
||||
<label class="checkbox_label">
|
||||
<input type="checkbox" id="qr--executeOnStartup" >
|
||||
<span><i class="fa-solid fa-fw fa-rocket"></i> Execute on app startup</span>
|
||||
<span><i class="fa-solid fa-fw fa-rocket"></i><span data-i18n="Execute on startup">Execute on startup</span></span>
|
||||
</label>
|
||||
<label class="checkbox_label">
|
||||
<input type="checkbox" id="qr--executeOnUser" >
|
||||
<span><i class="fa-solid fa-fw fa-user"></i> Execute on user message</span>
|
||||
<span><i class="fa-solid fa-fw fa-user"></i><span data-i18n="Execute on user message">Execute on user message</span></span>
|
||||
</label>
|
||||
<label class="checkbox_label">
|
||||
<input type="checkbox" id="qr--executeOnAi" >
|
||||
<span><i class="fa-solid fa-fw fa-robot"></i> Execute on AI message</span>
|
||||
<span><i class="fa-solid fa-fw fa-robot"></i><span data-i18n="Execute on AI message">Execute on AI message</span></span>
|
||||
</label>
|
||||
<label class="checkbox_label">
|
||||
<input type="checkbox" id="qr--executeOnChatChange" >
|
||||
<span><i class="fa-solid fa-fw fa-message"></i> Execute on opening chat</span>
|
||||
<span><i class="fa-solid fa-fw fa-message"></i><span data-i18n="Execute on chat change">Execute on chat change</span></span>
|
||||
</label>
|
||||
<label class="checkbox_label">
|
||||
<input type="checkbox" id="qr--executeOnGroupMemberDraft">
|
||||
<span><i class="fa-solid fa-fw fa-people-group"></i> Execute before group member message</span>
|
||||
<span><i class="fa-solid fa-fw fa-people-group"></i><span data-i18n="Execute on group member draft">Execute on group member draft</span></span>
|
||||
</label>
|
||||
<div class="flex-container alignItemsBaseline flexFlowColumn flexNoGap" title="Activate this quick reply when a World Info entry with the same Automation ID is triggered.">
|
||||
<small>Automation ID</small>
|
||||
<small data-i18n="Automation ID:">Automation ID</small>
|
||||
<input type="text" id="qr--automationId" class="text_pole flex1" placeholder="( None )">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h3>Testing</h3>
|
||||
<h3 data-i18n="Testing">Testing</h3>
|
||||
<div id="qr--modal-executeButtons">
|
||||
<div id="qr--modal-execute" class="qr--modal-executeButton menu_button" title="Execute the quick reply now">
|
||||
<i class="fa-solid fa-play"></i>
|
||||
Execute
|
||||
<span data-i18n="Execute">Execute</span>
|
||||
</div>
|
||||
<div id="qr--modal-pause" class="qr--modal-executeButton menu_button" title="Pause / continue execution">
|
||||
<span class="qr--modal-executeComboIcon">
|
||||
@@ -119,7 +119,7 @@
|
||||
<div id="qr--modal-executeProgress"></div>
|
||||
<label class="checkbox_label">
|
||||
<input type="checkbox" id="qr--modal-executeHide">
|
||||
<span> Hide editor while executing</span>
|
||||
<span title="Hide editor while executing"> Hide editor while executing</span>
|
||||
</label>
|
||||
<div id="qr--modal-executeErrors"></div>
|
||||
<div id="qr--modal-executeResult"></div>
|
||||
|
@@ -1,22 +1,22 @@
|
||||
<div id="qr--settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<strong>Quick Reply</strong>
|
||||
<strong data-i18n="Quick Reply">Quick Reply</strong>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<label class="flex-container">
|
||||
<input type="checkbox" id="qr--isEnabled"> Enable Quick Replies
|
||||
<input type="checkbox" id="qr--isEnabled"><span data-i18n="Enable Quick Replies">Enable Quick Replies</span>
|
||||
</label>
|
||||
<label class="flex-container">
|
||||
<input type="checkbox" id="qr--isCombined"> Combine buttons from all active sets
|
||||
<input type="checkbox" id="qr--isCombined"><span data-i18n="Combine Quick Replies">Combine Quick Replies</span>
|
||||
</label>
|
||||
|
||||
<hr>
|
||||
|
||||
<div id="qr--global">
|
||||
<div class="qr--head">
|
||||
<div class="qr--title">Global Quick Reply Sets</div>
|
||||
<div class="qr--title" data-i18n="Global Quick Reply Sets">Global Quick Reply Sets</div>
|
||||
<div class="qr--actions">
|
||||
<div class="qr--setListAdd menu_button menu_button_icon fa-solid fa-plus" id="qr--global-setListAdd" title="Add quick reply set"></div>
|
||||
</div>
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
<div id="qr--chat">
|
||||
<div class="qr--head">
|
||||
<div class="qr--title">Chat Quick Reply Sets</div>
|
||||
<div class="qr--title" data-i18n="Chat Quick Reply Sets">Chat Quick Reply Sets</div>
|
||||
<div class="qr--actions">
|
||||
<div class="qr--setListAdd menu_button menu_button_icon fa-solid fa-plus" id="qr--chat-setListAdd" title="Add quick reply set"></div>
|
||||
</div>
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
<div id="qr--editor">
|
||||
<div class="qr--head">
|
||||
<div class="qr--title">Edit Quick Replies</div>
|
||||
<div class="qr--title" data-i18n="Edit Quick Replies">Edit Quick Replies</div>
|
||||
<div class="qr--actions">
|
||||
<select id="qr--set" class="text_pole"></select>
|
||||
<div class="qr--add menu_button menu_button_icon fa-solid fa-plus" id="qr--set-new" title="Create new quick reply set"></div>
|
||||
@@ -52,13 +52,13 @@
|
||||
</div>
|
||||
<div id="qr--set-settings">
|
||||
<label class="flex-container">
|
||||
<input type="checkbox" id="qr--disableSend"> <span>Disable send (insert into input field)</span>
|
||||
<input type="checkbox" id="qr--disableSend"> <span data-i18n="Disable Send (Insert Into Input Field)">Disable send (insert into input field)</span>
|
||||
</label>
|
||||
<label class="flex-container">
|
||||
<input type="checkbox" id="qr--placeBeforeInput"> <span>Place quick reply before input</span>
|
||||
<input type="checkbox" id="qr--placeBeforeInput"> <span data-i18n="Place Quick Reply Before Input">Place quick reply before input</span>
|
||||
</label>
|
||||
<label class="flex-container" id="qr--injectInputContainer">
|
||||
<input type="checkbox" id="qr--injectInput"> <span>Inject user input automatically <small>(if disabled, use <code>{{input}}</code> macro for manual injection)</small></span>
|
||||
<input type="checkbox" id="qr--injectInput"> <span><span data-i18n="Inject user input automatically">Inject user input automatically</span> <small><span data-i18n="(if disabled, use ">(if disabled, use</span><code>{{input}}</code> <span data-i18n="macro for manual injection)">macro for manual injection)</span></small></span>
|
||||
</label>
|
||||
</div>
|
||||
<div id="qr--set-qrList" class="qr--qrList"></div>
|
||||
|
@@ -8,11 +8,11 @@
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<div class="flex-container">
|
||||
<div id="open_regex_editor" class="menu_button menu_button_icon" title="New global regex script">
|
||||
<div id="open_regex_editor" class="menu_button menu_button_icon" data-i18n="[title]ext_regex_new_global_script_desc" title="New global regex script">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
<small data-i18n="ext_regex_new_global_script">+ Global</small>
|
||||
</div>
|
||||
<div id="open_scoped_editor" class="menu_button menu_button_icon" title="New scoped regex script">
|
||||
<div id="open_scoped_editor" class="menu_button menu_button_icon" data-i18n="[title]ext_regex_new_scoped_script_desc" title="New scoped regex script">
|
||||
<i class="fa-solid fa-address-card"></i>
|
||||
<small data-i18n="ext_regex_new_scoped_script">+ Scoped</small>
|
||||
</div>
|
||||
@@ -39,7 +39,7 @@
|
||||
<label id="toggle_scoped_regex" class="checkbox flex-container" for="regex_scoped_toggle">
|
||||
<input type="checkbox" id="regex_scoped_toggle" class="enable_scoped" />
|
||||
<span class="regex-toggle-on fa-solid fa-toggle-on fa-lg" title="Disallow using scoped regex"></span>
|
||||
<span class="regex-toggle-off fa-solid fa-toggle-off fa-lg" title="Allow using scoped regex"></span>
|
||||
<span class="regex-toggle-off fa-solid fa-toggle-off fa-lg" data-i18n="[title]ext_regex_allow_scoped" title="Allow using scoped regex"></span>
|
||||
</label>
|
||||
</div>
|
||||
<small data-i18n="ext_regex_scoped_scripts_desc">
|
||||
|
@@ -17,6 +17,7 @@ import {
|
||||
getCharacterAvatar,
|
||||
formatCharacterAvatar,
|
||||
substituteParams,
|
||||
substituteParamsExtended,
|
||||
} from '../../../script.js';
|
||||
import { getApiUrl, getContext, extension_settings, doExtrasFetch, modules, renderExtensionTemplateAsync, writeExtensionField } from '../../extensions.js';
|
||||
import { selected_group } from '../../group-chats.js';
|
||||
@@ -50,7 +51,15 @@ const sources = {
|
||||
pollinations: 'pollinations',
|
||||
};
|
||||
|
||||
const initiators = {
|
||||
command: 'command',
|
||||
action: 'action',
|
||||
interactive: 'interactive',
|
||||
wand: 'wand',
|
||||
};
|
||||
|
||||
const generationMode = {
|
||||
MESSAGE: -1,
|
||||
CHARACTER: 0,
|
||||
USER: 1,
|
||||
SCENARIO: 2,
|
||||
@@ -62,6 +71,7 @@ const generationMode = {
|
||||
CHARACTER_MULTIMODAL: 8,
|
||||
USER_MULTIMODAL: 9,
|
||||
FACE_MULTIMODAL: 10,
|
||||
FREE_EXTENDED: 11,
|
||||
};
|
||||
|
||||
const multimodalMap = {
|
||||
@@ -71,6 +81,7 @@ const multimodalMap = {
|
||||
};
|
||||
|
||||
const modeLabels = {
|
||||
[generationMode.MESSAGE]: 'Chat Message Template',
|
||||
[generationMode.CHARACTER]: 'Character ("Yourself")',
|
||||
[generationMode.FACE]: 'Portrait ("Your Face")',
|
||||
[generationMode.USER]: 'User ("Me")',
|
||||
@@ -81,6 +92,7 @@ const modeLabels = {
|
||||
[generationMode.CHARACTER_MULTIMODAL]: 'Character (Multimodal Mode)',
|
||||
[generationMode.FACE_MULTIMODAL]: 'Portrait (Multimodal Mode)',
|
||||
[generationMode.USER_MULTIMODAL]: 'User (Multimodal Mode)',
|
||||
[generationMode.FREE_EXTENDED]: 'Free Mode (LLM-Extended)',
|
||||
};
|
||||
|
||||
const triggerWords = {
|
||||
@@ -94,7 +106,7 @@ const triggerWords = {
|
||||
};
|
||||
|
||||
const messageTrigger = {
|
||||
activationRegex: /\b(send|mail|imagine|generate|make|create|draw|paint|render)\b.{0,10}\b(pic|picture|image|drawing|painting|photo|photograph)\b(?:\s+of)?(?:\s+(?:a|an|the|this|that|those)?)?(.+)/i,
|
||||
activationRegex: /\b(send|mail|imagine|generate|make|create|draw|paint|render|show)\b.{0,10}\b(pic|picture|image|drawing|painting|photo|photograph)\b(?:\s+of)?(?:\s+(?:a|an|the|this|that|those|your)?)?(.+)/i,
|
||||
specialCases: {
|
||||
[generationMode.CHARACTER]: ['you', 'yourself'],
|
||||
[generationMode.USER]: ['me', 'myself'],
|
||||
@@ -106,6 +118,8 @@ const messageTrigger = {
|
||||
};
|
||||
|
||||
const promptTemplates = {
|
||||
// Not really a prompt template, rather an outcome message template
|
||||
[generationMode.MESSAGE]: '[{{char}} sends a picture that contains: {{prompt}}].',
|
||||
/*OLD: [generationMode.CHARACTER]: "Pause your roleplay and provide comma-delimited list of phrases and keywords which describe {{char}}'s physical appearance and clothing. Ignore {{char}}'s personality traits, and chat history when crafting this description. End your response once the comma-delimited list is complete. Do not roleplay when writing this description, and do not attempt to continue the story.", */
|
||||
[generationMode.CHARACTER]: '[In the next response I want you to provide only a detailed comma-delimited list of keywords and phrases which describe {{char}}. The list must include all of the following items in this order: name, species and race, gender, age, clothing, occupation, physical features and appearances. Do not include descriptions of non-visual qualities such as 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 \'full body portrait,\']',
|
||||
//face-specific prompt
|
||||
@@ -143,6 +157,7 @@ const promptTemplates = {
|
||||
[generationMode.FACE_MULTIMODAL]: 'Provide an exhaustive comma-separated list of tags describing the appearance of the character on this image in great detail. Start with "close-up portrait".',
|
||||
[generationMode.CHARACTER_MULTIMODAL]: 'Provide an exhaustive comma-separated list of tags describing the appearance of the character on this image in great detail. Start with "full body portrait".',
|
||||
[generationMode.USER_MULTIMODAL]: 'Provide an exhaustive comma-separated list of tags describing the appearance of the character on this image in great detail. Start with "full body portrait".',
|
||||
[generationMode.FREE_EXTENDED]: 'Pause your roleplay and provide an exhaustive comma-separated list of tags describing the appearance of "{0}" in great detail. Start with {{charPrefix}} (sic) if the subject is associated with {{char}}.',
|
||||
};
|
||||
|
||||
const defaultPrefix = 'best quality, absurdres, aesthetic,';
|
||||
@@ -204,6 +219,7 @@ const defaultSettings = {
|
||||
interactive_mode: false,
|
||||
multimodal_captioning: false,
|
||||
snap: false,
|
||||
free_extend: false,
|
||||
|
||||
prompts: promptTemplates,
|
||||
|
||||
@@ -261,6 +277,11 @@ const defaultSettings = {
|
||||
// Pollinations settings
|
||||
pollinations_enhance: false,
|
||||
pollinations_refine: false,
|
||||
|
||||
// Visibility toggles
|
||||
wand_visible: false,
|
||||
command_visible: false,
|
||||
interactive_visible: false,
|
||||
};
|
||||
|
||||
const writePromptFieldsDebounced = debounce(writePromptFields, debounce_timeout.relaxed);
|
||||
@@ -312,7 +333,7 @@ function processTriggers(chat, _, abort) {
|
||||
}
|
||||
|
||||
abort(true);
|
||||
setTimeout(() => generatePicture('sd', subject, message), 1);
|
||||
setTimeout(() => generatePicture(initiators.interactive, {}, subject, message), 1);
|
||||
} catch {
|
||||
console.log('SD: Failed to process triggers.');
|
||||
return;
|
||||
@@ -419,6 +440,10 @@ async function loadSettings() {
|
||||
$('#sd_clip_skip').val(extension_settings.sd.clip_skip);
|
||||
$('#sd_clip_skip_value').text(extension_settings.sd.clip_skip);
|
||||
$('#sd_seed').val(extension_settings.sd.seed);
|
||||
$('#sd_free_extend').prop('checked', extension_settings.sd.free_extend);
|
||||
$('#sd_wand_visible').prop('checked', extension_settings.sd.wand_visible);
|
||||
$('#sd_command_visible').prop('checked', extension_settings.sd.command_visible);
|
||||
$('#sd_interactive_visible').prop('checked', extension_settings.sd.interactive_visible);
|
||||
|
||||
for (const style of extension_settings.sd.styles) {
|
||||
const option = document.createElement('option');
|
||||
@@ -476,7 +501,7 @@ async function loadSettingOptions() {
|
||||
function addPromptTemplates() {
|
||||
$('#sd_prompt_templates').empty();
|
||||
|
||||
for (const [name, prompt] of Object.entries(extension_settings.sd.prompts)) {
|
||||
for (const [name, prompt] of Object.entries(extension_settings.sd.prompts).sort((a, b) => Number(a[0]) - Number(b[0]))) {
|
||||
const label = $('<label></label>')
|
||||
.text(modeLabels[name])
|
||||
.attr('for', `sd_prompt_${name}`)
|
||||
@@ -683,6 +708,18 @@ function onChatChanged() {
|
||||
$('#sd_character_prompt').val(characterPrompt);
|
||||
$('#sd_character_negative_prompt').val(negativePrompt);
|
||||
$('#sd_character_prompt_share').prop('checked', hasSharedData);
|
||||
adjustElementScrollHeight();
|
||||
}
|
||||
|
||||
function adjustElementScrollHeight(){
|
||||
if (!$('.sd_settings').is(':visible')) {
|
||||
return;
|
||||
}
|
||||
|
||||
resetScrollHeight($('#sd_prompt_prefix'));
|
||||
resetScrollHeight($('#sd_negative_prompt'));
|
||||
resetScrollHeight($('#sd_character_prompt'));
|
||||
resetScrollHeight($('#sd_character_negative_prompt'));
|
||||
}
|
||||
|
||||
function onCharacterPromptInput() {
|
||||
@@ -762,6 +799,26 @@ function onRefineModeInput() {
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onFreeExtendInput() {
|
||||
extension_settings.sd.free_extend = !!$('#sd_free_extend').prop('checked');
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onWandVisibleInput() {
|
||||
extension_settings.sd.wand_visible = !!$('#sd_wand_visible').prop('checked');
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onCommandVisibleInput() {
|
||||
extension_settings.sd.command_visible = !!$('#sd_command_visible').prop('checked');
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onInteractiveVisibleInput() {
|
||||
extension_settings.sd.interactive_visible = !!$('#sd_interactive_visible').prop('checked');
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onClipSkipInput() {
|
||||
extension_settings.sd.clip_skip = Number($('#sd_clip_skip').val());
|
||||
$('#sd_clip_skip_value').text(extension_settings.sd.clip_skip);
|
||||
@@ -1026,6 +1083,7 @@ async function changeComfyWorkflow(_, name) {
|
||||
} else {
|
||||
toastr.error(`ComfyUI Workflow "${name}" does not exist.`);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
async function validateAutoUrl() {
|
||||
@@ -2016,6 +2074,10 @@ function getGenerationType(prompt) {
|
||||
mode = multimodalMap[mode];
|
||||
}
|
||||
|
||||
if (mode === generationMode.FREE && extension_settings.sd.free_extend) {
|
||||
mode = generationMode.FREE_EXTENDED;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
@@ -2080,7 +2142,16 @@ function getRawLastMessage() {
|
||||
return `((${processReply(lastMessage.mes)})), (${processReply(character.scenario)}:0.7), (${processReply(character.description)}:0.5)`;
|
||||
}
|
||||
|
||||
async function generatePicture(args, trigger, message, callback) {
|
||||
/**
|
||||
* Generates an image based on the given trigger word.
|
||||
* @param {string} initiator The initiator of the image generation
|
||||
* @param {Record<string, object>} args Command arguments
|
||||
* @param {string} trigger Subject trigger word
|
||||
* @param {string} [message] Chat message
|
||||
* @param {function} [callback] Callback function
|
||||
* @returns {Promise<string>} Image path
|
||||
*/
|
||||
async function generatePicture(initiator, args, trigger, message, callback) {
|
||||
if (!trigger || trigger.trim().length === 0) {
|
||||
console.log('Trigger word empty, aborting');
|
||||
return;
|
||||
@@ -2111,9 +2182,9 @@ async function generatePicture(args, trigger, message, callback) {
|
||||
eventSource.emit(event_types.FORCE_SET_BACKGROUND, { url: imgUrl, path: imagePath });
|
||||
|
||||
if (typeof callbackOriginal === 'function') {
|
||||
callbackOriginal(prompt, imagePath, generationType, negativePromptPrefix);
|
||||
callbackOriginal(prompt, imagePath, generationType, negativePromptPrefix, initiator);
|
||||
} else {
|
||||
sendMessage(prompt, imagePath, generationType, negativePromptPrefix);
|
||||
sendMessage(prompt, imagePath, generationType, negativePromptPrefix, initiator);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -2122,18 +2193,19 @@ async function generatePicture(args, trigger, message, callback) {
|
||||
callback = () => { };
|
||||
}
|
||||
|
||||
const negativePromptPrefix = resolveVariable(args?.negative) || '';
|
||||
const dimensions = setTypeSpecificDimensions(generationType);
|
||||
let negativePromptPrefix = resolveVariable(args?.negative) || '';
|
||||
let imagePath = '';
|
||||
|
||||
try {
|
||||
const prompt = await getPrompt(generationType, message, trigger, quietPrompt);
|
||||
const combineNegatives = (prefix) => { negativePromptPrefix = combinePrefixes(negativePromptPrefix, prefix); };
|
||||
const prompt = await getPrompt(generationType, message, trigger, quietPrompt, combineNegatives);
|
||||
console.log('Processed image prompt:', prompt);
|
||||
|
||||
context.deactivateSendButtons();
|
||||
hideSwipeButtons();
|
||||
|
||||
imagePath = await sendGenerationRequest(generationType, prompt, negativePromptPrefix, characterName, callback);
|
||||
imagePath = await sendGenerationRequest(generationType, prompt, negativePromptPrefix, characterName, callback, initiator);
|
||||
} catch (err) {
|
||||
console.trace(err);
|
||||
throw new Error('SD prompt text generation failed.');
|
||||
@@ -2196,7 +2268,16 @@ function restoreOriginalDimensions(savedParams) {
|
||||
extension_settings.sd.width = savedParams.width;
|
||||
}
|
||||
|
||||
async function getPrompt(generationType, message, trigger, quietPrompt) {
|
||||
/**
|
||||
* Generates a prompt for image generation.
|
||||
* @param {number} generationType The type of image generation to perform.
|
||||
* @param {string} message A message text to use for the image generation.
|
||||
* @param {string} trigger A trigger string to use for the image generation.
|
||||
* @param {string} quietPrompt A quiet prompt to use for the image generation.
|
||||
* @param {function} combineNegatives A function that combines the negative prompt with other prompts.
|
||||
* @returns {Promise<string>} - A promise that resolves when the prompt generation completes.
|
||||
*/
|
||||
async function getPrompt(generationType, message, trigger, quietPrompt, combineNegatives) {
|
||||
let prompt;
|
||||
|
||||
switch (generationType) {
|
||||
@@ -2204,7 +2285,7 @@ async function getPrompt(generationType, message, trigger, quietPrompt) {
|
||||
prompt = message || getRawLastMessage();
|
||||
break;
|
||||
case generationMode.FREE:
|
||||
prompt = generateFreeModePrompt(trigger.trim());
|
||||
prompt = generateFreeModePrompt(trigger.trim(), combineNegatives);
|
||||
break;
|
||||
case generationMode.FACE_MULTIMODAL:
|
||||
case generationMode.CHARACTER_MULTIMODAL:
|
||||
@@ -2216,6 +2297,10 @@ async function getPrompt(generationType, message, trigger, quietPrompt) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (generationType === generationMode.FREE_EXTENDED) {
|
||||
prompt = generateFreeModePrompt(prompt.trim(), combineNegatives);
|
||||
}
|
||||
|
||||
if (generationType !== generationMode.FREE) {
|
||||
prompt = await refinePrompt(prompt, true);
|
||||
}
|
||||
@@ -2226,9 +2311,10 @@ async function getPrompt(generationType, message, trigger, quietPrompt) {
|
||||
/**
|
||||
* Generates a free prompt with a character-specific prompt prefix support.
|
||||
* @param {string} trigger - The prompt to use for the image generation.
|
||||
* @param {function} combineNegatives - A function that combines the negative prompt with other prompts.
|
||||
* @returns {string}
|
||||
*/
|
||||
function generateFreeModePrompt(trigger) {
|
||||
function generateFreeModePrompt(trigger, combineNegatives) {
|
||||
return trigger
|
||||
.replace(/(?:^char(\s|,)|\{\{charPrefix\}\})/gi, (_, suffix) => {
|
||||
const getLastCharacterKey = () => {
|
||||
@@ -2249,7 +2335,9 @@ function generateFreeModePrompt(trigger) {
|
||||
|
||||
const key = getLastCharacterKey();
|
||||
const value = (extension_settings.sd.character_prompts[key] || '').trim();
|
||||
return value ? value + (suffix || '') : '';
|
||||
const negativeValue = (extension_settings.sd.character_negative_prompts[key] || '').trim();
|
||||
typeof combineNegatives === 'function' && negativeValue ? combineNegatives(negativeValue) : void 0;
|
||||
return value ? combinePrefixes(value, (suffix || '')) : '';
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2335,12 +2423,13 @@ async function generatePrompt(quietPrompt) {
|
||||
* @param {number} generationType Type of image generation
|
||||
* @param {string} prompt Prompt to be used for image generation
|
||||
* @param {string} additionalNegativePrefix Additional negative prompt to be used for image generation
|
||||
* @param {string} [characterName] Name of the character
|
||||
* @param {function} [callback] Callback function to be called after image generation
|
||||
* @param {string} characterName Name of the character
|
||||
* @param {function} callback Callback function to be called after image generation
|
||||
* @param {string} initiator The initiator of the image generation
|
||||
* @returns
|
||||
*/
|
||||
async function sendGenerationRequest(generationType, prompt, additionalNegativePrefix, characterName = null, callback) {
|
||||
const noCharPrefix = [generationMode.FREE, generationMode.BACKGROUND, generationMode.USER, generationMode.USER_MULTIMODAL];
|
||||
async function sendGenerationRequest(generationType, prompt, additionalNegativePrefix, characterName, callback, initiator) {
|
||||
const noCharPrefix = [generationMode.FREE, generationMode.BACKGROUND, generationMode.USER, generationMode.USER_MULTIMODAL, generationMode.FREE_EXTENDED];
|
||||
const prefix = noCharPrefix.includes(generationType)
|
||||
? extension_settings.sd.prompt_prefix
|
||||
: combinePrefixes(extension_settings.sd.prompt_prefix, getCharacterPrefix());
|
||||
@@ -2405,7 +2494,7 @@ async function sendGenerationRequest(generationType, prompt, additionalNegativeP
|
||||
|
||||
const filename = `${characterName}_${humanizedDateTime()}`;
|
||||
const base64Image = await saveBase64AsFile(result.data, characterName, filename, result.format);
|
||||
callback ? callback(prompt, base64Image, generationType, additionalNegativePrefix) : sendMessage(prompt, base64Image, generationType, additionalNegativePrefix);
|
||||
callback ? callback(prompt, base64Image, generationType, additionalNegativePrefix, initiator) : sendMessage(prompt, base64Image, generationType, additionalNegativePrefix, initiator);
|
||||
return base64Image;
|
||||
}
|
||||
|
||||
@@ -3009,15 +3098,17 @@ async function onComfyDeleteWorkflowClick() {
|
||||
* @param {string} image Base64 encoded image
|
||||
* @param {number} generationType Generation type of the image
|
||||
* @param {string} additionalNegativePrefix Additional negative prompt used for the image generation
|
||||
* @param {string} initiator The initiator of the image generation
|
||||
*/
|
||||
async function sendMessage(prompt, image, generationType, additionalNegativePrefix) {
|
||||
async function sendMessage(prompt, image, generationType, additionalNegativePrefix, initiator) {
|
||||
const context = getContext();
|
||||
const name = context.groupId ? systemUserName : context.name2;
|
||||
const messageText = `[${name} sends a picture that contains: ${prompt}]`;
|
||||
const template = extension_settings.sd.prompts[generationMode.MESSAGE] || '{{prompt}}';
|
||||
const messageText = substituteParamsExtended(template, { char: name, prompt: prompt });
|
||||
const message = {
|
||||
name: name,
|
||||
is_user: false,
|
||||
is_system: true,
|
||||
is_system: !getVisibilityByInitiator(initiator),
|
||||
send_date: getMessageTimeStamp(),
|
||||
mes: messageText,
|
||||
extra: {
|
||||
@@ -3033,6 +3124,24 @@ async function sendMessage(prompt, image, generationType, additionalNegativePref
|
||||
context.saveChat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the visibility of the resulting message based on the initiator.
|
||||
* @param {string} initiator Generation initiator
|
||||
* @returns {boolean} Is resulting message visible
|
||||
*/
|
||||
function getVisibilityByInitiator(initiator) {
|
||||
switch (initiator) {
|
||||
case initiators.interactive:
|
||||
return !!extension_settings.sd.interactive_visible;
|
||||
case initiators.wand:
|
||||
return !!extension_settings.sd.wand_visible;
|
||||
case initiators.command:
|
||||
return !!extension_settings.sd.command_visible;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function addSDGenButtons() {
|
||||
const buttonHtml = await renderExtensionTemplateAsync('stable-diffusion', 'button');
|
||||
const dropdownHtml = await renderExtensionTemplateAsync('stable-diffusion', 'dropdown');
|
||||
@@ -3082,7 +3191,7 @@ async function addSDGenButtons() {
|
||||
|
||||
if (param) {
|
||||
console.log('doing /sd ' + param);
|
||||
generatePicture('sd', param);
|
||||
generatePicture(initiators.wand, {}, param);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -3159,11 +3268,11 @@ async function sdMessageButton(e) {
|
||||
const generationType = message?.extra?.generationType ?? generationMode.FREE;
|
||||
console.log('Regenerating an image, using existing prompt:', prompt);
|
||||
dimensions = setTypeSpecificDimensions(generationType);
|
||||
await sendGenerationRequest(generationType, prompt, negative, characterFileName, saveGeneratedImage);
|
||||
await sendGenerationRequest(generationType, prompt, negative, characterFileName, saveGeneratedImage, initiators.action);
|
||||
}
|
||||
else {
|
||||
console.log('doing /sd raw last');
|
||||
await generatePicture('sd', 'raw_last', messageText, saveGeneratedImage);
|
||||
await generatePicture(initiators.action, {}, 'raw_last', messageText, saveGeneratedImage);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
@@ -3226,7 +3335,7 @@ jQuery(async () => {
|
||||
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||
name: 'imagine',
|
||||
callback: generatePicture,
|
||||
callback: (args, trigger) => generatePicture(initiators.command, args, String(trigger)),
|
||||
aliases: ['sd', 'img', 'image'],
|
||||
namedArgumentList: [
|
||||
new SlashCommandNamedArgument(
|
||||
@@ -3326,6 +3435,10 @@ jQuery(async () => {
|
||||
$('#sd_clip_skip').on('input', onClipSkipInput);
|
||||
$('#sd_seed').on('input', onSeedInput);
|
||||
$('#sd_character_prompt_share').on('input', onCharacterPromptShareInput);
|
||||
$('#sd_free_extend').on('input', onFreeExtendInput);
|
||||
$('#sd_wand_visible').on('input', onWandVisibleInput);
|
||||
$('#sd_command_visible').on('input', onCommandVisibleInput);
|
||||
$('#sd_interactive_visible').on('input', onInteractiveVisibleInput);
|
||||
|
||||
$('.sd_settings .inline-drawer-toggle').on('click', function () {
|
||||
initScrollHeight($('#sd_prompt_prefix'));
|
||||
|
@@ -22,6 +22,11 @@
|
||||
<input id="sd_multimodal_captioning" type="checkbox" />
|
||||
<span data-i18n="sd_multimodal_captioning_txt">Use multimodal captioning for portraits</span>
|
||||
</label>
|
||||
<label for="sd_free_extend" class="checkbox_label" data-i18n="[title]sd_free_extend" title="Automatically extend free mode subject prompts (not portraits or backgrounds) using a currently selected LLM.">
|
||||
<input id="sd_free_extend" type="checkbox" />
|
||||
<span data-i18n="sd_free_extend_txt">Extend free mode prompts</span>
|
||||
<small data-i18n="sd_free_extend_small">(interactive/commands)</small>
|
||||
</label>
|
||||
<label for="sd_expand" class="checkbox_label" data-i18n="[title]sd_expand" title="Automatically extend prompts using text generation model">
|
||||
<input id="sd_expand" type="checkbox" />
|
||||
<span data-i18n="sd_expand_txt">Auto-enhance prompts</span>
|
||||
@@ -279,16 +284,16 @@
|
||||
</div>
|
||||
</div>
|
||||
<label for="sd_prompt_prefix" data-i18n="Common prompt prefix">Common prompt prefix</label>
|
||||
<textarea id="sd_prompt_prefix" class="text_pole textarea_compact" rows="3" data-i18n="[placeholder]sd_prompt_prefix_placeholder" placeholder="Use {prompt} to specify where the generated prompt will be inserted"></textarea>
|
||||
<textarea id="sd_prompt_prefix" class="text_pole textarea_compact" data-i18n="[placeholder]sd_prompt_prefix_placeholder" placeholder="Use {prompt} to specify where the generated prompt will be inserted"></textarea>
|
||||
<label for="sd_negative_prompt" data-i18n="Negative common prompt prefix">Negative common prompt prefix</label>
|
||||
<textarea id="sd_negative_prompt" class="text_pole textarea_compact" rows="3"></textarea>
|
||||
<textarea id="sd_negative_prompt" class="text_pole textarea_compact"></textarea>
|
||||
<div id="sd_character_prompt_block">
|
||||
<label for="sd_character_prompt" data-i18n="Character-specific prompt prefix">Character-specific prompt prefix</label>
|
||||
<small data-i18n="Won't be used in groups.">Won't be used in groups.</small>
|
||||
<textarea id="sd_character_prompt" class="text_pole textarea_compact" rows="3" data-i18n="[placeholder]sd_character_prompt_placeholder" placeholder="Any characteristics that describe the currently selected character. Will be added after a common prompt prefix. Example: female, green eyes, brown hair, pink shirt"></textarea>
|
||||
<textarea id="sd_character_prompt" class="text_pole textarea_compact" data-i18n="[placeholder]sd_character_prompt_placeholder" placeholder="Any characteristics that describe the currently selected character. Will be added after a common prompt prefix. Example: female, green eyes, brown hair, pink shirt"></textarea>
|
||||
<label for="sd_character_negative_prompt" data-i18n="Character-specific negative prompt prefix">Character-specific negative prompt prefix</label>
|
||||
<small data-i18n="Won't be used in groups.">Won't be used in groups.</small>
|
||||
<textarea id="sd_character_negative_prompt" class="text_pole textarea_compact" rows="3" data-i18n="[placeholder]sd_character_negative_prompt_placeholder" placeholder="Any characteristics that should not appear for the selected character. Will be added after a negative common prompt prefix. Example: jewellery, shoes, glasses"></textarea>
|
||||
<textarea id="sd_character_negative_prompt" class="text_pole textarea_compact" data-i18n="[placeholder]sd_character_negative_prompt_placeholder" placeholder="Any characteristics that should not appear for the selected character. Will be added after a negative common prompt prefix. Example: jewellery, shoes, glasses"></textarea>
|
||||
<label for="sd_character_prompt_share" class="checkbox_label flexWrap marginTop5">
|
||||
<input id="sd_character_prompt_share" type="checkbox" />
|
||||
<span data-i18n="Shareable">
|
||||
@@ -299,6 +304,36 @@
|
||||
</small>
|
||||
</label>
|
||||
</div>
|
||||
<hr>
|
||||
<h4 data-i18n="Chat Message Visibility (by source)">
|
||||
Chat Message Visibility (by source)
|
||||
</h4>
|
||||
<small data-i18n="Uncheck to hide the extension's messages in chat prompts.">
|
||||
Uncheck to hide the extension's messages in chat prompts.
|
||||
</small>
|
||||
<div class="flex-container flexFlowColumn marginTopBot5 flexGap10">
|
||||
<label for="sd_wand_visible" class="checkbox_label">
|
||||
<span class="flex1 flex-container alignItemsCenter">
|
||||
<i class="fa-solid fa-wand-magic-sparkles"></i>
|
||||
<span data-i18n="Extensions Menu">Extensions Menu</span>
|
||||
</span>
|
||||
<input id="sd_wand_visible" type="checkbox" />
|
||||
</label>
|
||||
<label for="sd_command_visible" class="checkbox_label">
|
||||
<span class="flex1 flex-container alignItemsCenter">
|
||||
<i class="fa-solid fa-terminal"></i>
|
||||
<span data-i18n="Slash Command">Slash Command</span>
|
||||
</span>
|
||||
<input id="sd_command_visible" type="checkbox" />
|
||||
</label>
|
||||
<label for="sd_interactive_visible" class="checkbox_label">
|
||||
<span class="flex1 flex-container alignItemsCenter">
|
||||
<i class="fa-solid fa-message"></i>
|
||||
<span data-i18n="Interactive Mode">Interactive Mode</span>
|
||||
</span>
|
||||
<input id="sd_interactive_visible" type="checkbox" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline-drawer">
|
||||
|
8
public/scripts/extensions/translate/buttons.html
Normal file
8
public/scripts/extensions/translate/buttons.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<div id="translate_chat" class="list-group-item flex-container flexGap5">
|
||||
<div class="fa-solid fa-language extensionsMenuExtensionButton" /></div>
|
||||
<span data-i18n="ext_translate_btn_chat">Translate Chat</span>
|
||||
</div>
|
||||
<div id="translate_input_message" class="list-group-item flex-container flexGap5">
|
||||
<div class="fa-solid fa-keyboard extensionsMenuExtensionButton" /></div>
|
||||
<span data-i18n="ext_translate_btn_input">Translate Input</span>
|
||||
</div>
|
@@ -0,0 +1 @@
|
||||
<h3 data-i18n="ext_translate_delete_confirm_1">Are you sure?</h3><span data-i18n="ext_translate_delete_confirm_2">This will remove translated text from all messages in the current chat. This action cannot be undone.</span>
|
38
public/scripts/extensions/translate/index.html
Normal file
38
public/scripts/extensions/translate/index.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<div class="translation_settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b data-i18n="ext_translate_title">Chat Translation</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<label for="translation_auto_mode" class="checkbox_label" data-i18n="ext_translate_auto_mode">Auto-mode</label>
|
||||
<select id="translation_auto_mode">
|
||||
<option data-i18n="ext_translate_mode_none" value="none">None</option>
|
||||
<option data-i18n="ext_translate_mode_responses" value="responses">Translate responses</option>
|
||||
<option data-i18n="ext_translate_mode_inputs" value="inputs">Translate inputs</option>
|
||||
<option data-i18n="ext_translate_mode_both" value="both">Translate both</option>
|
||||
</select>
|
||||
<label data-i18n="ext_translate_mode_provider" for="translation_provider">Provider</label>
|
||||
<div class="flex-container gap5px flexnowrap marginBot5">
|
||||
<select id="translation_provider" name="provider" class="margin0">
|
||||
<option value="libre">Libre</option>
|
||||
<option value="google">Google</option>
|
||||
<option value="lingva">Lingva</option>
|
||||
<option value="deepl">DeepL</option>
|
||||
<option value="deeplx">DeepLX</option>
|
||||
<option value="bing">Bing</option>
|
||||
<option value="oneringtranslator">OneRingTranslator</option>
|
||||
<option value="yandex">Yandex</option>
|
||||
<select>
|
||||
<div id="translate_key_button" class="menu_button fa-solid fa-key margin0"></div>
|
||||
<div id="translate_url_button" class="menu_button fa-solid fa-link margin0"></div>
|
||||
</div>
|
||||
<label data-i18n="ext_translate_target_lang" for="translation_target_language">Target Language</label>
|
||||
<select id="translation_target_language" name="target_language"></select>
|
||||
<div id="translation_clear" class="menu_button">
|
||||
<i class="fa-solid fa-trash-can"></i>
|
||||
<span data-i18n="ext_translate_clear">Clear Translations</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -10,13 +10,12 @@ import {
|
||||
substituteParams,
|
||||
updateMessageBlock,
|
||||
} from '../../../script.js';
|
||||
import { extension_settings, getContext } from '../../extensions.js';
|
||||
import { extension_settings, getContext, renderExtensionTemplateAsync } from '../../extensions.js';
|
||||
import { findSecret, secret_state, writeSecret } from '../../secrets.js';
|
||||
import { SlashCommand } from '../../slash-commands/SlashCommand.js';
|
||||
import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js';
|
||||
import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
|
||||
import { splitRecursive } from '../../utils.js';
|
||||
import { renderTemplateAsync } from '../../templates.js';
|
||||
|
||||
export const autoModeOptions = {
|
||||
NONE: 'none',
|
||||
@@ -505,7 +504,8 @@ async function onTranslateChatClick() {
|
||||
}
|
||||
|
||||
async function onTranslationsClearClick() {
|
||||
const confirm = await callPopup('<h3>Are you sure?</h3>This will remove translated text from all messages in the current chat. This action cannot be undone.', 'confirm');
|
||||
const popupHtml = await renderExtensionTemplateAsync('translate', 'deleteConfirmation');
|
||||
const confirm = await callPopup(popupHtml, 'confirm');
|
||||
|
||||
if (!confirm) {
|
||||
return;
|
||||
@@ -563,10 +563,10 @@ const handleMessageEdit = createEventHandler(translateMessageEdit, () => true);
|
||||
|
||||
window['translate'] = translate;
|
||||
|
||||
jQuery(async() => {
|
||||
const html = await renderTemplateAsync('translateIndex');
|
||||
jQuery(async () => {
|
||||
const html = await renderExtensionTemplateAsync('translate', 'index');
|
||||
|
||||
const buttonHtml = await renderTemplateAsync('translateButtons');
|
||||
const buttonHtml = await renderExtensionTemplateAsync('translate', 'buttons');
|
||||
$('#extensionsMenu').append(buttonHtml);
|
||||
$('#extensions_settings2').append(html);
|
||||
$('#translate_chat').on('click', onTranslateChatClick);
|
||||
@@ -609,7 +609,7 @@ jQuery(async() => {
|
||||
'libre': 'http://127.0.0.1:5000/translate',
|
||||
'lingva': 'https://lingva.ml/api/v1',
|
||||
'oneringtranslator': 'http://127.0.0.1:4990/translate',
|
||||
'deeplx': 'http://127.0.0.1:1188/translate'
|
||||
'deeplx': 'http://127.0.0.1:1188/translate',
|
||||
};
|
||||
const popupText = `<h3>${optionText} API URL</h3><i>Example: <tt>${String(exampleURLs[extension_settings.translate.provider])}</tt></i>`;
|
||||
|
||||
@@ -653,5 +653,6 @@ jQuery(async() => {
|
||||
: extension_settings.translate.target_language;
|
||||
return await translate(String(value), target);
|
||||
},
|
||||
returns: ARGUMENT_TYPE.STRING,
|
||||
}));
|
||||
});
|
||||
|
@@ -10,6 +10,7 @@ import {
|
||||
setExtensionPrompt,
|
||||
substituteParams,
|
||||
generateRaw,
|
||||
substituteParamsExtended,
|
||||
} from '../../../script.js';
|
||||
import {
|
||||
ModuleWorkerWrapper,
|
||||
@@ -49,6 +50,7 @@ const settings = {
|
||||
summarize_sent: false,
|
||||
summary_source: 'main',
|
||||
summary_prompt: 'Pause your roleplay. Summarize the most important parts of the message. Limit yourself to 250 words or less. Your response should include nothing but the summary.',
|
||||
force_chunk_delimiter: '',
|
||||
|
||||
// For chats
|
||||
enabled_chats: false,
|
||||
@@ -152,6 +154,20 @@ async function onVectorizeAllClick() {
|
||||
|
||||
let syncBlocked = false;
|
||||
|
||||
/**
|
||||
* Gets the chunk delimiters for splitting text.
|
||||
* @returns {string[]} Array of chunk delimiters
|
||||
*/
|
||||
function getChunkDelimiters() {
|
||||
const delimiters = ['\n\n', '\n', ' ', ''];
|
||||
|
||||
if (settings.force_chunk_delimiter) {
|
||||
delimiters.unshift(settings.force_chunk_delimiter);
|
||||
}
|
||||
|
||||
return delimiters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits messages into chunks before inserting them into the vector index.
|
||||
* @param {object[]} items Array of vector items
|
||||
@@ -165,7 +181,7 @@ function splitByChunks(items) {
|
||||
const chunkedItems = [];
|
||||
|
||||
for (const item of items) {
|
||||
const chunks = splitRecursive(item.text, settings.message_chunk_size);
|
||||
const chunks = splitRecursive(item.text, settings.message_chunk_size, getChunkDelimiters());
|
||||
for (const chunk of chunks) {
|
||||
const chunkedItem = { ...item, text: chunk };
|
||||
chunkedItems.push(chunkedItem);
|
||||
@@ -441,7 +457,7 @@ async function injectDataBankChunks(queryText, collectionIds) {
|
||||
return;
|
||||
}
|
||||
|
||||
const insertedText = substituteParams(settings.file_template_db.replace(/{{text}}/i, textResult));
|
||||
const insertedText = substituteParamsExtended(settings.file_template_db, { text: textResult });
|
||||
setExtensionPrompt(EXTENSION_PROMPT_TAG_DB, insertedText, settings.file_position_db, settings.file_depth_db, settings.include_wi, settings.file_depth_role_db);
|
||||
} catch (error) {
|
||||
console.error('Vectors: Failed to insert Data Bank chunks', error);
|
||||
@@ -483,9 +499,10 @@ async function vectorizeFile(fileText, fileName, collectionId, chunkSize, overla
|
||||
|
||||
const toast = toastr.info('Vectorization may take some time, please wait...', `Ingesting file ${fileName}`);
|
||||
const overlapSize = Math.round(chunkSize * overlapPercent / 100);
|
||||
const delimiters = getChunkDelimiters();
|
||||
// Overlap should not be included in chunk size. It will be later compensated by overlapChunks
|
||||
chunkSize = overlapSize > 0 ? (chunkSize - overlapSize) : chunkSize;
|
||||
const chunks = splitRecursive(fileText, chunkSize).map((x, y, z) => overlapSize > 0 ? overlapChunks(x, y, z, overlapSize) : x);
|
||||
const chunks = splitRecursive(fileText, chunkSize, delimiters).map((x, y, z) => overlapSize > 0 ? overlapChunks(x, y, z, overlapSize) : x);
|
||||
console.debug(`Vectors: Split file ${fileName} into ${chunks.length} chunks with ${overlapPercent}% overlap`, chunks);
|
||||
|
||||
const items = chunks.map((chunk, index) => ({ hash: getStringHash(chunk), text: chunk, index: index }));
|
||||
@@ -592,7 +609,7 @@ async function rearrangeChat(chat) {
|
||||
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));
|
||||
return substituteParamsExtended(settings.template, { text: queriedText });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1479,6 +1496,12 @@ jQuery(async () => {
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#vectors_force_chunk_delimiter').prop('checked', settings.force_chunk_delimiter).on('input', () => {
|
||||
settings.force_chunk_delimiter = String($('#vectors_force_chunk_delimiter').val());
|
||||
Object.assign(extension_settings.vectors, settings);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
const validSecret = !!secret_state[SECRET_KEYS.NOMICAI];
|
||||
const placeholder = validSecret ? '✔️ Key saved' : '❌ Missing key';
|
||||
$('#api_key_nomicai').attr('placeholder', placeholder);
|
||||
|
@@ -1,12 +1,12 @@
|
||||
<div class="vectors_settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Vector Storage</b>
|
||||
<b data-i18n="Vector Storage">Vector Storage</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<div class="flex-container flexFlowColumn">
|
||||
<label for="vectors_source">
|
||||
<label for="vectors_source" data-i18n="Vectorization Source">
|
||||
Vectorization Source
|
||||
</label>
|
||||
<select id="vectors_source" class="text_pole">
|
||||
@@ -14,7 +14,7 @@
|
||||
<option value="extras">Extras</option>
|
||||
<option value="palm">Google MakerSuite</option>
|
||||
<option value="llamacpp">llama.cpp</option>
|
||||
<option value="transformers">Local (Transformers)</option>
|
||||
<option value="transformers" data-i18n="Local (Transformers)">Local (Transformers)</option>
|
||||
<option value="mistral">MistralAI</option>
|
||||
<option value="nomicai">NomicAI</option>
|
||||
<option value="ollama">Ollama</option>
|
||||
@@ -24,28 +24,28 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-container flexFlowColumn" id="ollama_vectorsModel">
|
||||
<label for="vectors_ollama_model">
|
||||
<label for="vectors_ollama_model" data-i18n="Vectorization Model">
|
||||
Vectorization Model
|
||||
</label>
|
||||
<input id="vectors_ollama_model" class="text_pole" type="text" placeholder="Model tag, e.g. llama3" />
|
||||
<label for="vectors_ollama_keep" class="checkbox_label" title="When checked, the model will not be unloaded after use.">
|
||||
<input id="vectors_ollama_keep" type="checkbox" />
|
||||
<span>Keep model in memory</span>
|
||||
<span data-i18n="Keep model in memory">Keep model in memory</span>
|
||||
</label>
|
||||
<i>
|
||||
<i data-i18n="Hint: Download models and set the URL in the API connection settings.">
|
||||
Hint: Download models and set the URL in the API connection settings.
|
||||
</i>
|
||||
</div>
|
||||
<div class="flex-container flexFlowColumn" id="llamacpp_vectorsModel">
|
||||
<span>
|
||||
<span data-i18n="The server MUST be started with the --embedding flag to use this feature!">
|
||||
The server MUST be started with the <code>--embedding</code> flag to use this feature!
|
||||
</span>
|
||||
<i>
|
||||
<i data-i18n="Hint: Set the URL in the API connection settings.">
|
||||
Hint: Set the URL in the API connection settings.
|
||||
</i>
|
||||
</div>
|
||||
<div class="flex-container flexFlowColumn" id="openai_vectorsModel">
|
||||
<label for="vectors_openai_model">
|
||||
<label for="vectors_openai_model" data-i18n="Vectorization Model">
|
||||
Vectorization Model
|
||||
</label>
|
||||
<select id="vectors_openai_model" class="text_pole">
|
||||
@@ -55,7 +55,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-container flexFlowColumn" id="cohere_vectorsModel">
|
||||
<label for="vectors_cohere_model">
|
||||
<label for="vectors_cohere_model" data-i18n="Vectorization Model">
|
||||
Vectorization Model
|
||||
</label>
|
||||
<select id="vectors_cohere_model" class="text_pole">
|
||||
@@ -69,7 +69,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-container flexFlowColumn" id="together_vectorsModel">
|
||||
<label for="vectors_togetherai_model">
|
||||
<label for="vectors_togetherai_model" data-i18n="Vectorization Model">
|
||||
Vectorization Model
|
||||
</label>
|
||||
<select id="vectors_togetherai_model" class="text_pole">
|
||||
@@ -84,11 +84,11 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-container flexFlowColumn" id="vllm_vectorsModel">
|
||||
<label for="vectors_vllm_model">
|
||||
<label for="vectors_vllm_model" data-i18n="Vectorization Model">
|
||||
Vectorization Model
|
||||
</label>
|
||||
<input id="vectors_vllm_model" class="text_pole" type="text" placeholder="Model name, e.g. intfloat/e5-mistral-7b-instruct" />
|
||||
<i>
|
||||
<i data-i18n="Hint: Set the URL in the API connection settings.">
|
||||
Hint: Set the URL in the API connection settings.
|
||||
</i>
|
||||
</div>
|
||||
@@ -102,7 +102,7 @@
|
||||
|
||||
<div class="flex-container flexFlowColumn" id="nomicai_apiKey">
|
||||
<label for="api_key_nomicai">
|
||||
<span>NomicAI API Key</span>
|
||||
<span data-i18n="NomicAI API Key">NomicAI API Key</span>
|
||||
</label>
|
||||
<div class="flex-container">
|
||||
<input id="api_key_nomicai" name="api_key_nomicai" class="text_pole flex1 wide100p" maxlength="500" size="35" type="text" autocomplete="off">
|
||||
@@ -117,48 +117,54 @@
|
||||
<div class="flex-container marginTopBot5">
|
||||
<div class="flex-container flex1 flexFlowColumn" title="How many last messages will be matched for relevance.">
|
||||
<label for="vectors_query">
|
||||
<span>Query messages</span>
|
||||
<small data-i18n="Query messages">Query messages</small>
|
||||
</label>
|
||||
<input type="number" id="vectors_query" class="text_pole widthUnset" min="1" max="99" />
|
||||
<input type="number" id="vectors_query" class="text_pole" min="1" max="99" />
|
||||
</div>
|
||||
<div class="flex-container flex1 flexFlowColumn" title="Cut-off score for relevance. Helps to filter out irrelevant data.">
|
||||
<label for="vectors_query">
|
||||
<span>Score threshold</span>
|
||||
<small data-i18n="Score threshold">Score threshold</small>
|
||||
</label>
|
||||
<input type="number" id="vectors_score_threshold" class="text_pole widthUnset" min="0" max="1" step="0.05" />
|
||||
<input type="number" id="vectors_score_threshold" class="text_pole" min="0" max="1" step="0.05" />
|
||||
</div>
|
||||
<div class="flex-container flex1 flexFlowColumn" title="Prioritize chunking on the preferred delimiter.">
|
||||
<label for="vectors_force_chunk_delimiter">
|
||||
<small data-i18n="Chunk boundary">Chunk boundary</small>
|
||||
</label>
|
||||
<textarea id="vectors_force_chunk_delimiter" class="text_pole" rows="1" placeholder="(None)"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-container">
|
||||
<label class="checkbox_label expander" for="vectors_include_wi" title="Query results can activate World Info entries.">
|
||||
<input id="vectors_include_wi" type="checkbox" class="checkbox">
|
||||
Include in World Info Scanning
|
||||
<span data-i18n="Include in World Info Scanning">Include in World Info Scanning</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<h4>
|
||||
<h4 data-i18n="World Info settings">
|
||||
World Info settings
|
||||
</h4>
|
||||
|
||||
<label class="checkbox_label" for="vectors_enabled_world_info" title="Enable activation of World Info entries based on vector similarity.">
|
||||
<input id="vectors_enabled_world_info" type="checkbox" class="checkbox">
|
||||
Enabled for World Info
|
||||
<span data-i18n="Enable for World Info">Enable for World Info</span>
|
||||
</label>
|
||||
|
||||
<div id="vectors_world_info_settings" class="marginTopBot5">
|
||||
<div class="flex-container">
|
||||
<label for="vectors_enabled_for_all" class="checkbox_label">
|
||||
<input id="vectors_enabled_for_all" type="checkbox" />
|
||||
<span>Enabled for all entries</span>
|
||||
<span data-i18n="Enabled for all entries">Enabled for all entries</span>
|
||||
</label>
|
||||
<ul class="margin0">
|
||||
<li>
|
||||
<small>Checked: all entries except ❌ status can be activated.</small>
|
||||
<small data-i18n="Checked: all entries except ❌ status can be activated.">Checked: all entries except ❌ status can be activated.</small>
|
||||
</li>
|
||||
<li>
|
||||
<small>Unchecked: only entries with 🔗 status can be activated.</small>
|
||||
<small data-i18n="Unchecked: only entries with ❌ status can be activated.">Unchecked: only entries with 🔗 status can be activated.</small>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -168,7 +174,7 @@
|
||||
</div>
|
||||
<div class="flex1" title="Maximum number of entries to be activated">
|
||||
<label for="vectors_max_entries" >
|
||||
<small>Max Entries</small>
|
||||
<small data-i18n="Max Entries">Max Entries</small>
|
||||
</label>
|
||||
<input id="vectors_max_entries" type="number" class="text_pole widthUnset" min="1" max="9999" />
|
||||
</div>
|
||||
@@ -178,13 +184,13 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4>
|
||||
<h4 data-i18n="File vectorization settings">
|
||||
File vectorization settings
|
||||
</h4>
|
||||
|
||||
<label class="checkbox_label" for="vectors_enabled_files">
|
||||
<input id="vectors_enabled_files" type="checkbox" class="checkbox">
|
||||
Enabled for files
|
||||
<span data-i18n="Enable for files">Enable for files</span>
|
||||
</label>
|
||||
|
||||
<div id="vectors_files_settings" class="marginTopBot5">
|
||||
@@ -196,152 +202,153 @@
|
||||
<i class="fa-solid fa-flask" title="Experimental feature"></i>
|
||||
</label>
|
||||
<div class="flex justifyCenter" title="These settings apply to files attached directly to messages.">
|
||||
<span>Message attachments</span>
|
||||
<span data-i18n="Message attachments">Message attachments</span>
|
||||
</div>
|
||||
<div class="flex-container">
|
||||
<div class="flex1" title="Only files past this size will be vectorized.">
|
||||
<label for="vectors_size_threshold">
|
||||
<small>Size threshold (KB)</small>
|
||||
<small data-i18n="Size threshold (KB)">Size threshold (KB)</small>
|
||||
</label>
|
||||
<input id="vectors_size_threshold" type="number" class="text_pole" min="1" max="99999" />
|
||||
</div>
|
||||
<div class="flex1" title="Chunk size for file splitting.">
|
||||
<label for="vectors_chunk_size">
|
||||
<small>Chunk size (chars)</small>
|
||||
<small data-i18n="Chunk size (chars)">Chunk size (chars)</small>
|
||||
</label>
|
||||
<input id="vectors_chunk_size" type="number" class="text_pole" min="1" max="99999" />
|
||||
</div>
|
||||
<div class="flex1" title="The overlap between adjacent chunks in % from chunk size. The overlap text is trimmed to sentence boundaries. 0 = disabled.">
|
||||
<label for="vectors_overlap_percent">
|
||||
<small>Chunk overlap (%)</small>
|
||||
<small data-i18n="Chunk overlap (%)">Chunk overlap (%)</small>
|
||||
</label>
|
||||
<input id="vectors_overlap_percent" type="number" class="text_pole" min="0" max="99" step="1" />
|
||||
</div>
|
||||
<div class="flex1" title="How many chunks to retrieve when querying.">
|
||||
<label for="vectors_chunk_count">
|
||||
<small>Retrieve chunks</small>
|
||||
<small data-i18n="Retrieve chunks">Retrieve chunks</small>
|
||||
</label>
|
||||
<input id="vectors_chunk_count" type="number" class="text_pole" min="1" max="99999" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justifyCenter" title="These settings apply to files stored in the Data Bank.">
|
||||
<span>Data Bank files</span>
|
||||
<span data-i18n="Data Bank files">Data Bank files</span>
|
||||
</div>
|
||||
<div class="flex-container">
|
||||
<div class="flex1" title="Only files past this size will be vectorized.">
|
||||
<label for="vectors_size_threshold_db">
|
||||
<small>Size threshold (KB)</small>
|
||||
<small data-i18n="Size threshold (KB)">Size threshold (KB)</small>
|
||||
</label>
|
||||
<input id="vectors_size_threshold_db" type="number" class="text_pole" min="1" max="99999" />
|
||||
</div>
|
||||
<div class="flex1" title="Chunk size for file splitting.">
|
||||
<label for="vectors_chunk_size_db">
|
||||
<small>Chunk size (chars)</small>
|
||||
<small data-i18n="Chunk size (chars)">Chunk size (chars)</small>
|
||||
</label>
|
||||
<input id="vectors_chunk_size_db" type="number" class="text_pole" min="1" max="99999" />
|
||||
</div>
|
||||
<div class="flex1" title="The overlap between adjacent chunks in % from chunk size. The overlap text is trimmed to sentence boundaries. 0 = disabled.">
|
||||
<label for="vectors_overlap_percent_db">
|
||||
<small>Chunk overlap (%)</small>
|
||||
<small data-i18n="Chunk overlap (%)">Chunk overlap (%)</small>
|
||||
</label>
|
||||
<input id="vectors_overlap_percent_db" type="number" class="text_pole" min="0" max="99" step="1" />
|
||||
</div>
|
||||
<div class="flex1" title="How many chunks to retrieve when querying.">
|
||||
<label for="vectors_chunk_count_db">
|
||||
<small>Retrieve chunks</small>
|
||||
<small data-i18n="Retrieve chunks">Retrieve chunks</small>
|
||||
</label>
|
||||
<input id="vectors_chunk_count_db" type="number" class="text_pole" min="1" max="99999" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-container flexFlowColumn">
|
||||
<label for="vectors_file_template_db">
|
||||
<span>Injection Template</span>
|
||||
<span data-i18n="Injection Template">Injection Template</span>
|
||||
</label>
|
||||
<textarea id="vectors_file_template_db" class="margin0 text_pole textarea_compact" rows="3" placeholder="Use {{text}} macro to specify the position of retrieved text."></textarea>
|
||||
<label for="vectors_file_position_db">Injection Position</label>
|
||||
<label for="vectors_file_position_db" data-i18n="Injection Position">Injection Position</label>
|
||||
<div class="radio_group">
|
||||
<label>
|
||||
<input type="radio" name="vectors_file_position_db" value="2" />
|
||||
<span>Before Main Prompt / Story String</span>
|
||||
<span data-i18n="Before Main Prompt / Story String">Before Main Prompt / Story String</span>
|
||||
</label>
|
||||
<!--Keep these as 0 and 1 to interface with the setExtensionPrompt function-->
|
||||
<label>
|
||||
<input type="radio" name="vectors_file_position_db" value="0" />
|
||||
<span>After Main Prompt / Story String</span>
|
||||
<span data-i18n="After Main Prompt / Story String">After Main Prompt / Story String</span>
|
||||
</label>
|
||||
<label for="vectors_file_depth_db" title="How many messages before the current end of the chat." data-i18n="[title]How many messages before the current end of the chat.">
|
||||
<input type="radio" name="vectors_file_position_db" value="1" />
|
||||
<span>In-chat @ Depth</span>
|
||||
<span data-i18n="In-chat @ Depth">In-chat @ Depth</span>
|
||||
<input id="vectors_file_depth_db" class="text_pole widthUnset" type="number" min="0" max="999" />
|
||||
<span>as</span>
|
||||
<select id="vectors_file_depth_role_db" class="text_pole widthNatural">
|
||||
<option value="0">System</option>
|
||||
<option value="1">User</option>
|
||||
<option value="2">Assistant</option>
|
||||
<option value="0" data-i18n="System">System</option>
|
||||
<option value="1" data-i18n="User">User</option>
|
||||
<option value="2" data-i18n="Assistant">Assistant</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-container">
|
||||
<div id="vectors_files_vectorize_all" class="menu_button menu_button_icon" title="Vectorize all files in the Data Bank and current chat.">
|
||||
Vectorize All
|
||||
<span data-i18n="Vectorize All">Vectorize All</span>
|
||||
</div>
|
||||
<div id="vectors_files_purge" class="menu_button menu_button_icon" title="Purge all file vectors in the Data Bank and current chat.">
|
||||
Purge Vectors
|
||||
<span data-i18n="Purge Vectors">Purge Vectors</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<h4>
|
||||
<h4 data-i18n="Chat vectorization settings">
|
||||
Chat vectorization settings
|
||||
</h4>
|
||||
<label class="checkbox_label" for="vectors_enabled_chats">
|
||||
<input id="vectors_enabled_chats" type="checkbox" class="checkbox">
|
||||
Enabled for chat messages
|
||||
<span data-i18n="Enabled for chat messages">Enabled for chat messages</span>
|
||||
</label>
|
||||
|
||||
<hr>
|
||||
|
||||
<div id="vectors_chats_settings">
|
||||
<div id="vectors_advanced_settings">
|
||||
<label for="vectors_template">
|
||||
<label for="vectors_template" data-i18n="Injection Template">
|
||||
Injection Template
|
||||
</label>
|
||||
<textarea id="vectors_template" class="text_pole textarea_compact" rows="3" placeholder="Use {{text}} macro to specify the position of retrieved text."></textarea>
|
||||
<label for="vectors_position">Injection Position</label>
|
||||
<label for="vectors_position" data-i18n="Injection Position">Injection Position</label>
|
||||
<div class="radio_group">
|
||||
<label>
|
||||
<input type="radio" name="vectors_position" value="2" />
|
||||
Before Main Prompt / Story String
|
||||
<span data-i18n="Before Main Prompt / Story String">Before Main Prompt / Story String</span>
|
||||
</label>
|
||||
<!--Keep these as 0 and 1 to interface with the setExtensionPrompt function-->
|
||||
<label>
|
||||
<input type="radio" name="vectors_position" value="0" />
|
||||
After Main Prompt / Story String
|
||||
<span data-i18n="After Main Prompt / Story String">After Main Prompt / Story String</span>
|
||||
</label>
|
||||
<label for="vectors_depth" title="How many messages before the current end of the chat." data-i18n="[title]How many messages before the current end of the chat.">
|
||||
<input type="radio" name="vectors_position" value="1" />
|
||||
In-chat @ Depth <input id="vectors_depth" class="text_pole widthUnset" type="number" min="0" max="999" />
|
||||
<span data-i18n="In-chat @ Depth">In-chat @ Depth </span>
|
||||
<input id="vectors_depth" class="text_pole widthUnset" type="number" min="0" max="999" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="flex-container">
|
||||
<div class="flex1" title="Can increase the retrieval quality for the cost of processing. 0 = disabled.">
|
||||
<label for="vectors_message_chunk_size">
|
||||
<small>Chunk size (chars)</small>
|
||||
<small data-i18n="Chunk size (chars)">Chunk size (chars)</small>
|
||||
</label>
|
||||
<input id="vectors_message_chunk_size" type="number" class="text_pole widthUnset" min="0" max="9999" />
|
||||
</div>
|
||||
<div class="flex1" title="Prevents last N messages from being placed out of order.">
|
||||
<label for="vectors_protect">
|
||||
<small>Retain#</small>
|
||||
<small data-i18n="Retain#">Retain#</small>
|
||||
</label>
|
||||
<input type="number" id="vectors_protect" class="text_pole widthUnset" min="1" max="9999" />
|
||||
</div>
|
||||
<div class="flex1" title="How many past messages to insert as memories.">
|
||||
<label for="vectors_insert">
|
||||
<small>Insert#</small>
|
||||
<small data-i18n="Insert#">Insert#</small>
|
||||
</label>
|
||||
<input type="number" id="vectors_insert" class="text_pole widthUnset" min="1" max="9999" />
|
||||
</div>
|
||||
@@ -350,43 +357,43 @@
|
||||
<div class="flex-container flexFlowColumn">
|
||||
<div class="flex-container alignitemscenter justifyCenter">
|
||||
<i class="fa-solid fa-flask" title="Summarization for vectors is an experimental feature that may improve vectors or may worsen them. Use at your own discretion."></i>
|
||||
<span>Vector Summarization</span>
|
||||
<span data-i18n="Vector Summarization">Vector Summarization</span>
|
||||
</div>
|
||||
<label class="checkbox_label expander" for="vectors_summarize" title="Summarize chat messages before generating embeddings.">
|
||||
<input id="vectors_summarize" type="checkbox" class="checkbox">
|
||||
Summarize chat messages for vector generation
|
||||
<span data-i18n="Summarize chat messages for vector generation">Summarize chat messages for vector generation</span>
|
||||
</label>
|
||||
<i class="failure">Warning: This will slow down vector generation drastically, as all messages have to be summarized first.</i>
|
||||
<i class="failure" data-i18n="Warning: This will slow down vector generation drastically, as all messages have to be summarized first.">Warning: This will slow down vector generation drastically, as all messages have to be summarized first.</i>
|
||||
|
||||
<label class="checkbox_label expander" for="vectors_summarize_user" title="Summarize sent chat messages before generating embeddings.">
|
||||
<input id="vectors_summarize_user" type="checkbox" class="checkbox">
|
||||
Summarize chat messages when sending
|
||||
<span data-i18n="Summarize chat messages when sending">Summarize chat messages when sending</span>
|
||||
</label>
|
||||
<i class="failure">Warning: This might cause your sent messages to take a bit to process and slow down response time.</i>
|
||||
<i class="failure" data-i18n="Warning: This might cause your sent messages to take a bit to process and slow down response time.">Warning: This might cause your sent messages to take a bit to process and slow down response time.</i>
|
||||
|
||||
<label for="vectors_summary_source">Summarize with:</label>
|
||||
<label for="vectors_summary_source" title="Summarize with:">Summarize with:</label>
|
||||
<select id="vectors_summary_source" class="text_pole">
|
||||
<option value="main">Main API</option>
|
||||
<option value="extras">Extras API</option>
|
||||
<option value="main" data-i18n="Main API">Main API</option>
|
||||
<option value="extras" data-i18n="Extras API">Extras API</option>
|
||||
</select>
|
||||
|
||||
<label for="vectors_summary_prompt">Summary Prompt:</label>
|
||||
<small>Only used when Main API is selected.</small>
|
||||
<label for="vectors_summary_prompt" title="Summary Prompt:">Summary Prompt:</label>
|
||||
<small data-i18n="Only used when Main API is selected.">Only used when Main API is selected.</small>
|
||||
<textarea id="vectors_summary_prompt" class="text_pole textarea_compact" rows="6" placeholder="This prompt will be sent to AI to request the summary generation."></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<small>
|
||||
<small data-i18n="Old messages are vectorized gradually as you chat. To process all previous messages, click the button below.">
|
||||
Old messages are vectorized gradually as you chat.
|
||||
To process all previous messages, click the button below.
|
||||
</small>
|
||||
<div class="flex-container">
|
||||
<div id="vectors_vectorize_all" class="menu_button menu_button_icon">
|
||||
<div id="vectors_vectorize_all" class="menu_button menu_button_icon" data-i18n="Vectorize All">
|
||||
Vectorize All
|
||||
</div>
|
||||
<div id="vectors_purge" class="menu_button menu_button_icon">
|
||||
<div id="vectors_purge" class="menu_button menu_button_icon" data-i18n="Purge Vectors">
|
||||
Purge Vectors
|
||||
</div>
|
||||
<div id="vectors_view_stats" class="menu_button menu_button_icon">
|
||||
<div id="vectors_view_stats" class="menu_button menu_button_icon" data-i18n="View Stats">
|
||||
View Stats
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user