mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-02-21 22:47:41 +01:00
Merge branch 'staging' into parser-followup-2
This commit is contained in:
commit
8a55d64158
@ -17,6 +17,15 @@ module.exports = {
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['src/**/*.mjs'],
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
},
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
// Browser-side files
|
||||
files: ['public/**/*.js'],
|
||||
|
@ -2264,6 +2264,7 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll
|
||||
|
||||
if (type === 'swipe') {
|
||||
const swipeMessage = chatElement.find(`[mesid="${chat.length - 1}"]`);
|
||||
swipeMessage.attr('swipeid', params.swipeId);
|
||||
swipeMessage.find('.mes_text').html(messageText).attr('title', title);
|
||||
swipeMessage.find('.timestamp').text(timestamp).attr('title', `${params.extra.api} - ${params.extra.model}`);
|
||||
appendMediaToMessage(mes, swipeMessage);
|
||||
@ -4182,6 +4183,8 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
||||
summarizeString: (extension_prompts['1_memory']?.value || ''),
|
||||
authorsNoteString: (extension_prompts['2_floating_prompt']?.value || ''),
|
||||
smartContextString: (extension_prompts['chromadb']?.value || ''),
|
||||
chatVectorsString: (extension_prompts['3_vectors']?.value || ''),
|
||||
dataBankVectorsString: (extension_prompts['4_vectors_data_bank']?.value || ''),
|
||||
worldInfoString: worldInfoString,
|
||||
storyString: storyString,
|
||||
beforeScenarioAnchor: beforeScenarioAnchor,
|
||||
@ -4813,6 +4816,8 @@ export async function itemizedParams(itemizedPrompts, thisPromptSet) {
|
||||
thisPrompt_padding: itemizedPrompts[thisPromptSet].padding,
|
||||
this_main_api: itemizedPrompts[thisPromptSet].main_api,
|
||||
chatInjects: await getTokenCountAsync(itemizedPrompts[thisPromptSet].chatInjects),
|
||||
chatVectorsStringTokens: await getTokenCountAsync(itemizedPrompts[thisPromptSet].chatVectorsString),
|
||||
dataBankVectorsStringTokens: await getTokenCountAsync(itemizedPrompts[thisPromptSet].dataBankVectorsString),
|
||||
};
|
||||
|
||||
if (params.chatInjects) {
|
||||
|
@ -72,7 +72,7 @@ const registerPromptManagerMigration = () => {
|
||||
* Represents a prompt.
|
||||
*/
|
||||
class Prompt {
|
||||
identifier; role; content; name; system_prompt; position; injection_position; injection_depth; forbid_overrides;
|
||||
identifier; role; content; name; system_prompt; position; injection_position; injection_depth; forbid_overrides; extension;
|
||||
|
||||
/**
|
||||
* Create a new Prompt instance.
|
||||
@ -87,8 +87,9 @@ class Prompt {
|
||||
* @param {number} param0.injection_position - The insert position of the prompt.
|
||||
* @param {number} param0.injection_depth - The depth of the prompt in the chat.
|
||||
* @param {boolean} param0.forbid_overrides - Indicates if the prompt should not be overridden.
|
||||
* @param {boolean} param0.extension - Prompt is added by an extension.
|
||||
*/
|
||||
constructor({ identifier, role, content, name, system_prompt, position, injection_depth, injection_position, forbid_overrides } = {}) {
|
||||
constructor({ identifier, role, content, name, system_prompt, position, injection_depth, injection_position, forbid_overrides, extension } = {}) {
|
||||
this.identifier = identifier;
|
||||
this.role = role;
|
||||
this.content = content;
|
||||
@ -98,6 +99,7 @@ class Prompt {
|
||||
this.injection_depth = injection_depth;
|
||||
this.injection_position = injection_position;
|
||||
this.forbid_overrides = forbid_overrides;
|
||||
this.extension = extension ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,8 +23,7 @@ import { debounce_timeout } from '../../constants.js';
|
||||
import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
|
||||
import { SlashCommand } from '../../slash-commands/SlashCommand.js';
|
||||
import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js';
|
||||
import { resolveVariable } from '../../variables.js';
|
||||
import { commonEnumProviders } from '../../slash-commands/SlashCommandCommonEnumsProvider.js';
|
||||
import { MacrosParser } from '../../macros.js';
|
||||
export { MODULE_NAME };
|
||||
|
||||
const MODULE_NAME = '1_memory';
|
||||
@ -937,4 +936,6 @@ jQuery(async function () {
|
||||
helpString: 'Summarizes the given text. If no text is provided, the current chat will be summarized. Can specify the source and the prompt to use.',
|
||||
returns: ARGUMENT_TYPE.STRING,
|
||||
}));
|
||||
|
||||
MacrosParser.registerMacro('summary', () => getLatestMemoryFromChat(getContext().chat));
|
||||
});
|
||||
|
@ -1082,6 +1082,11 @@ async function populateChatCompletion(prompts, chatCompletion, { bias, quietProm
|
||||
}
|
||||
}
|
||||
|
||||
// Other relative extension prompts
|
||||
for (const prompt of prompts.collection.filter(p => p.extension && p.position)) {
|
||||
chatCompletion.insert(Message.fromPrompt(prompt), 'main', prompt.position);
|
||||
}
|
||||
|
||||
// Add in-chat injections
|
||||
messages = populationInjectionPrompts(userAbsolutePrompts, messages);
|
||||
|
||||
@ -1187,6 +1192,35 @@ function preparePromptsForChatCompletion({ Scenario, charPersonality, name2, wor
|
||||
systemPrompts.push({ role: 'system', content: power_user.persona_description, identifier: 'personaDescription' });
|
||||
}
|
||||
|
||||
const knownExtensionPrompts = [
|
||||
'1_memory',
|
||||
'2_floating_prompt',
|
||||
'3_vectors',
|
||||
'4_vectors_data_bank',
|
||||
'chromadb',
|
||||
'PERSONA_DESCRIPTION',
|
||||
'QUIET_PROMPT',
|
||||
'DEPTH_PROMPT',
|
||||
];
|
||||
|
||||
// Anything that is not a known extension prompt
|
||||
for (const key in extensionPrompts) {
|
||||
if (Object.hasOwn(extensionPrompts, key)) {
|
||||
const prompt = extensionPrompts[key];
|
||||
if (knownExtensionPrompts.includes(key)) continue;
|
||||
if (!extensionPrompts[key].value) continue;
|
||||
if (![extension_prompt_types.BEFORE_PROMPT, extension_prompt_types.IN_PROMPT].includes(prompt.position)) continue;
|
||||
|
||||
systemPrompts.push({
|
||||
identifier: key.replace(/\W/g, '_'),
|
||||
position: getPromptPosition(prompt.position),
|
||||
role: getPromptRole(prompt.role),
|
||||
content: prompt.value,
|
||||
extension: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// This is the prompt order defined by the user
|
||||
const prompts = promptManager.getPromptCollection();
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
<h3 class="flex-container justifyCenter alignitemscenter">
|
||||
Prompt Itemization
|
||||
<div id="showRawPrompt" class="fa-solid fa-square-poll-horizontal menu_button"></div>
|
||||
<div id="copyPromptToClipboard" class="fa-solid fa-copy menu_button"></div>
|
||||
<div id="diffPrevPrompt" class="fa-solid fa-code-compare menu_button"></div>
|
||||
<div id="showRawPrompt" class="fa-solid fa-square-poll-horizontal menu_button" title="Show Raw Prompt" data-i18n="[title]Show Raw Prompt"></div>
|
||||
<div id="copyPromptToClipboard" class="fa-solid fa-copy menu_button" title="Copy Prompt" data-i18n="[title]Copy Prompt"></div>
|
||||
<div id="diffPrevPrompt" class="fa-solid fa-code-compare menu_button" title="Show Prompt Differences" data-i18n="[title]Show Prompt Differences"></div>
|
||||
</h3>
|
||||
Tokenizer: {{selectedTokenizer}}<br>
|
||||
API Used: {{this_main_api}}<br>
|
||||
@ -107,6 +107,14 @@ API Used: {{this_main_api}}<br>
|
||||
<div class=" flex1 tokenItemizingSubclass">-- Smart Context:</div>
|
||||
<div class="tokenItemizingSubclass"> {{smartContextStringTokens}}</div>
|
||||
</div>
|
||||
<div class="flex-container ">
|
||||
<div class=" flex1 tokenItemizingSubclass">-- Vector Storage (Chats):</div>
|
||||
<div class="tokenItemizingSubclass"> {{chatVectorsStringTokens}}</div>
|
||||
</div>
|
||||
<div class="flex-container ">
|
||||
<div class=" flex1 tokenItemizingSubclass">-- Vector Storage (Data Bank):</div>
|
||||
<div class="tokenItemizingSubclass"> {{dataBankVectorsStringTokens}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wide100p flex-container">
|
||||
<div class="flex1" style="color: mediumpurple;">{{}} Bias:</div>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<h3 class="flex-container justifyCenter alignitemscenter">
|
||||
Prompt Itemization
|
||||
<div id="showRawPrompt" class="fa-solid fa-square-poll-horizontal menu_button"></div>
|
||||
<div id="copyPromptToClipboard" class="fa-solid fa-copy menu_button"></div>
|
||||
<div id="diffPrevPrompt" class="fa-solid fa-code-compare menu_button"></div>
|
||||
<div id="showRawPrompt" class="fa-solid fa-square-poll-horizontal menu_button" title="Show Raw Prompt" data-i18n="[title]Show Raw Prompt"></div>
|
||||
<div id="copyPromptToClipboard" class="fa-solid fa-copy menu_button" title="Copy Prompt" data-i18n="[title]Copy Prompt"></div>
|
||||
<div id="diffPrevPrompt" class="fa-solid fa-code-compare menu_button" title="Show Prompt Differences" data-i18n="[title]Show Prompt Differences"></div>
|
||||
</h3>
|
||||
Tokenizer: {{selectedTokenizer}}<br>
|
||||
API Used: {{this_main_api}}<br>
|
||||
@ -79,6 +79,14 @@ API Used: {{this_main_api}}<br>
|
||||
<div class=" flex1 tokenItemizingSubclass">-- Smart Context:</div>
|
||||
<div class="tokenItemizingSubclass"> {{smartContextStringTokens}}</div>
|
||||
</div>
|
||||
<div class="flex-container ">
|
||||
<div class=" flex1 tokenItemizingSubclass">-- Vector Storage (Chats):</div>
|
||||
<div class="tokenItemizingSubclass"> {{chatVectorsStringTokens}}</div>
|
||||
</div>
|
||||
<div class="flex-container ">
|
||||
<div class=" flex1 tokenItemizingSubclass">-- Vector Storage (Data Bank):</div>
|
||||
<div class="tokenItemizingSubclass"> {{dataBankVectorsStringTokens}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wide100p flex-container">
|
||||
<div class="flex1" style="color: mediumpurple;">{{}} Bias:</div>
|
||||
|
@ -16,6 +16,7 @@
|
||||
<li><tt>{{persona}}</tt> – <span data-i18n="help_macros_12">your current Persona Description</span></li>
|
||||
<li><tt>{{mesExamples}}</tt> – <span data-i18n="help_macros_13">the Character's Dialogue Examples</span></li>
|
||||
<li><tt>{{mesExamplesRaw}}</tt> – <span data-i18n="help_macros_14">unformatted Dialogue Examples </span><b data-i18n="(only for Story String)">(only for Story String)</b></li>
|
||||
<li><tt>{{summary}}</tt> – <span data-i18n="help_macros_summary">the latest chat summary generated by the "Summarize" extension (if available).</span></li>
|
||||
<li><tt>{{user}}</tt> – <span data-i18n="help_macros_15">your current Persona username</span></li>
|
||||
<li><tt>{{char}}</tt> – <span data-i18n="help_macros_16">the Character's name</span></li>
|
||||
<li><tt>{{char_version}}</tt> – <span data-i18n="help_macros_17">the Character's version number</span></li>
|
||||
|
@ -16,7 +16,10 @@ const STATS_FILE = 'stats.json';
|
||||
* @type {Map<string, Object>} The stats object for each user.
|
||||
*/
|
||||
const STATS = new Map();
|
||||
let lastSaveTimestamp = 0;
|
||||
/**
|
||||
* @type {Map<string, number>} The timestamps for each user.
|
||||
*/
|
||||
const TIMESTAMPS = new Map();
|
||||
|
||||
/**
|
||||
* Convert a timestamp to an integer timestamp.
|
||||
@ -119,7 +122,6 @@ function timestampToMoment(timestamp) {
|
||||
* @returns {Promise<Object>} The aggregated stats object.
|
||||
*/
|
||||
async function collectAndCreateStats(chatsPath, charactersPath) {
|
||||
console.log('Collecting and creating stats...');
|
||||
const files = await readdir(charactersPath);
|
||||
|
||||
const pngFiles = files.filter((file) => file.endsWith('.png'));
|
||||
@ -145,10 +147,10 @@ async function collectAndCreateStats(chatsPath, charactersPath) {
|
||||
* @param {string} charactersPath Path to the directory containing the character files.
|
||||
*/
|
||||
async function recreateStats(handle, chatsPath, charactersPath) {
|
||||
console.log('Collecting and creating stats for user:', handle);
|
||||
const stats = await collectAndCreateStats(chatsPath, charactersPath);
|
||||
STATS.set(handle, stats);
|
||||
await saveStatsToFile();
|
||||
console.debug('Stats (re)created and saved to file.');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,7 +169,7 @@ async function init() {
|
||||
} catch (err) {
|
||||
// If the file doesn't exist or is invalid, initialize stats
|
||||
if (err.code === 'ENOENT' || err instanceof SyntaxError) {
|
||||
recreateStats(handle, directories.chats, directories.characters);
|
||||
await recreateStats(handle, directories.chats, directories.characters);
|
||||
} else {
|
||||
throw err; // Rethrow the error if it's something we didn't expect
|
||||
}
|
||||
@ -185,13 +187,17 @@ async function init() {
|
||||
async function saveStatsToFile() {
|
||||
const userHandles = await getAllUserHandles();
|
||||
for (const handle of userHandles) {
|
||||
const charStats = STATS.get(handle) || {};
|
||||
if (!STATS.has(handle)) {
|
||||
continue;
|
||||
}
|
||||
const charStats = STATS.get(handle);
|
||||
const lastSaveTimestamp = TIMESTAMPS.get(handle) || 0;
|
||||
if (charStats.timestamp > lastSaveTimestamp) {
|
||||
try {
|
||||
const directories = getUserDirectories(handle);
|
||||
const statsFilePath = path.join(directories.root, STATS_FILE);
|
||||
await writeFileAtomic(statsFilePath, JSON.stringify(charStats));
|
||||
lastSaveTimestamp = Date.now();
|
||||
TIMESTAMPS.set(handle, Date.now());
|
||||
} catch (error) {
|
||||
console.log('Failed to save stats to file.', error);
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { pipeline, env, RawImage, Pipeline } from 'sillytavern-transformers';
|
||||
import { getConfigValue } from './util.js';
|
||||
import path from 'path';
|
||||
import _ from 'lodash';
|
||||
|
||||
configureTransformers();
|
||||
|
||||
@ -114,4 +113,4 @@ async function getPipeline(task, forceModel = '') {
|
||||
export default {
|
||||
getPipeline,
|
||||
getRawImage,
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user