Merge pull request #3301 from SillyTavern/tempresponselength Restore temp response length as early as possible
Signed| @@ -574,7 +574,7 @@ export const DEFAULT_SAVE_EDIT_TIMEOUT = debounce_timeout.relaxed; | |||
| 574 | /** @type {debounce_timeout} The debounce timeout used for printing. debounce_timeout.quick: 100 ms */ | 574 | /** @type {debounce_timeout} The debounce timeout used for printing. debounce_timeout.quick: 100 ms */ |
| 575 | export const DEFAULT_PRINT_TIMEOUT = debounce_timeout.quick; | 575 | export const DEFAULT_PRINT_TIMEOUT = debounce_timeout.quick; |
| 576 | 576 | ||
| 577 | export const saveSettingsDebounced = debounce(() => saveSettings(), DEFAULT_SAVE_EDIT_TIMEOUT); | 577 | export const saveSettingsDebounced = debounce((loopCounter = 0) => saveSettings(loopCounter), DEFAULT_SAVE_EDIT_TIMEOUT); |
| 578 | export const saveCharacterDebounced = debounce(() => $('#create_button').trigger('click'), DEFAULT_SAVE_EDIT_TIMEOUT); | 578 | export const saveCharacterDebounced = debounce(() => $('#create_button').trigger('click'), DEFAULT_SAVE_EDIT_TIMEOUT); |
| 579 | 579 | ||
| 580 | /** | 580 | /** |
| @@ -2724,7 +2724,7 @@ export function getStoppingStrings(isImpersonate, isContinue) { | |||
| 2724 | export async function generateQuietPrompt(quiet_prompt, quietToLoud, skipWIAN, quietImage = null, quietName = null, responseLength = null, force_chid = null) { | 2724 | export async function generateQuietPrompt(quiet_prompt, quietToLoud, skipWIAN, quietImage = null, quietName = null, responseLength = null, force_chid = null) { |
| 2725 | console.log('got into genQuietPrompt'); | 2725 | console.log('got into genQuietPrompt'); |
| 2726 | const responseLengthCustomized = typeof responseLength === 'number' && responseLength > 0; | 2726 | const responseLengthCustomized = typeof responseLength === 'number' && responseLength > 0; |
| 2727 | let originalResponseLength = -1; | 2727 | let eventHook = () => {}; |
| 2728 | try { | 2728 | try { |
| 2729 | /** @type {GenerateOptions} */ | 2729 | /** @type {GenerateOptions} */ |
| 2730 | const options = { | 2730 | const options = { |
| @@ -2736,11 +2736,15 @@ export async function generateQuietPrompt(quiet_prompt, quietToLoud, skipWIAN, q | |||
| 2736 | quietName: quietName, | 2736 | quietName: quietName, |
| 2737 | force_chid: force_chid, | 2737 | force_chid: force_chid, |
| 2738 | }; | 2738 | }; |
| 2739 | originalResponseLength = responseLengthCustomized ? saveResponseLength(main_api, responseLength) : -1; | 2739 | if (responseLengthCustomized) { |
| 2740 | TempResponseLength.save(main_api, responseLength); | ||
| 2741 | eventHook = TempResponseLength.setupEventHook(main_api); | ||
| 2742 | } | ||
| 2740 | return await Generate('quiet', options); | 2743 | return await Generate('quiet', options); |
| 2741 | } finally { | 2744 | } finally { |
| 2742 | if (responseLengthCustomized) { | 2745 | if (responseLengthCustomized && TempResponseLength.isCustomized()) { |
| 2743 | restoreResponseLength(main_api, originalResponseLength); | 2746 | TempResponseLength.restore(main_api); |
| 2747 | TempResponseLength.removeEventHook(main_api, eventHook); | ||
| 2744 | } | 2748 | } |
| 2745 | } | 2749 | } |
| 2746 | } | 2750 | } |
| @@ -3384,9 +3388,9 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy | |||
| 3384 | 3388 | ||
| 3385 | const abortController = new AbortController(); | 3389 | const abortController = new AbortController(); |
| 3386 | const responseLengthCustomized = typeof responseLength === 'number' && responseLength > 0; | 3390 | const responseLengthCustomized = typeof responseLength === 'number' && responseLength > 0; |
| 3387 | let originalResponseLength = -1; | ||
| 3388 | const isInstruct = power_user.instruct.enabled && api !== 'openai' && api !== 'novel' && !instructOverride; | 3391 | const isInstruct = power_user.instruct.enabled && api !== 'openai' && api !== 'novel' && !instructOverride; |
| 3389 | const isQuiet = true; | 3392 | const isQuiet = true; |
| 3393 | let eventHook = () => {}; | ||
| 3390 | 3394 | ||
| 3391 | if (systemPrompt) { | 3395 | if (systemPrompt) { |
| 3392 | systemPrompt = substituteParams(systemPrompt); | 3396 | systemPrompt = substituteParams(systemPrompt); |
| @@ -3400,7 +3404,9 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy | |||
| 3400 | prompt = isInstruct ? (prompt + formatInstructModePrompt(name2, false, '', name1, name2, isQuiet, quietToLoud)) : (prompt + '\n'); | 3404 | prompt = isInstruct ? (prompt + formatInstructModePrompt(name2, false, '', name1, name2, isQuiet, quietToLoud)) : (prompt + '\n'); |
| 3401 | 3405 | ||
| 3402 | try { | 3406 | try { |
| 3403 | originalResponseLength = responseLengthCustomized ? saveResponseLength(api, responseLength) : -1; | 3407 | if (responseLengthCustomized) { |
| 3408 | TempResponseLength.save(api, responseLength); | ||
| 3409 | } | ||
| 3404 | let generateData = {}; | 3410 | let generateData = {}; |
| 3405 | 3411 | ||
| 3406 | switch (api) { | 3412 | switch (api) { |
| @@ -3413,20 +3419,24 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy | |||
| 3413 | const koboldSettings = koboldai_settings[koboldai_setting_names[preset_settings]]; | 3419 | const koboldSettings = koboldai_settings[koboldai_setting_names[preset_settings]]; |
| 3414 | generateData = getKoboldGenerationData(prompt, koboldSettings, amount_gen, max_context, isHorde, 'quiet'); | 3420 | generateData = getKoboldGenerationData(prompt, koboldSettings, amount_gen, max_context, isHorde, 'quiet'); |
| 3415 | } | 3421 | } |
| 3422 | TempResponseLength.restore(api); | ||
| 3416 | break; | 3423 | break; |
| 3417 | case 'novel': { | 3424 | case 'novel': { |
| 3418 | const novelSettings = novelai_settings[novelai_setting_names[nai_settings.preset_settings_novel]]; | 3425 | const novelSettings = novelai_settings[novelai_setting_names[nai_settings.preset_settings_novel]]; |
| 3419 | generateData = getNovelGenerationData(prompt, novelSettings, amount_gen, false, false, null, 'quiet'); | 3426 | generateData = getNovelGenerationData(prompt, novelSettings, amount_gen, false, false, null, 'quiet'); |
| 3427 | TempResponseLength.restore(api); | ||
| 3420 | break; | 3428 | break; |
| 3421 | } | 3429 | } |
| 3422 | case 'textgenerationwebui': | 3430 | case 'textgenerationwebui': |
| 3423 | generateData = getTextGenGenerationData(prompt, amount_gen, false, false, null, 'quiet'); | 3431 | generateData = getTextGenGenerationData(prompt, amount_gen, false, false, null, 'quiet'); |
| 3432 | TempResponseLength.restore(api); | ||
| 3424 | break; | 3433 | break; |
| 3425 | case 'openai': { | 3434 | case 'openai': { |
| 3426 | generateData = [{ role: 'user', content: prompt.trim() }]; | 3435 | generateData = [{ role: 'user', content: prompt.trim() }]; |
| 3427 | if (systemPrompt) { | 3436 | if (systemPrompt) { |
| 3428 | generateData.unshift({ role: 'system', content: systemPrompt.trim() }); | 3437 | generateData.unshift({ role: 'system', content: systemPrompt.trim() }); |
| 3429 | } | 3438 | } |
| 3439 | eventHook = TempResponseLength.setupEventHook(api); | ||
| 3430 | } break; | 3440 | } break; |
| 3431 | } | 3441 | } |
| 3432 | 3442 | ||
| @@ -3468,41 +3478,100 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy | |||
| 3468 | 3478 | ||
| 3469 | return message; | 3479 | return message; |
| 3470 | } finally { | 3480 | } finally { |
| 3471 | if (responseLengthCustomized) { | 3481 | if (responseLengthCustomized && TempResponseLength.isCustomized()) { |
| 3472 | restoreResponseLength(api, originalResponseLength); | 3482 | TempResponseLength.restore(api); |
| 3483 | TempResponseLength.removeEventHook(api, eventHook); | ||
| 3473 | } | 3484 | } |
| 3474 | } | 3485 | } |
| 3475 | } | 3486 | } |
| 3476 | 3487 | ||
| 3477 | /** | 3488 | class TempResponseLength { |
| 3478 | * Temporarily change the response length for the specified API. | 3489 | static #originalResponseLength = -1; |
| 3479 | * @param {string} api API to use. | 3490 | static #lastApi = null; |
| 3480 | * @param {number} responseLength Target response length. | 3491 | |
| 3481 | * @returns {number} The original response length. | 3492 | static isCustomized() { |
| 3482 | */ | 3493 | return this.#originalResponseLength > -1; |
| 3483 | function saveResponseLength(api, responseLength) { | ||
| 3484 | let oldValue = -1; | ||
| 3485 | if (api === 'openai') { | ||
| 3486 | oldValue = oai_settings.openai_max_tokens; | ||
| 3487 | oai_settings.openai_max_tokens = responseLength; | ||
| 3488 | } else { | ||
| 3489 | oldValue = amount_gen; | ||
| 3490 | amount_gen = responseLength; | ||
| 3491 | } | 3494 | } |
| 3492 | return oldValue; | ||
| 3493 | } | ||
| 3494 | 3495 | ||
| 3495 | /** | 3496 | /** |
| 3496 | * Restore the original response length for the specified API. | 3497 | * Save the current response length for the specified API. |
| 3497 | * @param {string} api API to use. | 3498 | * @param {string} api API identifier |
| 3498 | * @param {number} responseLength Target response length. | 3499 | * @param {number} responseLength New response length |
| 3499 | * @returns {void} | 3500 | */ |
| 3500 | */ | 3501 | static save(api, responseLength) { |
| 3501 | function restoreResponseLength(api, responseLength) { | 3502 | if (api === 'openai') { |
| 3502 | if (api === 'openai') { | 3503 | this.#originalResponseLength = oai_settings.openai_max_tokens; |
| 3503 | oai_settings.openai_max_tokens = responseLength; | 3504 | oai_settings.openai_max_tokens = responseLength; |
| 3504 | } else { | 3505 | } else { |
| 3505 | amount_gen = responseLength; | 3506 | this.#originalResponseLength = amount_gen; |
| 3507 | amount_gen = responseLength; | ||
| 3508 | } | ||
| 3509 | |||
| 3510 | this.#lastApi = api; | ||
| 3511 | console.log('[TempResponseLength] Saved original response length:', TempResponseLength.#originalResponseLength); | ||
| 3512 | } | ||
| 3513 | |||
| 3514 | /** | ||
| 3515 | * Restore the original response length for the specified API. | ||
| 3516 | * @param {string|null} api API identifier | ||
| 3517 | * @returns {void} | ||
| 3518 | */ | ||
| 3519 | static restore(api) { | ||
| 3520 | if (this.#originalResponseLength === -1) { | ||
| 3521 | return; | ||
| 3522 | } | ||
| 3523 | if (!api && this.#lastApi) { | ||
| 3524 | api = this.#lastApi; | ||
| 3525 | } | ||
| 3526 | if (api === 'openai') { | ||
| 3527 | oai_settings.openai_max_tokens = this.#originalResponseLength; | ||
| 3528 | } else { | ||
| 3529 | amount_gen = this.#originalResponseLength; | ||
| 3530 | } | ||
| 3531 | |||
| 3532 | console.log('[TempResponseLength] Restored original response length:', this.#originalResponseLength); | ||
| 3533 | this.#originalResponseLength = -1; | ||
| 3534 | this.#lastApi = null; | ||
| 3535 | } | ||
| 3536 | |||
| 3537 | /** | ||
| 3538 | * Sets up an event hook to restore the original response length when the event is emitted. | ||
| 3539 | * @param {string} api API identifier | ||
| 3540 | * @returns {function(): void} Event hook function | ||
| 3541 | */ | ||
| 3542 | static setupEventHook(api) { | ||
| 3543 | const eventHook = () => { | ||
| 3544 | if (this.isCustomized()) { | ||
| 3545 | this.restore(api); | ||
| 3546 | } | ||
| 3547 | }; | ||
| 3548 | |||
| 3549 | switch (api) { | ||
| 3550 | case 'openai': | ||
| 3551 | eventSource.once(event_types.CHAT_COMPLETION_SETTINGS_READY, eventHook); | ||
| 3552 | break; | ||
| 3553 | default: | ||
| 3554 | eventSource.once(event_types.GENERATE_AFTER_DATA, eventHook); | ||
| 3555 | break; | ||
| 3556 | } | ||
| 3557 | |||
| 3558 | return eventHook; | ||
| 3559 | } | ||
| 3560 | |||
| 3561 | /** | ||
| 3562 | * Removes the event hook for the specified API. | ||
| 3563 | * @param {string} api API identifier | ||
| 3564 | * @param {function(): void} eventHook Previously set up event hook | ||
| 3565 | */ | ||
| 3566 | static removeEventHook(api, eventHook) { | ||
| 3567 | switch (api) { | ||
| 3568 | case 'openai': | ||
| 3569 | eventSource.removeListener(event_types.CHAT_COMPLETION_SETTINGS_READY, eventHook); | ||
| 3570 | break; | ||
| 3571 | default: | ||
| 3572 | eventSource.removeListener(event_types.GENERATE_AFTER_DATA, eventHook); | ||
| 3573 | break; | ||
| 3574 | } | ||
| 3506 | } | 3575 | } |
| 3507 | } | 3576 | } |
| 3508 | 3577 | ||
| @@ -6865,12 +6934,23 @@ function selectKoboldGuiPreset() { | |||
| 6865 | .trigger('change'); | 6934 | .trigger('change'); |
| 6866 | } | 6935 | } |
| 6867 | 6936 | ||
| 6868 | export async function saveSettings(type) { | 6937 | export async function saveSettings(loopCounter = 0) { |
| 6869 | if (!settingsReady) { | 6938 | if (!settingsReady) { |
| 6870 | console.warn('Settings not ready, aborting save'); | 6939 | console.warn('Settings not ready, aborting save'); |
| 6871 | return; | 6940 | return; |
| 6872 | } | 6941 | } |
| 6873 | 6942 | ||
| 6943 | const MAX_RETRIES = 3; | ||
| 6944 | if (TempResponseLength.isCustomized()) { | ||
| 6945 | if (loopCounter < MAX_RETRIES) { | ||
| 6946 | console.warn('Response length is currently being overridden, scheduling another save'); | ||
| 6947 | saveSettingsDebounced(++loopCounter); | ||
| 6948 | return; | ||
| 6949 | } | ||
| 6950 | console.error('Response length is currently being overridden, but the save loop has reached the maximum number of retries'); | ||
| 6951 | TempResponseLength.restore(null); | ||
| 6952 | } | ||
| 6953 | |||
| 6874 | //console.log('Entering settings with name1 = '+name1); | 6954 | //console.log('Entering settings with name1 = '+name1); |
| 6875 | return jQuery.ajax({ | 6955 | return jQuery.ajax({ |
| 6876 | type: 'POST', | 6956 | type: 'POST', |