mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge branch 'staging' into slash-escapes
This commit is contained in:
@@ -139,7 +139,7 @@ const languageCodes = {
|
||||
};
|
||||
|
||||
const KEY_REQUIRED = ['deepl', 'libre'];
|
||||
const LOCAL_URL = ['libre', 'oneringtranslator', 'deeplx'];
|
||||
const LOCAL_URL = ['libre', 'oneringtranslator', 'deeplx', 'lingva'];
|
||||
|
||||
function showKeysButton() {
|
||||
const providerRequiresKey = KEY_REQUIRED.includes(extension_settings.translate.provider);
|
||||
@@ -249,6 +249,27 @@ async function translateProviderGoogle(text, lang) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates text using an instance of the Lingva Translate
|
||||
* @param {string} text Text to translate
|
||||
* @param {string} lang Target language code
|
||||
* @returns {Promise<string>} Translated text
|
||||
*/
|
||||
async function translateProviderLingva(text, lang) {
|
||||
const response = await fetch('/api/translate/lingva', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({ text: text, lang: lang }),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.text();
|
||||
return result;
|
||||
}
|
||||
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates text using the DeepL API
|
||||
* @param {string} text Text to translate
|
||||
@@ -355,6 +376,8 @@ async function translate(text, lang) {
|
||||
return await translateProviderLibre(text, lang);
|
||||
case 'google':
|
||||
return await chunkedTranslate(text, lang, translateProviderGoogle, 5000);
|
||||
case 'lingva':
|
||||
return await chunkedTranslate(text, lang, translateProviderLingva, 5000);
|
||||
case 'deepl':
|
||||
return await translateProviderDeepl(text, lang);
|
||||
case 'deeplx':
|
||||
@@ -507,6 +530,7 @@ jQuery(() => {
|
||||
<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>
|
||||
@@ -569,6 +593,7 @@ jQuery(() => {
|
||||
const optionText = $('#translation_provider option:selected').text();
|
||||
const exampleURLs = {
|
||||
'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',
|
||||
};
|
||||
|
@@ -2,7 +2,9 @@
|
||||
"display_name": "Vector Storage",
|
||||
"loading_order": 100,
|
||||
"requires": [],
|
||||
"optional": [],
|
||||
"optional": [
|
||||
"embeddings"
|
||||
],
|
||||
"generate_interceptor": "vectors_rearrangeChat",
|
||||
"js": "index.js",
|
||||
"css": "style.css",
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { fuzzySearchCharacters, fuzzySearchGroups, fuzzySearchTags, fuzzySearchWorldInfo, power_user } from './power-user.js';
|
||||
import { fuzzySearchCharacters, fuzzySearchGroups, fuzzySearchPersonas, fuzzySearchTags, fuzzySearchWorldInfo, power_user } from './power-user.js';
|
||||
import { tag_map } from './tags.js';
|
||||
|
||||
/**
|
||||
@@ -11,6 +11,7 @@ export const FILTER_TYPES = {
|
||||
FAV: 'fav',
|
||||
GROUP: 'group',
|
||||
WORLD_INFO_SEARCH: 'world_info_search',
|
||||
PERSONA_SEARCH: 'persona_search',
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -39,6 +40,7 @@ export class FilterHelper {
|
||||
[FILTER_TYPES.FAV]: this.favFilter.bind(this),
|
||||
[FILTER_TYPES.TAG]: this.tagFilter.bind(this),
|
||||
[FILTER_TYPES.WORLD_INFO_SEARCH]: this.wiSearchFilter.bind(this),
|
||||
[FILTER_TYPES.PERSONA_SEARCH]: this.personaSearchFilter.bind(this),
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -51,6 +53,7 @@ export class FilterHelper {
|
||||
[FILTER_TYPES.FAV]: false,
|
||||
[FILTER_TYPES.TAG]: { excluded: [], selected: [] },
|
||||
[FILTER_TYPES.WORLD_INFO_SEARCH]: '',
|
||||
[FILTER_TYPES.PERSONA_SEARCH]: '',
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -69,6 +72,22 @@ export class FilterHelper {
|
||||
return data.filter(entity => fuzzySearchResults.includes(entity.uid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a search filter to Persona data.
|
||||
* @param {string[]} data The data to filter.
|
||||
* @returns {string[]} The filtered data.
|
||||
*/
|
||||
personaSearchFilter(data) {
|
||||
const term = this.filterData[FILTER_TYPES.PERSONA_SEARCH];
|
||||
|
||||
if (!term) {
|
||||
return data;
|
||||
}
|
||||
|
||||
const fuzzySearchResults = fuzzySearchPersonas(data, term);
|
||||
return data.filter(entity => fuzzySearchResults.includes(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given entity is tagged with the given tag ID.
|
||||
* @param {object} entity Searchable entity
|
||||
|
@@ -108,6 +108,7 @@ export const group_activation_strategy = {
|
||||
export const group_generation_mode = {
|
||||
SWAP: 0,
|
||||
APPEND: 1,
|
||||
APPEND_DISABLED: 2,
|
||||
};
|
||||
|
||||
const DEFAULT_AUTO_MODE_DELAY = 5;
|
||||
@@ -325,7 +326,7 @@ export function getGroupDepthPrompts(groupId, characterId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines group members info a single string. Only for groups with generation mode set to APPEND.
|
||||
* Combines group members cards into a single string. Only for groups with generation mode set to APPEND or APPEND_DISABLED.
|
||||
* @param {string} groupId Group ID
|
||||
* @param {number} characterId Current Character ID
|
||||
* @returns {{description: string, personality: string, scenario: string, mesExamples: string}} Group character cards combined
|
||||
@@ -334,7 +335,7 @@ export function getGroupCharacterCards(groupId, characterId) {
|
||||
console.debug('getGroupCharacterCards entered for group: ', groupId);
|
||||
const group = groups.find(x => x.id === groupId);
|
||||
|
||||
if (!group || group?.generation_mode !== group_generation_mode.APPEND || !Array.isArray(group.members) || !group.members.length) {
|
||||
if (!group || !group?.generation_mode || !Array.isArray(group.members) || !group.members.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -354,7 +355,7 @@ export function getGroupCharacterCards(groupId, characterId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (group.disabled_members.includes(member) && characterId !== index) {
|
||||
if (group.disabled_members.includes(member) && characterId !== index && group.generation_mode !== group_generation_mode.APPEND_DISABLED) {
|
||||
console.debug(`Skipping disabled group member: ${member}`);
|
||||
continue;
|
||||
}
|
||||
|
@@ -374,6 +374,11 @@ function withVirtualWhitespace(text, span) {
|
||||
* @param {string | null} continueFrom - for 'continue' generations, the prompt
|
||||
*/
|
||||
export function saveLogprobsForActiveMessage(logprobs, continueFrom) {
|
||||
if (!logprobs) {
|
||||
// non-streaming APIs could return null data
|
||||
return;
|
||||
}
|
||||
|
||||
convertTokenIdLogprobsToText(logprobs);
|
||||
|
||||
const msgId = chat.length - 1;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { chat, main_api, getMaxContextSize, getCharacterCardFields } from '../script.js';
|
||||
import { chat, main_api, getMaxContextSize } from '../script.js';
|
||||
import { timestampToMoment, isDigitsOnly } from './utils.js';
|
||||
import { textgenerationwebui_banned_in_macros } from './textgen-settings.js';
|
||||
import { replaceInstructMacros } from './instruct-mode.js';
|
||||
@@ -201,56 +201,41 @@ function diceRollReplace(input, invalidRollPlaceholder = '') {
|
||||
/**
|
||||
* Substitutes {{macro}} parameters in a string.
|
||||
* @param {string} content - The string to substitute parameters in.
|
||||
* @param {*} _name1 - The name of the user.
|
||||
* @param {*} _name2 - The name of the character.
|
||||
* @param {*} _original - The original message for {{original}} substitution.
|
||||
* @param {*} _group - The group members list for {{group}} substitution.
|
||||
* @param {boolean} _replaceCharacterCard - Whether to replace character card macros.
|
||||
* @param {Object<string, *>} env - Map of macro names to the values they'll be substituted with. If the param
|
||||
* values are functions, those functions will be called and their return values are used.
|
||||
* @returns {string} The string with substituted parameters.
|
||||
*/
|
||||
export function evaluateMacros(content, _name1, _name2, _original, _group, _replaceCharacterCard = true) {
|
||||
export function evaluateMacros(content, env) {
|
||||
if (!content) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Replace {{original}} with the original message
|
||||
// Note: only replace the first instance of {{original}}
|
||||
// This will hopefully prevent the abuse
|
||||
if (typeof _original === 'string') {
|
||||
content = content.replace(/{{original}}/i, _original);
|
||||
}
|
||||
content = diceRollReplace(content);
|
||||
content = replaceInstructMacros(content);
|
||||
content = replaceVariableMacros(content);
|
||||
content = content.replace(/{{newline}}/gi, '\n');
|
||||
content = content.replace(/{{input}}/gi, String($('#send_textarea').val()));
|
||||
|
||||
if (_replaceCharacterCard) {
|
||||
const fields = getCharacterCardFields();
|
||||
content = content.replace(/{{charPrompt}}/gi, fields.system || '');
|
||||
content = content.replace(/{{charJailbreak}}/gi, fields.jailbreak || '');
|
||||
content = content.replace(/{{description}}/gi, fields.description || '');
|
||||
content = content.replace(/{{personality}}/gi, fields.personality || '');
|
||||
content = content.replace(/{{scenario}}/gi, fields.scenario || '');
|
||||
content = content.replace(/{{persona}}/gi, fields.persona || '');
|
||||
content = content.replace(/{{mesExamples}}/gi, fields.mesExamples || '');
|
||||
// Substitute passed-in variables
|
||||
for (const varName in env) {
|
||||
if (!Object.hasOwn(env, varName)) continue;
|
||||
|
||||
const param = env[varName];
|
||||
content = content.replace(new RegExp(`{{${varName}}}`, 'gi'), param);
|
||||
}
|
||||
|
||||
content = content.replace(/{{maxPrompt}}/gi, () => String(getMaxContextSize()));
|
||||
content = content.replace(/{{user}}/gi, _name1);
|
||||
content = content.replace(/{{char}}/gi, _name2);
|
||||
content = content.replace(/{{charIfNotGroup}}/gi, _group);
|
||||
content = content.replace(/{{group}}/gi, _group);
|
||||
content = content.replace(/{{lastMessage}}/gi, getLastMessage());
|
||||
content = content.replace(/{{lastMessageId}}/gi, getLastMessageId());
|
||||
content = content.replace(/{{firstIncludedMessageId}}/gi, getFirstIncludedMessageId());
|
||||
content = content.replace(/{{lastSwipeId}}/gi, getLastSwipeId());
|
||||
content = content.replace(/{{currentSwipeId}}/gi, getCurrentSwipeId());
|
||||
|
||||
content = content.replace(/<USER>/gi, _name1);
|
||||
content = content.replace(/<BOT>/gi, _name2);
|
||||
content = content.replace(/<CHARIFNOTGROUP>/gi, _group);
|
||||
content = content.replace(/<GROUP>/gi, _group);
|
||||
// Legacy non-macro substitutions
|
||||
content = content.replace(/<USER>/gi, typeof env.user === 'function' ? env.user() : env.user);
|
||||
content = content.replace(/<BOT>/gi, typeof env.char === 'function' ? env.char() : env.char);
|
||||
content = content.replace(/<CHARIFNOTGROUP>/gi, typeof env.group === 'function' ? env.group() : env.group);
|
||||
content = content.replace(/<GROUP>/gi, typeof env.group === 'function' ? env.group() : env.group);
|
||||
|
||||
content = content.replace(/\{\{\/\/([\s\S]*?)\}\}/gm, '');
|
||||
|
||||
|
@@ -317,6 +317,15 @@ const oai_settings = {
|
||||
seed: -1,
|
||||
};
|
||||
|
||||
export let proxies = [
|
||||
{
|
||||
name: 'None',
|
||||
url: '',
|
||||
password: '',
|
||||
},
|
||||
];
|
||||
export let selected_proxy = proxies[0];
|
||||
|
||||
let openai_setting_names;
|
||||
let openai_settings;
|
||||
|
||||
@@ -1596,8 +1605,8 @@ async function sendOpenAIRequest(type, messages, signal) {
|
||||
delete generate_data.stop;
|
||||
}
|
||||
|
||||
// Proxy is only supported for Claude and OpenAI
|
||||
if (oai_settings.reverse_proxy && [chat_completion_sources.CLAUDE, chat_completion_sources.OPENAI].includes(oai_settings.chat_completion_source)) {
|
||||
// Proxy is only supported for Claude, OpenAI and Mistral
|
||||
if (oai_settings.reverse_proxy && [chat_completion_sources.CLAUDE, chat_completion_sources.OPENAI, chat_completion_sources.MISTRALAI].includes(oai_settings.chat_completion_source)) {
|
||||
validateReverseProxy();
|
||||
generate_data['reverse_proxy'] = oai_settings.reverse_proxy;
|
||||
generate_data['proxy_password'] = oai_settings.proxy_password;
|
||||
@@ -3803,6 +3812,110 @@ export function isImageInliningSupported() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy stuff
|
||||
*/
|
||||
export function loadProxyPresets(settings) {
|
||||
let proxyPresets = settings.proxies;
|
||||
selected_proxy = settings.selected_proxy || selected_proxy;
|
||||
if (!Array.isArray(proxyPresets) || proxyPresets.length === 0) {
|
||||
proxyPresets = proxies;
|
||||
} else {
|
||||
proxies = proxyPresets;
|
||||
}
|
||||
|
||||
$('#openai_proxy_preset').empty();
|
||||
|
||||
for (const preset of proxyPresets) {
|
||||
const option = document.createElement('option');
|
||||
option.innerText = preset.name;
|
||||
option.value = preset.name;
|
||||
option.selected = preset.name === 'None';
|
||||
$('#openai_proxy_preset').append(option);
|
||||
}
|
||||
$('#openai_proxy_preset').val(selected_proxy.name);
|
||||
setProxyPreset(selected_proxy.name, selected_proxy.url, selected_proxy.password);
|
||||
}
|
||||
|
||||
function setProxyPreset(name, url, password) {
|
||||
const preset = proxies.find(p => p.name === name);
|
||||
if (preset) {
|
||||
preset.url = url;
|
||||
preset.password = password;
|
||||
selected_proxy = preset;
|
||||
} else {
|
||||
let new_proxy = { name, url, password };
|
||||
proxies.push(new_proxy);
|
||||
selected_proxy = new_proxy;
|
||||
}
|
||||
|
||||
$('#openai_reverse_proxy_name').val(name);
|
||||
oai_settings.reverse_proxy = url;
|
||||
$('#openai_reverse_proxy').val(oai_settings.reverse_proxy);
|
||||
oai_settings.proxy_password = password;
|
||||
$('#openai_proxy_password').val(oai_settings.proxy_password);
|
||||
reconnectOpenAi();
|
||||
}
|
||||
|
||||
function onProxyPresetChange() {
|
||||
const value = String($('#openai_proxy_preset').find(':selected').val());
|
||||
const selectedPreset = proxies.find(preset => preset.name === value);
|
||||
|
||||
if (selectedPreset) {
|
||||
setProxyPreset(selectedPreset.name, selectedPreset.url, selectedPreset.password);
|
||||
} else {
|
||||
console.error(`Proxy preset "${value}" not found in proxies array.`);
|
||||
}
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
$('#save_proxy').on('click', async function () {
|
||||
const presetName = $('#openai_reverse_proxy_name').val();
|
||||
const reverseProxy = $('#openai_reverse_proxy').val();
|
||||
const proxyPassword = $('#openai_proxy_password').val();
|
||||
|
||||
setProxyPreset(presetName, reverseProxy, proxyPassword);
|
||||
saveSettingsDebounced();
|
||||
toastr.success('Proxy Saved');
|
||||
if($('#openai_proxy_preset').val() !== presetName) {
|
||||
const option = document.createElement('option');
|
||||
option.text = presetName;
|
||||
option.value = presetName;
|
||||
|
||||
$('#openai_proxy_preset').append(option);
|
||||
}
|
||||
$('#openai_proxy_preset').val(presetName);
|
||||
});
|
||||
|
||||
$('#delete_proxy').on('click', async function () {
|
||||
const presetName = $('#openai_reverse_proxy_name').val();
|
||||
const index = proxies.findIndex(preset => preset.name === presetName);
|
||||
|
||||
if (index !== -1) {
|
||||
proxies.splice(index, 1);
|
||||
$('#openai_proxy_preset option[value="' + presetName + '"]').remove();
|
||||
|
||||
if (proxies.length > 0) {
|
||||
const newIndex = Math.max(0, index - 1);
|
||||
selected_proxy = proxies[newIndex];
|
||||
} else {
|
||||
selected_proxy = { name: 'None', url: '', password: '' };
|
||||
}
|
||||
|
||||
$('#openai_reverse_proxy_name').val(selected_proxy.name);
|
||||
oai_settings.reverse_proxy = selected_proxy.url;
|
||||
$('#openai_reverse_proxy').val(selected_proxy.url);
|
||||
oai_settings.proxy_password = selected_proxy.password;
|
||||
$('#openai_proxy_password').val(selected_proxy.password);
|
||||
|
||||
saveSettingsDebounced();
|
||||
$('#openai_proxy_preset').val(selected_proxy.name);
|
||||
toastr.success('Proxy Deleted');
|
||||
} else {
|
||||
toastr.error(`Could not find proxy with name "${presetName}"`);
|
||||
}
|
||||
});
|
||||
|
||||
$(document).ready(async function () {
|
||||
$('#test_api_button').on('click', testApiConnection);
|
||||
|
||||
@@ -4183,4 +4296,5 @@ $(document).ready(async function () {
|
||||
$('#import_oai_preset').on('click', onImportPresetClick);
|
||||
$('#openai_proxy_password_show').on('click', onProxyPasswordShowClick);
|
||||
$('#customize_additional_parameters').on('click', onCustomizeParametersClick);
|
||||
$('#openai_proxy_preset').on('change', onProxyPresetChange);
|
||||
});
|
||||
|
@@ -11,6 +11,7 @@ import {
|
||||
name1,
|
||||
saveMetadata,
|
||||
saveSettingsDebounced,
|
||||
setUserAvatar,
|
||||
setUserName,
|
||||
this_chid,
|
||||
user_avatar,
|
||||
@@ -20,6 +21,13 @@ import { persona_description_positions, power_user } from './power-user.js';
|
||||
import { getTokenCount } from './tokenizers.js';
|
||||
import { debounce, delay, download, parseJsonFile } from './utils.js';
|
||||
|
||||
const GRID_STORAGE_KEY = 'Personas_GridView';
|
||||
|
||||
function switchPersonaGridView() {
|
||||
const state = localStorage.getItem(GRID_STORAGE_KEY) === 'true';
|
||||
$('#user_avatar_block').toggleClass('gridView', state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads an avatar file to the server
|
||||
* @param {string} url URL for the avatar file
|
||||
@@ -46,7 +54,7 @@ async function uploadUserAvatar(url, name) {
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: async function () {
|
||||
await getUserAvatars();
|
||||
await getUserAvatars(true, name);
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -156,7 +164,7 @@ export async function convertCharacterToPersona(characterId = null) {
|
||||
toastr.success(`You can now select ${name} as a persona in the Persona Management menu.`, 'Persona Created');
|
||||
|
||||
// Refresh the persona selector
|
||||
await getUserAvatars();
|
||||
await getUserAvatars(true, overwriteName);
|
||||
// Reload the persona description
|
||||
setPersonaDescription();
|
||||
}
|
||||
@@ -187,7 +195,7 @@ export function autoSelectPersona(name) {
|
||||
for (const [key, value] of Object.entries(power_user.personas)) {
|
||||
if (value === name) {
|
||||
console.log(`Auto-selecting persona ${key} for name ${name}`);
|
||||
$(`.avatar[imgfile="${key}"]`).trigger('click');
|
||||
setUserAvatar(key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -201,7 +209,7 @@ export function autoSelectPersona(name) {
|
||||
export async function updatePersonaNameIfExists(avatarId, newName) {
|
||||
if (avatarId in power_user.personas) {
|
||||
power_user.personas[avatarId] = newName;
|
||||
await getUserAvatars();
|
||||
await getUserAvatars(true, avatarId);
|
||||
saveSettingsDebounced();
|
||||
console.log(`Updated persona name for ${avatarId} to ${newName}`);
|
||||
} else {
|
||||
@@ -209,7 +217,8 @@ export async function updatePersonaNameIfExists(avatarId, newName) {
|
||||
}
|
||||
}
|
||||
|
||||
async function bindUserNameToPersona() {
|
||||
async function bindUserNameToPersona(e) {
|
||||
e?.stopPropagation();
|
||||
const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile');
|
||||
|
||||
if (!avatarId) {
|
||||
@@ -254,7 +263,7 @@ async function bindUserNameToPersona() {
|
||||
}
|
||||
|
||||
saveSettingsDebounced();
|
||||
await getUserAvatars();
|
||||
await getUserAvatars(true, avatarId);
|
||||
setPersonaDescription();
|
||||
}
|
||||
|
||||
@@ -331,7 +340,8 @@ async function lockUserNameToChat() {
|
||||
updateUserLockIcon();
|
||||
}
|
||||
|
||||
async function deleteUserAvatar() {
|
||||
async function deleteUserAvatar(e) {
|
||||
e?.stopPropagation();
|
||||
const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile');
|
||||
|
||||
if (!avatarId) {
|
||||
@@ -400,6 +410,9 @@ function onPersonaDescriptionInput() {
|
||||
object.description = power_user.persona_description;
|
||||
}
|
||||
|
||||
$(`.avatar-container[imgfile="${user_avatar}"] .ch_description`)
|
||||
.text(power_user.persona_description || '[No description]')
|
||||
.toggleClass('text_muted', !power_user.persona_description);
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
@@ -425,7 +438,8 @@ function onPersonaDescriptionPositionInput() {
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
async function setDefaultPersona() {
|
||||
async function setDefaultPersona(e) {
|
||||
e?.stopPropagation();
|
||||
const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile');
|
||||
|
||||
if (!avatarId) {
|
||||
@@ -472,7 +486,7 @@ async function setDefaultPersona() {
|
||||
}
|
||||
|
||||
saveSettingsDebounced();
|
||||
await getUserAvatars();
|
||||
await getUserAvatars(true, avatarId);
|
||||
}
|
||||
|
||||
function updateUserLockIcon() {
|
||||
@@ -481,7 +495,7 @@ function updateUserLockIcon() {
|
||||
$('#lock_user_name').toggleClass('fa-lock', hasLock);
|
||||
}
|
||||
|
||||
function setChatLockedPersona() {
|
||||
async function setChatLockedPersona() {
|
||||
// Define a persona for this chat
|
||||
let chatPersona = '';
|
||||
|
||||
@@ -502,10 +516,10 @@ function setChatLockedPersona() {
|
||||
}
|
||||
|
||||
// Find the avatar file
|
||||
const personaAvatar = $(`.avatar[imgfile="${chatPersona}"]`).trigger('click');
|
||||
const userAvatars = await getUserAvatars(false);
|
||||
|
||||
// Avatar missing (persona deleted)
|
||||
if (chat_metadata['persona'] && personaAvatar.length == 0) {
|
||||
if (chat_metadata['persona'] && !userAvatars.includes(chatPersona)) {
|
||||
console.warn('Persona avatar not found, unlocking persona');
|
||||
delete chat_metadata['persona'];
|
||||
updateUserLockIcon();
|
||||
@@ -513,7 +527,7 @@ function setChatLockedPersona() {
|
||||
}
|
||||
|
||||
// Default persona missing
|
||||
if (power_user.default_persona && personaAvatar.length == 0) {
|
||||
if (power_user.default_persona && !userAvatars.includes(power_user.default_persona)) {
|
||||
console.warn('Default persona avatar not found, clearing default persona');
|
||||
power_user.default_persona = null;
|
||||
saveSettingsDebounced();
|
||||
@@ -521,7 +535,7 @@ function setChatLockedPersona() {
|
||||
}
|
||||
|
||||
// Persona avatar found, select it
|
||||
personaAvatar.trigger('click');
|
||||
setUserAvatar(chatPersona);
|
||||
updateUserLockIcon();
|
||||
}
|
||||
|
||||
@@ -560,7 +574,7 @@ async function onPersonasRestoreInput(e) {
|
||||
return;
|
||||
}
|
||||
|
||||
const avatarsList = await getUserAvatars();
|
||||
const avatarsList = await getUserAvatars(false);
|
||||
const warnings = [];
|
||||
|
||||
// Merge personas with existing ones
|
||||
@@ -626,6 +640,16 @@ export function initPersonas() {
|
||||
$('#personas_backup').on('click', onBackupPersonas);
|
||||
$('#personas_restore').on('click', () => $('#personas_restore_input').trigger('click'));
|
||||
$('#personas_restore_input').on('change', onPersonasRestoreInput);
|
||||
$('#persona_sort_order').val(power_user.persona_sort_order).on('input', function () {
|
||||
power_user.persona_sort_order = String($(this).val());
|
||||
getUserAvatars(true, user_avatar);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$('#persona_grid_toggle').on('click', () => {
|
||||
const state = localStorage.getItem(GRID_STORAGE_KEY) === 'true';
|
||||
localStorage.setItem(GRID_STORAGE_KEY, String(!state));
|
||||
switchPersonaGridView();
|
||||
});
|
||||
|
||||
eventSource.on('charManagementDropdown', (target) => {
|
||||
if (target === 'convert_to_persona') {
|
||||
@@ -633,4 +657,5 @@ export function initPersonas() {
|
||||
}
|
||||
});
|
||||
eventSource.on(event_types.CHAT_CHANGED, setChatLockedPersona);
|
||||
switchPersonaGridView();
|
||||
}
|
||||
|
@@ -225,6 +225,7 @@ let power_user = {
|
||||
persona_description: '',
|
||||
persona_description_position: persona_description_positions.IN_PROMPT,
|
||||
persona_show_notifications: true,
|
||||
persona_sort_order: 'asc',
|
||||
|
||||
custom_stopping_strings: '',
|
||||
custom_stopping_strings_macro: true,
|
||||
@@ -501,6 +502,11 @@ async function switchLabMode() {
|
||||
$('#labModeWarning').removeClass('displayNone');
|
||||
//$("#advanced-ai-config-block input[type='range']").hide()
|
||||
|
||||
$('#amount_gen').attr('min', '1')
|
||||
.attr('max', '99999')
|
||||
.attr('step', '1');
|
||||
|
||||
|
||||
} else {
|
||||
//re apply the original sliders values to each input
|
||||
originalSliderValues.forEach(function (slider) {
|
||||
@@ -512,6 +518,10 @@ async function switchLabMode() {
|
||||
});
|
||||
$('#advanced-ai-config-block input[type=\'range\']').show();
|
||||
$('#labModeWarning').addClass('displayNone');
|
||||
|
||||
$('#amount_gen').attr('min', '16')
|
||||
.attr('max', '2048')
|
||||
.attr('step', '1');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,7 +621,9 @@ async function CreateZenSliders(elmnt) {
|
||||
decimals = 0;
|
||||
}
|
||||
if (sliderID == 'min_temp_textgenerationwebui' ||
|
||||
sliderID == 'max_temp_textgenerationwebui') {
|
||||
sliderID == 'max_temp_textgenerationwebui' ||
|
||||
sliderID == 'dynatemp_exponent_textgenerationwebui' ||
|
||||
sliderID == 'smoothing_factor_textgenerationwebui') {
|
||||
decimals = 2;
|
||||
}
|
||||
if (sliderID == 'eta_cutoff_textgenerationwebui' ||
|
||||
@@ -1828,6 +1840,23 @@ export function fuzzySearchWorldInfo(data, searchValue) {
|
||||
return results.map(x => x.item?.uid);
|
||||
}
|
||||
|
||||
export function fuzzySearchPersonas(data, searchValue) {
|
||||
data = data.map(x => ({ key: x, description: power_user.persona_descriptions[x]?.description ?? '', name: power_user.personas[x] ?? '' }));
|
||||
const fuse = new Fuse(data, {
|
||||
keys: [
|
||||
{ name: 'name', weight: 4 },
|
||||
{ name: 'description', weight: 1 },
|
||||
],
|
||||
includeScore: true,
|
||||
ignoreLocation: true,
|
||||
threshold: 0.2,
|
||||
});
|
||||
|
||||
const results = fuse.search(searchValue);
|
||||
console.debug('Personas fuzzy search results for ' + searchValue, results);
|
||||
return results.map(x => x.item?.key);
|
||||
}
|
||||
|
||||
export function fuzzySearchTags(searchValue) {
|
||||
const fuse = new Fuse(tags, {
|
||||
keys: [
|
||||
|
@@ -79,6 +79,8 @@ const settings = {
|
||||
dynatemp: false,
|
||||
min_temp: 0,
|
||||
max_temp: 2.0,
|
||||
dynatemp_exponent: 1.0,
|
||||
smoothing_factor: 0.0,
|
||||
seed: -1,
|
||||
preset: 'Default',
|
||||
add_bos_token: true,
|
||||
@@ -140,6 +142,8 @@ const setting_names = [
|
||||
'dynatemp',
|
||||
'min_temp',
|
||||
'max_temp',
|
||||
'dynatemp_exponent',
|
||||
'smoothing_factor',
|
||||
'encoder_rep_pen',
|
||||
'freq_pen',
|
||||
'presence_pen',
|
||||
@@ -714,7 +718,7 @@ function parseTextgenLogprobs(token, logprobs) {
|
||||
switch (settings.type) {
|
||||
case APHRODITE:
|
||||
case OOBA: {
|
||||
/** @type {Record<string, number>[]} */
|
||||
/** @type {Record<string, number>[]} */
|
||||
const topLogprobs = logprobs.top_logprobs;
|
||||
if (!topLogprobs?.length) {
|
||||
return null;
|
||||
@@ -799,7 +803,7 @@ export function getTextGenGenerationData(finalPrompt, maxTokens, isImpersonate,
|
||||
'model': getModel(),
|
||||
'max_new_tokens': maxTokens,
|
||||
'max_tokens': maxTokens,
|
||||
'logprobs': power_user.request_token_probabilities ? 10: undefined,
|
||||
'logprobs': power_user.request_token_probabilities ? 10 : undefined,
|
||||
'temperature': settings.dynatemp ? (settings.min_temp + settings.max_temp) / 2 : settings.temp,
|
||||
'top_p': settings.top_p,
|
||||
'typical_p': settings.typical_p,
|
||||
@@ -818,6 +822,8 @@ export function getTextGenGenerationData(finalPrompt, maxTokens, isImpersonate,
|
||||
'dynatemp_low': settings.min_temp,
|
||||
'dynatemp_high': settings.max_temp,
|
||||
'dynatemp_range': settings.dynatemp ? (settings.max_temp - settings.min_temp) / 2 : 0,
|
||||
'dynatemp_exponent': settings.dynatemp_exponent,
|
||||
'smoothing_factor': settings.smoothing_factor,
|
||||
'stopping_strings': getStoppingStrings(isImpersonate, isContinue),
|
||||
'stop': getStoppingStrings(isImpersonate, isContinue),
|
||||
'truncation_length': max_context,
|
||||
@@ -864,6 +870,7 @@ export function getTextGenGenerationData(finalPrompt, maxTokens, isImpersonate,
|
||||
'best_of': canMultiSwipe ? settings.n : 1,
|
||||
'ignore_eos': settings.ignore_eos_token_aphrodite,
|
||||
'spaces_between_special_tokens': settings.spaces_between_special_tokens_aphrodite,
|
||||
'grammar': settings.grammar_string,
|
||||
//'logits_processors': settings.logits_processors_aphrodite,
|
||||
//'logprobs': settings.log_probs_aphrodite,
|
||||
//'prompt_logprobs': settings.prompt_log_probs_aphrodite,
|
||||
|
@@ -35,7 +35,7 @@ export const SENTENCEPIECE_TOKENIZERS = [
|
||||
//tokenizers.NERD2,
|
||||
];
|
||||
|
||||
export const TEXTGEN_TOKENIZERS = [OOBA, TABBY, KOBOLDCPP, LLAMACPP];
|
||||
export const TEXTGEN_TOKENIZERS = [OOBA, TABBY, KOBOLDCPP, LLAMACPP, APHRODITE];
|
||||
|
||||
const TOKENIZER_URLS = {
|
||||
[tokenizers.GPT2]: {
|
||||
|
Reference in New Issue
Block a user