Feat/Link sampler selection lock to TC API Type (#4782) * Update - Revert connection profile change TC commands load order This change was made to prevent preset tied samplers from breaking, such thing doesn't exist anymore. * Update - Unlink preset renaming logic from sampler selection lock * Update - Link TC sampler selection lock to API Type * Fix - Clean comments * Update - Use localforage selectedSamplers and data selectsampler as main sampler selection storage * Fix - ESLint errors * Update - Change lock tooltip with correct description * Fix - Move and await sampler select localforage initializer to finish Tried to move it to the most reasonable place possible that allowed to make an await. * Fix - Make loadTextGenSettings async to load API selected samplers

e8a75c33299b7f164c1af8f531de3a804060a374

Leandro Jofré <leandrotomasjofre@gmail.com>

Signed
6 files changed, +206 -384Ignore whitespace
public/script.js+1 -1
@@ -7395,7 +7395,7 @@ export async function getSettings() {
73957395 loadNovelSettings(data, settings.nai_settings ?? settings);
73967396
73977397 // TextGen
73987398 await loadTextGenSettings(data, settings);
73997399
74007400 // OpenAI
74017401 loadOpenAISettings(data, settings.oai_settings ?? settings);
public/scripts/extensions/connection-manager/index.js+1 -1
@@ -47,8 +47,8 @@ const CC_COMMANDS = [
4747];
4848
4949const TC_COMMANDS = [
50- 'preset',
5150 'api',
51+ 'preset',
5252 'api-url',
5353 'model',
5454 'sysprompt',
public/scripts/preset-manager.js+0 -11
@@ -27,7 +27,6 @@ import { oai_settings, openai_setting_names, openai_settings } from './openai.js
2727import { POPUP_RESULT, POPUP_TYPE, Popup } from './popup.js';
2828import { context_presets, getContextSettings, power_user } from './power-user.js';
2929import { reasoning_templates } from './reasoning.js';
30-import { getManualPresetSamplers, resetPresetSelectedSamplers, setPresetSamplersState } from './samplerSelect.js';
3130import { SlashCommand } from './slash-commands/SlashCommand.js';
3231import { ARGUMENT_TYPE, SlashCommandArgument } from './slash-commands/SlashCommandArgument.js';
3332import { enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';
@@ -1072,16 +1071,6 @@ export async function initPresetManager() {
10721071 return;
10731072 }
10741073
1075- if (apiId === 'textgenerationwebui') {
1076- const manualSamplersIterable = Object.entries(getManualPresetSamplers(oldName));
1077-
1078- for (const [sampler, value] of manualSamplersIterable) {
1079- setPresetSamplersState(sampler, value, newName);
1080- }
1081-
1082- await resetPresetSelectedSamplers(oldName, true);
1083- }
1084-
10851074 const successToast = !presetManager.isAdvancedFormatting() ? t`Preset renamed` : t`Template renamed`;
10861075 toastr.success(successToast);
10871076 });
public/scripts/samplerSelect.js+190 -352
@@ -2,7 +2,6 @@ import {
22 main_api,
33 saveSettingsDebounced,
44} from '../script.js';
5-import { power_user } from './power-user.js';
65//import { BIAS_CACHE, displayLogitBias, getLogitBiasListResult } from './logit-bias.js';
76//import { getEventSourceStream } from './sse-stream.js';
87//import { getSortableDelay, onlyUnique } from './utils.js';
@@ -14,8 +13,11 @@ import { localforage } from '../lib.js';
1413
1514const forcedOnColoring = 'color: #89db35;';
1615const forcedOffColoring = 'color: #e84f62;';
17-
16+const SELECT_SAMPLER = {
18-let userDisabledSamplers, userShownSamplers;
17+ DATA: 'selectsampler',
18+ SHOWN: 'shown',
19+ HIDDEN: 'hidden',
20+};
1921
2022const textGenObjectStore = localforage.createInstance({ name: 'SillyTavern_TextCompletions' });
2123let selectedSamplers = {};
@@ -38,28 +40,15 @@ async function showSamplerSelectPopup() {
3840
3941 $('#resetSelectedSamplers').off('click').on('click', async function () {
4042 console.log('saw sampler select reset click');
41- userDisabledSamplers = [];
42- userShownSamplers = [];
43- power_user.selectSamplers.forceShown = [];
44- power_user.selectSamplers.forceHidden = [];
4543
4644 if (main_api === 'textgenerationwebui') {
4745 $('#prioritizeManuallySelectedSamplers').toggleClass('toggleEnabled', false);
4846 await resetPresetSelectedSamplersresetApiSelectedSamplers(null, true);
4947 }
5048
5149 await validateDisabledSamplers(true);
5250 });
5351
54- $('#textgen_type').on('change', async function () {
55- console.log('changed TG Type, resetting custom samplers'); //unfortunate, but necessary unless we save custom samplers for each TGTytpe
56- userDisabledSamplers = [];
57- userShownSamplers = [];
58- power_user.selectSamplers.forceShown = [];
59- power_user.selectSamplers.forceHidden = [];
60- await validateDisabledSamplers();
61- });
62-
6352 if (main_api === 'textgenerationwebui') {
6453 $('#prioritizeManuallySelectedSamplers').show();
6554 $('#prioritizeManuallySelectedSamplers').toggleClass('toggleEnabled', isSamplerManualPriorityEnabled());
@@ -76,138 +65,143 @@ async function showSamplerSelectPopup() {
7665 }
7766
7867 await showPromise;
7968 if (main_api === 'textgenerationwebui') await savePresetSelectedSamplerssaveApiSelectedSamplers();
8069}
8170
8271function setSamplerListListenersgetRelatedDOMElement(samplerName) {
83- // Goal 2: hide unchecked samplers from DOM
72+ let relatedDOMElement = $(`#${samplerName}_${main_api}`).parent();
8473 let listContainertargetDisplayType = $('#apiSamplersListflex');
85- listContainer.find('input').off('change').on('change', async function () {
74+ let displayname;
8675
87- const samplerName = this.name.replace('_checkbox', '');
76+ if (samplerName === 'json_schema') {
8877 let relatedDOMElement = $(`'#${samplerName}_${main_api}`).parent(json_schema_block');
8978 let targetDisplayType = 'flexblock';
79+ displayname = 'JSON Schema Block';
80+ }
9081
9182 if (samplerName === 'json_schemagrammar_string') {
9283 relatedDOMElement = $('#json_schema_blockgrammar_block_ooba');
9384 targetDisplayType = 'block';
94- }
85+ displayname = 'Grammar Block';
86+ }
9587
9688 if (samplerName === 'grammar_stringguidance_scale') {
9789 relatedDOMElement = $('#grammar_block_oobacfg_block_ooba');
9890 targetDisplayType = 'block';
99- }
91+ displayname = 'CFG Block';
92+ }
10093
10194 if (samplerName === 'guidance_scalemirostat_mode') {
10295 relatedDOMElement = $('#cfg_block_oobamirostat_block_ooba');
10396 targetDisplayType = 'block';
104- }
97+ displayname = 'Mirostat Block';
98+ }
10599
106100 if (samplerName === 'mirostat_modedry_multiplier') {
107101 relatedDOMElement = $('#mirostat_block_oobadryBlock');
108102 targetDisplayType = 'block';
109- }
103+ displayname = 'DRY Rep Pen Block';
104+ }
110105
111106 if (samplerName === 'dry_multiplierxtc_probability') {
112107 relatedDOMElement = $('#dryBlockxtc_block');
113108 targetDisplayType = 'block';
114- }
109+ displayname = 'XTC Block';
110+ }
115111
116112 if (samplerName === 'xtc_probabilitydynatemp') {
117113 relatedDOMElement = $('#xtc_blockdynatemp_block_ooba');
118114 targetDisplayType = 'block';
119- }
115+ displayname = 'DynaTemp Block';
116+ }
120117
121118 if (samplerName === 'dynatempbanned_tokens') {
122119 relatedDOMElement = $('#dynatemp_block_oobabanned_tokens_block_ooba');
123120 targetDisplayType = 'block';
124121 }
125122
126123 if (samplerName === 'banned_tokenssampler_order') { //this is for kcpp sampler order
127124 relatedDOMElement = $('#banned_tokens_block_oobasampler_order_block_kcpp');
128125 targetDisplayType displayname = 'blockKCPP Sampler Order Block';
129126 }
130127
131128 if (samplerName === 'sampler_ordersamplers') { //this is for kcpplcpp sampler order
132129 relatedDOMElement = $('#sampler_order_block_kcppsampler_order_block_lcpp');
133- }
130+ displayname = 'LCPP Sampler Order Block';
131+ }
134132
135133 if (samplerName === 'samplerssampler_priority') { //this is for lcppooba's sampler orderpriority
136134 relatedDOMElement = $('#sampler_order_block_lcppsampler_priority_block_ooba');
137- }
135+ displayname = 'Ooba Sampler Priority Block';
136+ }
138137
139138 if (samplerName === 'sampler_prioritysamplers_priorities') { //this is for oobaaphrodite's sampler priority
140139 relatedDOMElement = $('#sampler_priority_block_oobasampler_priority_block_aphrodite');
141- }
140+ displayname = 'Aphrodite Sampler Priority Block';
141+ }
142142
143143 if (samplerName === 'samplers_prioritiespenalty_alpha') { //thiscontrastive issearch foronly aphrodite'shas one sampler, prioritydoes it need its own block?
144144 relatedDOMElement = $('#sampler_priority_block_aphroditecontrastiveSearchBlock');
145- }
145+ displayname = 'Contrast Search Block';
146+ }
146147
147148 if (samplerName === 'penalty_alphanum_beams') { //contrastive search only has one sampler,num_beams doesis itthe needkillswitch itsfor ownBeam block?Search
148149 relatedDOMElement = $('#contrastiveSearchBlockbeamSearchBlock');
149- }
150+ targetDisplayType = 'block';
151+ displayname = 'Beam Search Block';
152+ }
150153
151154 if (samplerName === 'num_beamssmoothing_factor') { // num_beams is the killswitch for Beam Search
152155 relatedDOMElement = $('#beamSearchBlocksmoothingBlock');
153156 targetDisplayType = 'block';
154- }
157+ displayname = 'Smoothing Block';
158+ }
155159
156- if (samplerName === 'smoothing_factor') { // num_beams is the killswitch for Beam Search
160+ return { relatedDOMElement, targetDisplayType, displayname };
157- relatedDOMElement = $('#smoothingBlock');
161+}
158- targetDisplayType = 'block';
162+
159- }
163+function setSamplerListListeners() {
164+ // Goal 2: hide unchecked samplers from DOM
165+ let listContainer = $('#apiSamplersList');
166+ listContainer.find('input').off('change').on('change', async function () {
167+ const samplerName = this.name.replace('_checkbox', '');
168+ const { relatedDOMElement, targetDisplayType } = getRelatedDOMElement(samplerName);
160169
161170 // Get the current state of the custom data attribute
162171 const previousState = relatedDOMElement.data('selectsampler'SELECT_SAMPLER.DATA);
163-
172+ const isChecked = $(this).prop('checked');
164- if ($(this).prop('checked') === false) {
173+ const popupInputLabel = $(this).parent().find('.sampler_name');
165- //console.log('saw clicking checkbox from on to off...');
174+
166175 if (previousStateisChecked === 'shown'false) {
167- console.log('saw previously custom shown sampler');
176+ if (previousState === SELECT_SAMPLER.SHOWN) {
168177 //console.log('removingsaw frompreviously custom forceshown showsampler list=> new state:', isChecked, samplerName);
169178 relatedDOMElement.removeData('selectsampler'SELECT_SAMPLER.DATA);
170179 $(this).parent().find('.sampler_name')popupInputLabel.removeAttr('style');
171- power_user?.selectSamplers?.forceShown.splice(power_user?.selectSamplers?.forceShown.indexOf(samplerName), 1);
172- console.log(power_user?.selectSamplers?.forceShown);
173180 } else {
174181 console.log('saw previous untouched sampler => new state:', isChecked, samplerName);
175- //console.log(`adding ${samplerName} to force hide list`);
182+ relatedDOMElement.data(SELECT_SAMPLER.DATA, SELECT_SAMPLER.HIDDEN);
176183 relatedDOMElementpopupInputLabel.dataattr('selectsamplerstyle', 'hidden'forcedOffColoring);
177- console.log(relatedDOMElement.data('selectsampler'));
178- power_user.selectSamplers.forceHidden.push(samplerName);
179- $(this).parent().find('.sampler_name').attr('style', forcedOffColoring);
180- console.log(power_user.selectSamplers.forceHidden);
181184 }
182- } else { // going from unchecked to checked
185+ } else {
183- //console.log('saw clicking checkbox from off to on...');
186+ if (previousState === SELECT_SAMPLER.HIDDEN) {
184- if (previousState === 'hidden') {
187+ console.log('saw previously custom hidden sampler => new state:', isChecked, samplerName);
185- console.log('saw previously custom hidden sampler');
188+ relatedDOMElement.removeData(SELECT_SAMPLER.DATA);
186- //console.log('removing from custom force hide list');
189+ popupInputLabel.removeAttr('style');
187- relatedDOMElement.removeData('selectsampler');
188- $(this).parent().find('.sampler_name').removeAttr('style');
189- power_user?.selectSamplers?.forceHidden.splice(power_user?.selectSamplers?.forceHidden.indexOf(samplerName), 1);
190- console.log(power_user?.selectSamplers?.forceHidden);
191190 } else {
192191 console.log('saw previous untouched sampler => new state:', isChecked, samplerName);
193- //console.log(`adding ${samplerName} to force shown list`);
192+ relatedDOMElement.data(SELECT_SAMPLER.DATA, SELECT_SAMPLER.SHOWN);
194193 relatedDOMElementpopupInputLabel.dataattr('selectsamplerstyle', 'shown'forcedOnColoring);
195- console.log(relatedDOMElement.data('selectsampler'));
196- power_user.selectSamplers.forceShown.push(samplerName);
197- $(this).parent().find('.sampler_name').attr('style', forcedOnColoring);
198- console.log(power_user.selectSamplers.forceShown);
199194 }
200195 }
196+
201197 await saveSettingsDebounced();
202198
203199 const shouldDisplay = $(this).prop('checked')isChecked ? targetDisplayType : 'none';
204200 relatedDOMElement.css('display', shouldDisplay);
205201
206202 if (main_api === 'textgenerationwebui') {setApiSamplersState(samplerName, shouldDisplay !== 'none');
207- setPresetSamplersState(samplerName, shouldDisplay !== 'none');
208- }
209203
210204 console.log(samplerName, relatedDOMElement.data('selectsampler'SELECT_SAMPLER.DATA), shouldDisplay);
211205 });
212206
213207}
@@ -237,115 +231,42 @@ async function listSamplers(main_api, arrayOnly = false) {
237231 return availableSamplers;
238232 }
239233
240234 const samplersActivatedManually = (main_api === 'textgenerationwebui') ? getManualActivePresetSamplersgetActiveManualApiSamplers() : [];
241235 const prioritizeManualSamplerSelect = (main_api === 'textgenerationwebui') ? isSamplerManualPriorityEnabled() : false;
242236
243237 const samplersListHTML = availableSamplers.reduce((html, sampler) => {
244238 let customColor, displayname;
245- let targetDOMelement = $(`#${sampler}_${main_api}`);
239+ let { relatedDOMElement, displayname } = getRelatedDOMElement(sampler);
246-
247- if (sampler === 'sampler_order') { //this is for kcpp sampler order
248- targetDOMelement = $('#sampler_order_block_kcpp');
249- displayname = 'KCPP Sampler Order Block';
250- }
251-
252- if (sampler === 'samplers') { //this is for lcpp sampler order
253- targetDOMelement = $('#sampler_order_block_lcpp');
254- displayname = 'LCPP Sampler Order Block';
255- }
256-
257- if (sampler === 'sampler_priority') { //this is for ooba's sampler priority
258- targetDOMelement = $('#sampler_priority_block_ooba');
259- displayname = 'Ooba Sampler Priority Block';
260- }
261-
262- if (sampler === 'samplers_priorities') { //this is for aphrodite's sampler priority
263- targetDOMelement = $('#sampler_priority_block_aphrodite');
264- displayname = 'Aphrodite Sampler Priority Block';
265- }
266-
267- if (sampler === 'penalty_alpha') { //contrastive search only has one sampler, does it need its own block?
268- targetDOMelement = $('#contrastiveSearchBlock');
269- displayname = 'Contrast Search Block';
270- }
271-
272- if (sampler === 'num_beams') { // num_beams is the killswitch for Beam Search
273- targetDOMelement = $('#beamSearchBlock');
274- displayname = 'Beam Search Block';
275- }
276-
277- if (sampler === 'smoothing_factor') { // num_beams is the killswitch for Beam Search
278- targetDOMelement = $('#smoothingBlock');
279- displayname = 'Smoothing Block';
280- }
281-
282- if (sampler === 'dry_multiplier') {
283- targetDOMelement = $('#dryBlock');
284- displayname = 'DRY Rep Pen Block';
285- }
286- if (sampler === 'xtc_probability') {
287- targetDOMelement = $('#xtc_block');
288- displayname = 'XTC Block';
289- }
290-
291- if (sampler === 'dynatemp') {
292- targetDOMelement = $('#dynatemp_block_ooba');
293- displayname = 'DynaTemp Block';
294- }
295-
296- if (sampler === 'json_schema') {
297- targetDOMelement = $('#json_schema_block');
298- displayname = 'JSON Schema Block';
299- }
300-
301- if (sampler === 'grammar_string') {
302- targetDOMelement = $('#grammar_block_ooba');
303- displayname = 'Grammar Block';
304- }
305-
306- if (sampler === 'guidance_scale') {
307- targetDOMelement = $('#cfg_block_ooba');
308- displayname = 'CFG Block';
309- }
310-
311- if (sampler === 'mirostat_mode') {
312- targetDOMelement = $('#mirostat_block_ooba');
313- displayname = 'Mirostat Block';
314- }
315240
316241 const isManuallyActivated = samplersActivatedManually.includes(sampler);
317242 const isInForceHiddenArraydisplayModified = userDisabledSamplersrelatedDOMElement.includesdata(samplerSELECT_SAMPLER.DATA);
318243 const isInForceShownArrayisInDefaultState = userShownSamplers.includes(sampler)!displayModified;
319- let isVisibleInDOM = isElementVisibleInDOM(targetDOMelement[0]);
320- const isInDefaultState = () => {
321- if (isVisibleInDOM && isInForceShownArray) { return false; }
322- else if (!isVisibleInDOM && isInForceHiddenArray) { return false; }
323- else { return true; }
324- };
325244
326245 const shouldBeChecked = () => {
246+ let finalState = isElementVisibleInDOM(relatedDOMElement[0]);
247+
327248 if (prioritizeManualSamplerSelect) {
328249 returnfinalState = isManuallyActivated;
329250 }
330- else if (isInForceHiddenArray) {
251+
331- customColor = forcedOffColoring;
252+ else if (!isInDefaultState) {
332- return false;
253+ finalState = displayModified === SELECT_SAMPLER.SHOWN;
333- }
254+ customColor = finalState ? forcedOnColoring : forcedOffColoring;
334- else if (isInForceShownArray) {
335- customColor = forcedOnColoring;
336- return true;
337255 }
338- else { return isVisibleInDOM; }
256+
257+ return finalState;
339258 };
340- console.log(sampler, targetDOMelement.prop('id'), isInDefaultState(), isInForceShownArray, isInForceHiddenArray, shouldBeChecked());
259+
341- if (displayname === undefined) { displayname = sampler; }
260+ console.log(sampler, relatedDOMElement.prop('id'), isInDefaultState, shouldBeChecked());
342- if (main_api === 'textgenerationwebui') setPresetSamplersState(sampler, shouldBeChecked());
261+
262+ if (displayname === undefined) displayname = sampler;
263+ if (main_api === 'textgenerationwebui') setApiSamplersState(sampler, shouldBeChecked());
264+
343265 return html + `
344266 <divlabel class="sampler_view_list_item wide50p flex-container">
345267 <input type="checkbox" name="${sampler}_checkbox" ${shouldBeChecked() ? 'checked' : ''}>
346268 <small class="sampler_name" style="${customColor}">${displayname}</small>
347269 </divlabel>`;
348- `;
349270 }, '');
350271
351272 return samplersListHTML;
@@ -361,109 +282,28 @@ export async function validateDisabledSamplers(redraw = false) {
361282 return;
362283 }
363284
364285 const samplersActivatedManually = (main_api === 'textgenerationwebui') ? getManualActivePresetSamplersgetActiveManualApiSamplers() : [];
365286 const prioritizeManualSamplerSelect = (main_api === 'textgenerationwebui') ? isSamplerManualPriorityEnabled() : false;
366287
367288 for (const sampler of APISamplers) {
368- let relatedDOMElement = $(`#${sampler}_${main_api}`).parent();
289+ const { relatedDOMElement, targetDisplayType } = getRelatedDOMElement(sampler);
369- let targetDisplayType = 'flex';
370-
371- if (sampler === 'json_schema') {
372- relatedDOMElement = $('#json_schema_block');
373- targetDisplayType = 'block';
374- }
375-
376- if (sampler === 'grammar_string') {
377- relatedDOMElement = $('#grammar_block_ooba');
378- targetDisplayType = 'block';
379- }
380-
381- if (sampler === 'guidance_scale') {
382- relatedDOMElement = $('#cfg_block_ooba');
383- targetDisplayType = 'block';
384- }
385-
386- if (sampler === 'mirostat_mode') {
387- relatedDOMElement = $('#mirostat_block_ooba');
388- targetDisplayType = 'block';
389- }
390-
391- if (sampler === 'dynatemp') {
392- relatedDOMElement = $('#dynatemp_block_ooba');
393- targetDisplayType = 'block';
394- }
395-
396- if (sampler === 'banned_tokens') {
397- relatedDOMElement = $('#banned_tokens_block_ooba');
398- targetDisplayType = 'block';
399- }
400-
401- if (sampler === 'sampler_order') { //this is for kcpp sampler order
402- relatedDOMElement = $('#sampler_order_block_kcpp');
403- }
404-
405- if (sampler === 'samplers') { //this is for lcpp sampler order
406- relatedDOMElement = $('#sampler_order_block_lcpp');
407- }
408-
409- if (sampler === 'sampler_priority') { //this is for ooba's sampler priority
410- relatedDOMElement = $('#sampler_priority_block_ooba');
411- }
412-
413- if (sampler === 'samplers_priorities') { //this is for aphrodite's sampler priority
414- relatedDOMElement = $('#sampler_priority_block_aphrodite');
415- }
416-
417- if (sampler === 'dry_multiplier') {
418- relatedDOMElement = $('#dryBlock');
419- targetDisplayType = 'block';
420- }
421-
422- if (sampler === 'xtc_probability') {
423- relatedDOMElement = $('#xtc_block');
424- targetDisplayType = 'block';
425- }
426-
427- if (sampler === 'penalty_alpha') { //contrastive search only has one sampler, does it need its own block?
428- relatedDOMElement = $('#contrastiveSearchBlock');
429- }
430-
431- if (sampler === 'num_beams') { // num_beams is the killswitch for Beam Search
432- relatedDOMElement = $('#beamSearchBlock');
433- }
434-
435- if (sampler === 'smoothing_factor') { // num_beams is the killswitch for Beam Search
436- relatedDOMElement = $('#smoothingBlock');
437- }
438-
439-
440- if (power_user?.selectSamplers?.forceHidden.includes(sampler)) {
441- //default handling for standard sliders
442- relatedDOMElement.data('selectsampler', 'hidden');
443- relatedDOMElement.css('display', 'none');
444- } else if (power_user?.selectSamplers?.forceShown.includes(sampler)) {
445- relatedDOMElement.data('selectsampler', 'shown');
446- relatedDOMElement.css('display', targetDisplayType);
447- } else {
448- if (relatedDOMElement.data('selectsampler') === 'hidden') {
449- relatedDOMElement.removeAttr('selectsampler');
450- relatedDOMElement.css('display', targetDisplayType);
451- }
452- if (relatedDOMElement.data('selectsampler') === 'shown') {
453- relatedDOMElement.removeAttr('selectsampler');
454- relatedDOMElement.css('display', 'none');
455- }
456- }
457290
458291 if (prioritizeManualSamplerSelect) {
459292 const isManuallyActivated = samplersActivatedManually.includes(sampler);
460293 relatedDOMElement.css('display', isManuallyActivated ? targetDisplayType : 'none');
294+ } else {
295+ const selectSamplerData = relatedDOMElement.data(SELECT_SAMPLER.DATA);
296+ relatedDOMElement.css('display', selectSamplerData === SELECT_SAMPLER.SHOWN ? targetDisplayType : 'none');
461297 }
298+
299+ relatedDOMElement.removeData(SELECT_SAMPLER.DATA);
462300 }
463301
464- if (redraw) {
302+ if (!prioritizeManualSamplerSelect && main_api === 'textgenerationwebui') {
465- if (main_api === 'textgenerationwebui') showTGSamplerControls();
303+ showTGSamplerControls();
304+ }
466305
306+ if (redraw) {
467307 let samplersHTML = await listSamplers(main_api);
468308 $('#apiSamplersList').empty().append(samplersHTML.toString());
469309 setSamplerListListeners();
@@ -474,8 +314,9 @@ export async function validateDisabledSamplers(redraw = false) {
474314
475315/**
476316 * Initializes the configuration object for manually selected samplers.
317+ * @returns void
477318 */
478319export async function loadPresetSelectedSamplersloadApiSelectedSamplers() {
479320 try {
480321 console.debug('Text Completions: loading selected samplers');
481322 selectedSamplers = await textGenObjectStore.getItem('selectedSamplers') || {};
@@ -487,8 +328,9 @@ export async function loadPresetSelectedSamplers() {
487328
488329/**
489330 * Synchronizes the local forage instance with the selected samplers configuration object.
331+ * @returns void
490332 */
491333export async function savePresetSelectedSamplerssaveApiSelectedSamplers() {
492334 try {
493335 console.debug('Text Completions: saving selected samplers');
494336 await textGenObjectStore.setItem('selectedSamplers', selectedSamplers);
@@ -499,18 +341,19 @@ export async function savePresetSelectedSamplers() {
499341
500342/**
501343 * Resets the selected samplers configuration object from the local forage instance.
502344 * @param {string?} presetNametcApiType Name of the target presetAPI Type - It picks the currentcurrently active TC presetAPI type name by default
503345 * @param {boolean} silent Suppresses the toastr message confirming that the data was deleted.
346+ * @returns void
504347 */
505348export async function resetPresetSelectedSamplersresetApiSelectedSamplers(presetNametcApiType = '', silent = false) {
506349 try {
507350 if (!textgenerationwebui_settings?.presettype && !presetNametcApiType) return;
508351 if (!presetNametcApiType) presetNametcApiType = textgenerationwebui_settings.presettype;
509352 if (!selectedSamplers[presetNametcApiType]) return;
510353
511354 console.debug('Text Completions: resetting selected samplers');
512355 delete selectedSamplers[presetNametcApiType];
513356 await savePresetSelectedSamplerssaveApiSelectedSamplers();
514357 if (!silent) toastr.success('Selected samplers cleared.');
515358 } catch (error) {
516359 console.log('Text Completions: unable to reset selected preset samplers', error);
@@ -521,43 +364,43 @@ export async function resetPresetSelectedSamplers(presetName = '', silent = fals
521364 * Saves the visibility state for selected samplers into the configuration object.
522365 * @param {string} samplerName Target sampler key name
523366 * @param {string|boolean} state Visibility state of the target sampler
524367 * @param {string?} presetNametcApiType Name of the target presetAPI Type - It picks the currentcurrently active TC presetAPI type name by default
525368 * @returns void
526369 */
527370export function setPresetSamplersStatesetApiSamplersState(samplerName, state, presetNametcApiType = '') {
528371 if (!textgenerationwebui_settings?.presettype && !presetNametcApiType) return;
529372 if (!presetNametcApiType) presetNametcApiType = textgenerationwebui_settings.presettype;
530373 if (!selectedSamplers[presetNametcApiType]) selectedSamplers[presetNametcApiType] = {};
531374
532375 const presetSamplers = selectedSamplers[presetNametcApiType];
533376 presetSamplers[samplerName] = String(state) === 'true';
534377}
535378
536379/**
537380 * Returns the local forage object belonging to the active/selected TC presetAPI Type
538381 * @param {string?} presetNametcApiType Name of the target presetAPI Type - It picks the currentcurrently active TC presetAPI type name by default
539382 * @returns {object} Full localforage object with manual selections
540383 */
541384export function getManualPresetSamplersgetAllManualApiSamplers(presetNametcApiType = '') {
542385 if (!textgenerationwebui_settings?.presettype && !presetNametcApiType) return {};
543386 if (!presetNametcApiType) presetNametcApiType = textgenerationwebui_settings.presettype;
544387 if (!selectedSamplers[presetNametcApiType]) selectedSamplers[presetNametcApiType] = {};
545388
546389 return selectedSamplers[presetNametcApiType];
547390}
548391
549392/**
550393 * Returns the key names of all the preset samplersmanually activated manuallyAPI Type samplers.
551394 * @param {string?} presetNametcApiType Name of the target presetAPI Type - It picks the currentcurrently active TC presetAPI type name by default
552395 * @returns {string[]} Array of sampler key names
553396 */
554397export function getManualActivePresetSamplersgetActiveManualApiSamplers(presetNametcApiType = '') {
555398 if (!textgenerationwebui_settings?.presettype && !presetNametcApiType) return [];
556399 if (!presetNametcApiType) presetNametcApiType = textgenerationwebui_settings.presettype;
557400 if (!selectedSamplers[presetNametcApiType]) selectedSamplers[presetNametcApiType] = {};
558401
559402 try {
560403 const presetSamplers = Object.entries(selectedSamplers[presetNametcApiType]);
561404
562405 return presetSamplers
563406 .filter(([key, val]) => val === true && key !== 'st_manual_priority')
@@ -570,36 +413,31 @@ export function getManualActivePresetSamplers(presetName = '') {
570413
571414/**
572415 * @param {string|boolean} state Target state of the feature
573416 * @param {string?} presetNametcApiType Name of the target presetAPI Type - It picks the currentcurrently active TC presetAPI type name by default
574417 * @returns void
575418 */
576419export function toggleSamplerManualPriority(state = false, presetNametcApiType = '') {
577420 if (!textgenerationwebui_settings?.presettype && !presetNametcApiType) return;
578421 if (!presetNametcApiType) presetNametcApiType = textgenerationwebui_settings.presettype;
579422 if (!selectedSamplers[presetNametcApiType]) selectedSamplers[presetNametcApiType] = {};
580423
581424 const presetSamplers = selectedSamplers[presetNametcApiType];
582425 presetSamplers.st_manual_priority = String(state) === 'true';
583426}
584427
585428/**
586429 * @param {string?} presetNametcApiType Name of the target presetAPI Type - It picks the currentcurrently active TC presetAPI type name by default
587430 * @returns {boolean}
588431 */
589432export function isSamplerManualPriorityEnabled(presetNametcApiType = '') {
590433 if (!textgenerationwebui_settings?.presettype && !presetNametcApiType) return false;
591434 if (!presetNametcApiType) presetNametcApiType = textgenerationwebui_settings.presettype;
592435 if (!selectedSamplers[presetNametcApiType]) selectedSamplers[presetNametcApiType] = {};
593436
594437 return selectedSamplers[presetNametcApiType]?.st_manual_priority ?? false;
595438}
596439
597440export async function initCustomSelectedSamplers() {
598- userDisabledSamplers = power_user?.selectSamplers?.forceHidden || [];
599- userShownSamplers = power_user?.selectSamplers?.forceShown || [];
600- power_user.selectSamplers = {};
601- power_user.selectSamplers.forceHidden = userDisabledSamplers;
602- power_user.selectSamplers.forceShown = userShownSamplers;
603441 await saveSettingsDebounced();
604442 $('#samplerSelectButton').off('click').on('click', showSamplerSelectPopup);
605443}
public/scripts/templates/samplerSelector.html+1 -1
@@ -10,7 +10,7 @@
1010 <i class="fa-solid fa-lock"></i>
1111 <span data-i18n="Prioritize">Prioritize</span>
1212 </div>
1313 <div class="margin5 fa-solid fa-exclamation-circle" data-i18n="[title]Toggle on to force the samplers selected in this menu to be shown when switching to thisthe presetcurrent API Type (API Connections Panel). By default, SillyTavern automatically selects samplers used or needed by the selected API Type in the API Connections panel." title="Toggle on to force the samplers selected in this menu to be shown when switching to thisthe presetcurrent API Type (API Connections Panel). By default, SillyTavern automatically selects samplers used or needed by the selected API Type in the API Connections panel."></div>
1414 </div>
1515 <!--<div class="flex-container alignItemsBaseline">
1616 <div class="menu_button menu_button_icon" title="Create a new sampler">
public/scripts/textgen-settings.js+13 -18
@@ -20,7 +20,7 @@ import { autoSelectInstructPreset, selectContextPreset, selectInstructPreset } f
2020import { BIAS_CACHE, createNewLogitBiasEntry, displayLogitBias, getLogitBiasListResult } from './logit-bias.js';
2121
2222import { power_user, registerDebugFunction } from './power-user.js';
2323import { getManualActivePresetSamplersgetActiveManualApiSamplers, isSamplerManualPriorityEnabledloadApiSelectedSamplers, loadPresetSelectedSamplersisSamplerManualPriorityEnabled } from './samplerSelect.js';
2424import { SECRET_KEYS, writeSecret } from './secrets.js';
2525import { getEventSourceStream } from './sse-stream.js';
2626import { getCurrentDreamGenModelTokenizer, getCurrentOpenRouterModelTokenizer, loadAphroditeModels, loadDreamGenModels, loadFeatherlessModels, loadGenericModels, loadInfermaticAIModels, loadMancerModels, loadOllamaModels, loadOpenRouterModels, loadTabbyModels, loadTogetherAIModels, loadVllmModels } from './textgen-models.js';
@@ -372,7 +372,6 @@ async function selectPreset(name) {
372372 setSettingByName(name, value, true);
373373 }
374374 setGenerationParamsFromPreset(preset);
375- showSamplerControls(null, true);
376375 BIAS_CACHE.delete(BIAS_KEY);
377376 displayLogitBias(preset.logit_bias, BIAS_KEY);
378377 saveSettingsDebounced();
@@ -530,7 +529,8 @@ function calculateLogitBias() {
530529 return result;
531530}
532531
533532export async function loadTextGenSettings(data, loadedSettings) {
533+ await loadApiSelectedSamplers();
534534 textgenerationwebui_presets = convertPresets(data.textgenerationwebui_presets);
535535 textgenerationwebui_preset_names = data.textgenerationwebui_preset_names ?? [];
536536 Object.assign(settings, loadedSettings.textgenerationwebui_settings ?? {});
@@ -572,8 +572,7 @@ export function loadTextGenSettings(data, loadedSettings) {
572572
573573 $('#textgen_type').val(settings.type);
574574 $('#openrouter_providers_text').val(settings.openrouter_providers).trigger('change');
575575 loadPresetSelectedSamplersshowSamplerControls(settings.type);
576- showSamplerControls();
577576 BIAS_CACHE.delete(BIAS_KEY);
578577 displayLogitBias(settings.logit_bias, BIAS_KEY);
579578
@@ -779,8 +778,6 @@ async function getStatusTextgen() {
779778}
780779
781780export function initTextGenSettings() {
782- loadPresetSelectedSamplers();
783-
784781 $('#send_banned_tokens_textgenerationwebui').on('change', function () {
785782 const checked = !!$(this).prop('checked');
786783 toggleBannedStringsKillSwitch(checked,
@@ -1078,21 +1075,19 @@ export function initTextGenSettings() {
10781075/**
10791076 * Hides and shows preset samplers from the left panel.
10801077 * @param {string?} apiType API Type selected in API Connections - Currently selected one by default
1081- * @param {boolean?} isPresetSwitch Wheter the trigger comes from a preset switch - false by default
10821078 * @returns void
10831079 */
10841080function showSamplerControls(apiType = null, isPresetSwitch = false) {
1085- const prioritizeManualSamplerSelect = isSamplerManualPriorityEnabled();
1081+ $('#textgenerationwebui_api-settings [data-tg-samplers]').each(function(idx, elem) {
1086-
1082+ const typeSpecificControlled = $(elem).data('tg-type') !== undefined;
1087- if (isPresetSwitch && !prioritizeManualSamplerSelect) return;
10881083
1089- $('#textgenerationwebui_api-settings [data-tg-samplers]:not([data-tg-type])').each(function() {
1084+ if (!typeSpecificControlled) $(this).show();
1090- $(this).show();
10911085 });
10921086
10931087 showTypeSpecificControls(apiType ?? settings.type);
10941088
10951089 const samplersActivatedManuallyprioritizeManualSamplerSelect = getManualActivePresetSamplersisSamplerManualPriorityEnabled(apiType ?? settings.type);
1090+ const samplersActivatedManually = getActiveManualApiSamplers(apiType ?? settings.type);
10961091
10971092 if (!samplersActivatedManually?.length || !prioritizeManualSamplerSelect) return;
10981093
@@ -1110,18 +1105,18 @@ function showSamplerControls(apiType = null, isPresetSwitch = false) {
11101105 });
11111106}
11121107
11131108function showTypeSpecificControls(typeapiType) {
11141109 $('[data-tg-type]').each(function () {
11151110 const mode = String($(this).attr('data-tg-type-mode') ?? '').toLowerCase().trim();
11161111 const tgTypes = $(this).attr('data-tg-type').split(',').map(x => x.trim());
11171112
11181113 if (mode === 'except') {
11191114 $(this)[tgTypes.includes(typeapiType) ? 'hide' : 'show']();
11201115 return;
11211116 }
11221117
11231118 for (const tgType of tgTypes) {
11241119 if (tgType === typeapiType || tgType == 'all') {
11251120 $(this).show();
11261121 return;
11271122 } else {