Remove empty message looping
| @@ -881,7 +881,6 @@ let abortController; | |||
| 881 | 881 | ||
| 882 | //css | 882 | //css |
| 883 | var css_send_form_display = $('<div id=send_form></div>').css('display'); | 883 | var css_send_form_display = $('<div id=send_form></div>').css('display'); |
| 884 | const MAX_GENERATION_LOOPS = 5; | ||
| 885 | 884 | ||
| 886 | var kobold_horde_model = ''; | 885 | var kobold_horde_model = ''; |
| 887 | 886 | ||
| @@ -2864,10 +2863,10 @@ export function isStreamingEnabled() { | |||
| 2864 | const noStreamSources = [chat_completion_sources.SCALE]; | 2863 | const noStreamSources = [chat_completion_sources.SCALE]; |
| 2865 | return ( | 2864 | return ( |
| 2866 | (main_api == 'openai' && | 2865 | (main_api == 'openai' && |
| 2867 | oai_settings.stream_openai && | 2866 | oai_settings.stream_openai && |
| 2868 | !noStreamSources.includes(oai_settings.chat_completion_source) && | 2867 | !noStreamSources.includes(oai_settings.chat_completion_source) && |
| 2869 | !(oai_settings.chat_completion_source == chat_completion_sources.OPENAI && oai_settings.openai_model.startsWith('o1-')) && | 2868 | !(oai_settings.chat_completion_source == chat_completion_sources.OPENAI && oai_settings.openai_model.startsWith('o1-')) && |
| 2870 | !(oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE && oai_settings.google_model.includes('bison'))) | 2869 | !(oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE && oai_settings.google_model.includes('bison'))) |
| 2871 | || (main_api == 'kobold' && kai_settings.streaming_kobold && kai_flags.can_use_streaming) | 2870 | || (main_api == 'kobold' && kai_settings.streaming_kobold && kai_flags.can_use_streaming) |
| 2872 | || (main_api == 'novel' && nai_settings.streaming_novel) | 2871 | || (main_api == 'novel' && nai_settings.streaming_novel) |
| 2873 | || (main_api == 'textgenerationwebui' && textgen_settings.streaming)); | 2872 | || (main_api == 'textgenerationwebui' && textgen_settings.streaming)); |
| @@ -3342,11 +3341,11 @@ function removeLastMessage() { | |||
| 3342 | * @param {GenerateOptions} options Generation options | 3341 | * @param {GenerateOptions} options Generation options |
| 3343 | * @param {boolean} dryRun Whether to actually generate a message or just assemble the prompt | 3342 | * @param {boolean} dryRun Whether to actually generate a message or just assemble the prompt |
| 3344 | * @returns {Promise<any>} Returns a promise that resolves when the text is done generating. | 3343 | * @returns {Promise<any>} Returns a promise that resolves when the text is done generating. |
| 3345 | * @typedef {{automatic_trigger?: boolean, force_name2?: boolean, quiet_prompt?: string, quietToLoud?: boolean, skipWIAN?: boolean, force_chid?: number, signal?: AbortSignal, quietImage?: string, maxLoops?: number, quietName?: string }} GenerateOptions | 3344 | * @typedef {{automatic_trigger?: boolean, force_name2?: boolean, quiet_prompt?: string, quietToLoud?: boolean, skipWIAN?: boolean, force_chid?: number, signal?: AbortSignal, quietImage?: string, quietName?: string }} GenerateOptions |
| 3346 | */ | 3345 | */ |
| 3347 | export async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage, maxLoops, quietName } = {}, dryRun = false) { | 3346 | export async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage, quietName } = {}, dryRun = false) { |
| 3348 | console.log('Generate entered'); | 3347 | console.log('Generate entered'); |
| 3349 | await eventSource.emit(event_types.GENERATION_STARTED, type, { automatic_trigger, force_name2, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage, maxLoops }, dryRun); | 3348 | await eventSource.emit(event_types.GENERATION_STARTED, type, { automatic_trigger, force_name2, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage }, dryRun); |
| 3350 | setGenerationProgress(0); | 3349 | setGenerationProgress(0); |
| 3351 | generation_started = new Date(); | 3350 | generation_started = new Date(); |
| 3352 | 3351 | ||
| @@ -3408,7 +3407,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 3408 | if (selected_group && !is_group_generating) { | 3407 | if (selected_group && !is_group_generating) { |
| 3409 | if (!dryRun) { | 3408 | if (!dryRun) { |
| 3410 | // Returns the promise that generateGroupWrapper returns; resolves when generation is done | 3409 | // Returns the promise that generateGroupWrapper returns; resolves when generation is done |
| 3411 | return generateGroupWrapper(false, type, { quiet_prompt, force_chid, signal: abortController.signal, quietImage, maxLoops }); | 3410 | return generateGroupWrapper(false, type, { quiet_prompt, force_chid, signal: abortController.signal, quietImage }); |
| 3412 | } | 3411 | } |
| 3413 | 3412 | ||
| 3414 | const characterIndexMap = new Map(characters.map((char, index) => [char.avatar, index])); | 3413 | const characterIndexMap = new Map(characters.map((char, index) => [char.avatar, index])); |
| @@ -4440,53 +4439,30 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4440 | const displayIncomplete = type === 'quiet' && !quietToLoud; | 4439 | const displayIncomplete = type === 'quiet' && !quietToLoud; |
| 4441 | getMessage = cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncomplete); | 4440 | getMessage = cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncomplete); |
| 4442 | 4441 | ||
| 4443 | if (getMessage.length > 0 || data.allowEmptyResponse) { | 4442 | if (isImpersonate) { |
| 4444 | if (isImpersonate) { | 4443 | $('#send_textarea').val(getMessage)[0].dispatchEvent(new Event('input', { bubbles: true })); |
| 4445 | $('#send_textarea').val(getMessage)[0].dispatchEvent(new Event('input', { bubbles: true })); | 4444 | generatedPromptCache = ''; |
| 4446 | generatedPromptCache = ''; | 4445 | await eventSource.emit(event_types.IMPERSONATE_READY, getMessage); |
| 4447 | await eventSource.emit(event_types.IMPERSONATE_READY, getMessage); | 4446 | } |
| 4448 | } | 4447 | else if (type == 'quiet') { |
| 4449 | else if (type == 'quiet') { | 4448 | unblockGeneration(type); |
| 4450 | unblockGeneration(type); | 4449 | return getMessage; |
| 4451 | return getMessage; | 4450 | } |
| 4451 | else { | ||
| 4452 | // Without streaming we'll be having a full message on continuation. Treat it as a last chunk. | ||
| 4453 | if (originalType !== 'continue') { | ||
| 4454 | ({ type, getMessage } = await saveReply(type, getMessage, false, title, swipes)); | ||
| 4452 | } | 4455 | } |
| 4453 | else { | 4456 | else { |
| 4454 | // Without streaming we'll be having a full message on continuation. Treat it as a last chunk. | 4457 | ({ type, getMessage } = await saveReply('appendFinal', getMessage, false, title, swipes)); |
| 4455 | if (originalType !== 'continue') { | ||
| 4456 | ({ type, getMessage } = await saveReply(type, getMessage, false, title, swipes)); | ||
| 4457 | } | ||
| 4458 | else { | ||
| 4459 | ({ type, getMessage } = await saveReply('appendFinal', getMessage, false, title, swipes)); | ||
| 4460 | } | ||
| 4461 | |||
| 4462 | // This relies on `saveReply` having been called to add the message to the chat, so it must be last. | ||
| 4463 | parseAndSaveLogprobs(data, continue_mag); | ||
| 4464 | } | 4458 | } |
| 4465 | 4459 | ||
| 4466 | if (type !== 'quiet') { | 4460 | // This relies on `saveReply` having been called to add the message to the chat, so it must be last. |
| 4467 | playMessageSound(); | 4461 | parseAndSaveLogprobs(data, continue_mag); |
| 4468 | } | 4462 | } |
| 4469 | } else { | ||
| 4470 | // If maxLoops is not passed in (e.g. first time generating), set it to MAX_GENERATION_LOOPS | ||
| 4471 | maxLoops ??= MAX_GENERATION_LOOPS; | ||
| 4472 | |||
| 4473 | if (maxLoops === 0) { | ||
| 4474 | if (type !== 'quiet') { | ||
| 4475 | throwCircuitBreakerError(); | ||
| 4476 | } | ||
| 4477 | throw new Error('Generate circuit breaker interruption'); | ||
| 4478 | } | ||
| 4479 | 4463 | ||
| 4480 | // regenerate with character speech reenforced | 4464 | if (type !== 'quiet') { |
| 4481 | // to make sure we leave on swipe type while also adding the name2 appendage | 4465 | playMessageSound(); |
| 4482 | await delay(1000); | ||
| 4483 | // A message was already deleted on regeneration, so instead treat is as a normal gen | ||
| 4484 | if (type === 'regenerate') { | ||
| 4485 | type = 'normal'; | ||
| 4486 | } | ||
| 4487 | // The first await is for waiting for the generate to start. The second one is waiting for it to finish | ||
| 4488 | const result = await await Generate(type, { automatic_trigger, force_name2: true, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage, quietName, maxLoops: maxLoops - 1 }); | ||
| 4489 | return result; | ||
| 4490 | } | 4466 | } |
| 4491 | 4467 | ||
| 4492 | if (power_user.auto_swipe) { | 4468 | if (power_user.auto_swipe) { |
| @@ -5259,11 +5235,6 @@ function getGenerateUrl(api) { | |||
| 5259 | } | 5235 | } |
| 5260 | } | 5236 | } |
| 5261 | 5237 | ||
| 5262 | function throwCircuitBreakerError() { | ||
| 5263 | callPopup(`Could not extract reply in ${MAX_GENERATION_LOOPS} attempts. Try generating again`, 'text'); | ||
| 5264 | unblockGeneration(); | ||
| 5265 | } | ||
| 5266 | |||
| 5267 | function extractTitleFromData(data) { | 5238 | function extractTitleFromData(data) { |
| 5268 | if (main_api == 'koboldhorde') { | 5239 | if (main_api == 'koboldhorde') { |
| 5269 | return data.workerName; | 5240 | return data.workerName; |