Merge pull request #2147 from Wolfsblvt/wi-entry-inclusion-prio

World Info inclusion group prio toggle
This commit is contained in:
Cohee 2024-04-27 21:09:43 +03:00 committed by GitHub
commit 404d9db359
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 63 additions and 18 deletions

View File

@ -5196,7 +5196,7 @@
<small for="characterFilter" data-i18n="Filter to Character(s)">
Filter to Character(s)
</small>
<label class="checkbox_label flexNoGap">
<label class="checkbox_label flexNoGap margin-r5" for="character_exclusion">
<input type="checkbox" name="character_exclusion" />
<span>
<small data-i18n="Character Exclusion">Character Exclusion</small>
@ -5212,12 +5212,27 @@
</div>
</div>
<div class="flex1 flex-container flexFlowColumn flexNoGap">
<label for="group">
<small data-i18n="Inclusion Group">
<div class="flex-container justifySpaceBetween">
<small for="group" data-i18n="Inclusion Group">
Inclusion Group
<a href="https://docs.sillytavern.app/usage/core-concepts/worldinfo/#inclusion-group" class="notes-link" target="_blank"
title="Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered.&#13;&#13;Documentation: World Info - Inclusion Group" data-i18n="[title]Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered.&#13;&#13;Documentation: World Info - Inclusion Group">
<span class="fa-solid fa-circle-question note-link-span"></span>
</a>
</small>
</label>
<input type="text" class="text_pole" name="group" rows="1" data-i18n="[placeholder]Only one entry with the same label will be activated" placeholder="Only one entry with the same label will be activated">
<label class="checkbox_label flexNoGap margin-r5" for="groupOverride">
<input type="checkbox" name="groupOverride" />
<span>
<small data-i18n="Prioritize Inclusion" title="Prioritize this entry: When checked, this entry is prioritized out of all selections.&#13;If multiple are prioritized, the one with the highest 'Order' is chosen.&#13;" data-i18n="[title]Prioritize this entry: When checked, this entry is prioritized out of all selections.&#13;If multiple are prioritized, the one with the highest 'Order' is chosen.">
Prioritize Inclusion
<div class="fa-solid fa-circle-info opacity50p"></div>
</small>
</span>
</label>
</div>
<div class="range-block-range">
<input type="text" class="text_pole margin0" name="group" rows="1" data-i18n="[placeholder]Only one entry with the same label will be activated" placeholder="Only one entry with the same label will be activated">
</div>
</div>
</div>
<div name="WIEntryBottomControls" class="flex-container flex1 justifySpaceBetween world_entry_form_horizontal">

View File

