mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Add v3 writing and decorators
This commit is contained in:
@ -108,6 +108,7 @@ const METADATA_KEY = 'world_info';
|
|||||||
const DEFAULT_DEPTH = 4;
|
const DEFAULT_DEPTH = 4;
|
||||||
const DEFAULT_WEIGHT = 100;
|
const DEFAULT_WEIGHT = 100;
|
||||||
const MAX_SCAN_DEPTH = 1000;
|
const MAX_SCAN_DEPTH = 1000;
|
||||||
|
const KNOWN_DECORATORS = ['@@activate', '@@dont_activate']
|
||||||
|
|
||||||
// Typedef area
|
// Typedef area
|
||||||
/**
|
/**
|
||||||
@ -3531,6 +3532,61 @@ export async function getSortedEntries() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse decorators from worldinfo content
|
||||||
|
* @param {string} content The content to parse
|
||||||
|
* @returns {[string[],string]} The decorators found in the content and the content without decorators
|
||||||
|
*/
|
||||||
|
function parseDecorators(content){
|
||||||
|
/**
|
||||||
|
* Check if the decorator is known
|
||||||
|
* @param {string} data string to check
|
||||||
|
* @returns {boolean} true if the decorator is known
|
||||||
|
*/
|
||||||
|
const isKnownDecorator = (data) => {
|
||||||
|
if(data.startsWith('@@@')){
|
||||||
|
data = data.substring(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let i = 0; i<KNOWN_DECORATORS.length;i++){
|
||||||
|
if(data.startsWith(KNOWN_DECORATORS[i])){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if(content.startsWith('@@')){
|
||||||
|
let newContent = content;
|
||||||
|
const splited = content.split('\n');
|
||||||
|
let decorators = []
|
||||||
|
let fallbacked = false;
|
||||||
|
|
||||||
|
for (let i = 0; i < splited.length; i++) {
|
||||||
|
if(splited[i].startsWith('@@')){
|
||||||
|
if(splited[i].startsWith('@@@') && !fallbacked){
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isKnownDecorator(splited[i])){
|
||||||
|
decorators.push(splited[i].startsWith('@@@') ? splited[i].substring(1) : splited[i])
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
fallbacked = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newContent = splited.slice(i).join('\n');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [decorators, newContent]
|
||||||
|
}
|
||||||
|
|
||||||
|
return [[], content]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a scan on the chat and returns the world info activated.
|
* Performs a scan on the chat and returns the world info activated.
|
||||||
* @param {string[]} chat The chat messages to scan, in reverse order.
|
* @param {string[]} chat The chat messages to scan, in reverse order.
|
||||||
@ -3588,6 +3644,20 @@ async function checkWorldInfo(chat, maxContext, isDryRun) {
|
|||||||
let activatedNow = new Set();
|
let activatedNow = new Set();
|
||||||
|
|
||||||
for (let entry of sortedEntries) {
|
for (let entry of sortedEntries) {
|
||||||
|
|
||||||
|
//oarse decorators
|
||||||
|
const [decorators] = parseDecorators(entry.content);
|
||||||
|
if(decorators.includes('@@activate')){
|
||||||
|
//activate in any case
|
||||||
|
activatedNow.add(entry);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(decorators.includes('@@dont_activate')){
|
||||||
|
//deactivate in any case if @@activate is not present
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if this entry applies to the character or if it's excluded
|
// Check if this entry applies to the character or if it's excluded
|
||||||
if (entry.characterFilter && entry.characterFilter?.names?.length > 0) {
|
if (entry.characterFilter && entry.characterFilter?.names?.length > 0) {
|
||||||
const nameIncluded = entry.characterFilter.names.includes(getCharaFilename());
|
const nameIncluded = entry.characterFilter.names.includes(getCharaFilename());
|
||||||
@ -3656,6 +3726,7 @@ async function checkWorldInfo(chat, maxContext, isDryRun) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (Array.isArray(entry.key) && entry.key.length) { //check for keywords existing
|
if (Array.isArray(entry.key) && entry.key.length) { //check for keywords existing
|
||||||
// If selectiveLogic isn't found, assume it's AND, only do this once per entry
|
// If selectiveLogic isn't found, assume it's AND, only do this once per entry
|
||||||
const selectiveLogic = entry.selectiveLogic ?? 0;
|
const selectiveLogic = entry.selectiveLogic ?? 0;
|
||||||
@ -3748,7 +3819,7 @@ async function checkWorldInfo(chat, maxContext, isDryRun) {
|
|||||||
} else { console.debug(`uid:${entry.uid} passed probability check, inserting to prompt`); }
|
} else { console.debug(`uid:${entry.uid} passed probability check, inserting to prompt`); }
|
||||||
|
|
||||||
// Substitute macros inline, for both this checking and also future processing
|
// Substitute macros inline, for both this checking and also future processing
|
||||||
entry.content = substituteParams(entry.content);
|
entry.content = substituteParams(parseDecorators(entry.content)[1]);
|
||||||
newContent += `${entry.content}\n`;
|
newContent += `${entry.content}\n`;
|
||||||
|
|
||||||
if ((textToScanTokens + (await getTokenCountAsync(newContent))) >= budget) {
|
if ((textToScanTokens + (await getTokenCountAsync(newContent))) >= budget) {
|
||||||
|
@ -23,9 +23,24 @@ const write = (image, data) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add new chunks before the IEND chunk
|
// Add new v2 chunk before the IEND chunk
|
||||||
const base64EncodedData = Buffer.from(data, 'utf8').toString('base64');
|
const base64EncodedData = Buffer.from(data, 'utf8').toString('base64');
|
||||||
chunks.splice(-1, 0, PNGtext.encode('chara', base64EncodedData));
|
chunks.splice(-1, 0, PNGtext.encode('chara', base64EncodedData));
|
||||||
|
|
||||||
|
// Try adding v3 chunk before the IEND chunk
|
||||||
|
try {
|
||||||
|
//change v2 format to v3
|
||||||
|
const v3Data = JSON.parse(data);
|
||||||
|
v3Data.spec = 'chara_card_v3'
|
||||||
|
v3Data.spec_version = '3.0'
|
||||||
|
if(v3Data.data && !v3Data.data.group_only_greetings){
|
||||||
|
v3Data.data.group_only_greetings = []
|
||||||
|
}
|
||||||
|
|
||||||
|
const base64EncodedData = Buffer.from(JSON.stringify(v3Data), 'utf8').toString('base64');
|
||||||
|
chunks.splice(-1, 0, PNGtext.encode('ccv3', base64EncodedData));
|
||||||
|
} catch (error) {}
|
||||||
|
|
||||||
const newBuffer = Buffer.from(encode(chunks));
|
const newBuffer = Buffer.from(encode(chunks));
|
||||||
return newBuffer;
|
return newBuffer;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user