@ -992,6 +992,7 @@ const originalDataKeyMap = {
'scanDepth': 'extensions.scan_depth',
'automationId': 'extensions.automation_id',
'vectorized': 'extensions.vectorized',
'groupOverride': 'extensions.group_override',
};
function setOriginalDataValue(data, uid, key, value) {
@ -1338,6 +1339,18 @@ function getWorldEntry(name, data, entry) {
groupInput.val(entry.group ?? '').trigger('input');
setTimeout(() => createEntryInputAutocomplete(groupInput, getInclusionGroupCallback(data)), 1);
// inclusion priority
const groupOverrideInput = template.find('input[name="groupOverride"]');
groupOverrideInput.data('uid', entry.uid);
groupOverrideInput.on('input', function () {
const uid = $(this).data('uid');
const value = $(this).prop('checked');
data.entries[uid].groupOverride = value;
setOriginalDataValue(data, uid, 'extensions.groupOverride', data.entries[uid].groupOverride);
saveWorldInfo(name, data);
});
groupOverrideInput.prop('checked', entry.groupOverride).trigger('input');
// probability
if (entry.probability === undefined) {
entry.probability = null;
@ -1824,6 +1837,7 @@ const newEntryTemplate = {
useProbability: true,
depth: DEFAULT_DEPTH,
group: '',
groupOverride: false,
scanDepth: null,
caseSensitive: null,
matchWholeWords: null,
@ -2276,7 +2290,7 @@ async function checkWorldInfo(chat, maxContext) {
for (const entry of newEntries) {
const rollValue = Math.random() * 100;
if (entry.useProbability && rollValue > entry.probability) {
if (!entry.group && entry.useProbability && rollValue > entry.probability) {
console.debug(`WI entry ${entry.uid} ${entry.key} failed probability check, skipping`);
failedProbabilityChecks.add(entry);
continue;
@ -2410,15 +2424,25 @@ function filterByInclusionGroups(newEntries, allActivatedEntries) {
return;
}
const removeEntry = (entry) => newEntries.splice(newEntries.indexOf(entry), 1);
function removeAllBut(group, chosen, logging = true) {
for (const entry of group) {
if (entry === chosen) {
continue;
}
if (logging) console.debug(`Removing loser from inclusion group '${entry.group}' entry '${entry.uid}'`, entry);
removeEntry(entry);
}
}
for (const [key, group] of Object.entries(grouped)) {
console.debug(`Checking inclusion group '${key}' with ${group.length} entries`, group);
if (Array.from(allActivatedEntries).some(x => x.group === key)) {
console.debug(`Skipping inclusion group check, group already activated '${key}'`);
// We need to forcefully deactivate all other entries in the group
for (const entry of group) {
newEntries.splice(newEntries.indexOf(entry), 1);
}
removeAllBut(group, null, false);
continue;
}
@ -2427,6 +2451,14 @@ function filterByInclusionGroups(newEntries, allActivatedEntries) {
continue;
}
// Check for group prio
const prios = group.filter(x => x.groupOverride).sort(sortFn);
if (prios.length) {
console.debug(`Activated inclusion group '${key}' with by prio winner entry '${prios[0].uid}'`, prios[0]);
removeAllBut(group, prios[0]);
continue;
}
// Do weighted random using probability of entry as weight
const totalWeight = group.reduce((acc, item) => acc + item.probability, 0);
const rollValue = Math.random() * totalWeight;
@ -2437,7 +2469,7 @@ function filterByInclusionGroups(newEntries, allActivatedEntries) {
currentWeight += entry.probability;
if (rollValue <= currentWeight) {
console.debug(`Activated inclusion group '${key}' with entry '${entry.uid}'`, entry);
console.debug(`Activated inclusion group '${key}' with roll winner entry '${entry.uid}'`, entry);
winner = entry;
break;
}
@ -2449,14 +2481,7 @@ function filterByInclusionGroups(newEntries, allActivatedEntries) {
}
// Remove every group item from newEntries but the winner
for (const entry of group) {
if (entry === winner) {
continue;
}
console.debug(`Removing loser from inclusion group '${key}' entry '${entry.uid}'`, entry);
newEntries.splice(newEntries.indexOf(entry), 1);
}
removeAllBut(group, winner);
}
}
@ -2484,6 +2509,7 @@ function convertAgnaiMemoryBook(inputObj) {
probability: null,
useProbability: false,
group: '',
groupOverride: false,
scanDepth: entry.extensions?.scan_depth ?? null,
caseSensitive: entry.extensions?.case_sensitive ?? null,
matchWholeWords: entry.extensions?.match_whole_words ?? null,
@ -2519,6 +2545,7 @@ function convertRisuLorebook(inputObj) {
probability: entry.activationPercent ?? null,
useProbability: entry.activationPercent ?? false,
group: '',
groupOverride: false,
scanDepth: entry.extensions?.scan_depth ?? null,
caseSensitive: entry.extensions?.case_sensitive ?? null,
matchWholeWords: entry.extensions?.match_whole_words ?? null,
@ -2559,6 +2586,7 @@ function convertNovelLorebook(inputObj) {
probability: null,
useProbability: false,
group: '',
groupOverride: false,
scanDepth: entry.extensions?.scan_depth ?? null,
caseSensitive: entry.extensions?.case_sensitive ?? null,
matchWholeWords: entry.extensions?.match_whole_words ?? null,
@ -2600,6 +2628,7 @@ function convertCharacterBook(characterBook) {
depth: entry.extensions?.depth ?? DEFAULT_DEPTH,
selectiveLogic: entry.extensions?.selectiveLogic ?? world_info_logic.AND_ANY,
group: entry.extensions?.group ?? '',
groupOverride: entry.extensions?.group_override ?? false,
scanDepth: entry.extensions?.scan_depth ?? null,
caseSensitive: entry.extensions?.case_sensitive ?? null,
matchWholeWords: entry.extensions?.match_whole_words ?? null,

View File

@ -433,6 +433,7 @@ function convertWorldInfoToCharacterBook(name, entries) {
depth: entry.depth ?? 4,
selectiveLogic: entry.selectiveLogic ?? 0,
group: entry.group ?? '',
group_override: entry.groupOverride ?? false,
prevent_recursion: entry.preventRecursion ?? false,
scan_depth: entry.scanDepth ?? null,
match_whole_words: entry.matchWholeWords ?? null,