mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	#1403 Add Aphrodite multi-swipe
This commit is contained in:
		| @@ -1163,6 +1163,10 @@ | |||||||
|                                 </div> |                                 </div> | ||||||
|                             </div><!-- end of novel settings--> |                             </div><!-- end of novel settings--> | ||||||
|                             <div id="textgenerationwebui_api-settings"> |                             <div id="textgenerationwebui_api-settings"> | ||||||
|  |                                 <div data-newbie-hidden data-tg-type="aphrodite" class="flex-container flexFlowColumn alignitemscenter flexBasis100p flexGrow flexShrink gap0"> | ||||||
|  |                                     <small data-i18n="Multiple swipes per generation">Multiple swipes per generation</small> | ||||||
|  |                                     <input type="number" id="n_textgenerationwebui" class="text_pole textAlignCenter" min="1" value="1" /> | ||||||
|  |                                 </div> | ||||||
|                                 <div class="flex-container gap10h5v justifyCenter"> |                                 <div class="flex-container gap10h5v justifyCenter"> | ||||||
|                                     <div class="alignitemscenter flex-container flexFlowColumn flexBasis48p flexGrow flexShrink gap0"> |                                     <div class="alignitemscenter flex-container flexFlowColumn flexBasis48p flexGrow flexShrink gap0"> | ||||||
|                                         <small> |                                         <small> | ||||||
|   | |||||||
| @@ -2536,6 +2536,13 @@ class StreamingProcessor { | |||||||
|     onProgressStreaming(messageId, text, isFinal) { |     onProgressStreaming(messageId, text, isFinal) { | ||||||
|         const isImpersonate = this.type == 'impersonate'; |         const isImpersonate = this.type == 'impersonate'; | ||||||
|         const isContinue = this.type == 'continue'; |         const isContinue = this.type == 'continue'; | ||||||
|  |  | ||||||
|  |         if (!isImpersonate && !isContinue && Array.isArray(this.swipes) && this.swipes.length > 0) { | ||||||
|  |             for (let i = 0; i < this.swipes.length; i++) { | ||||||
|  |                 this.swipes[i] = cleanUpMessage(this.removePrefix(this.swipes[i]), false, false, true); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         text = this.removePrefix(text); |         text = this.removePrefix(text); | ||||||
|         let processedText = cleanUpMessage(text, isImpersonate, isContinue, !isFinal); |         let processedText = cleanUpMessage(text, isImpersonate, isContinue, !isFinal); | ||||||
|  |  | ||||||
| @@ -2598,6 +2605,21 @@ class StreamingProcessor { | |||||||
|         this.onProgressStreaming(messageId, text, true); |         this.onProgressStreaming(messageId, text, true); | ||||||
|         addCopyToCodeBlocks($(`#chat .mes[mesid="${messageId}"]`)); |         addCopyToCodeBlocks($(`#chat .mes[mesid="${messageId}"]`)); | ||||||
|  |  | ||||||
|  |         if (Array.isArray(this.swipes) && this.swipes.length > 0) { | ||||||
|  |             const message = chat[messageId]; | ||||||
|  |             const swipeInfo = { | ||||||
|  |                 send_date: message.send_date, | ||||||
|  |                 gen_started: message.gen_started, | ||||||
|  |                 gen_finished: message.gen_finished, | ||||||
|  |                 extra: structuredClone(message.extra), | ||||||
|  |             }; | ||||||
|  |             const swipeInfoArray = []; | ||||||
|  |             swipeInfoArray.length = this.swipes.length; | ||||||
|  |             swipeInfoArray.fill(swipeInfo); | ||||||
|  |             chat[messageId].swipes.push(...this.swipes); | ||||||
|  |             chat[messageId].swipe_info.push(...swipeInfoArray); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (this.type !== 'impersonate') { |         if (this.type !== 'impersonate') { | ||||||
|             await eventSource.emit(event_types.MESSAGE_RECEIVED, this.messageId); |             await eventSource.emit(event_types.MESSAGE_RECEIVED, this.messageId); | ||||||
|             await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, this.messageId); |             await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, this.messageId); | ||||||
| @@ -2683,6 +2705,7 @@ class StreamingProcessor { | |||||||
|         this.abortController = new AbortController(); |         this.abortController = new AbortController(); | ||||||
|         this.firstMessageText = '...'; |         this.firstMessageText = '...'; | ||||||
|         this.timeStarted = timeStarted; |         this.timeStarted = timeStarted; | ||||||
|  |         this.swipes = []; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async generate() { |     async generate() { | ||||||
| @@ -2693,13 +2716,14 @@ class StreamingProcessor { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         try { |         try { | ||||||
|             for await (const text of this.generator()) { |             for await (const { text, swipes } of this.generator()) { | ||||||
|                 if (this.isStopped) { |                 if (this.isStopped) { | ||||||
|                     this.onStopStreaming(); |                     this.onStopStreaming(); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 this.result = text; |                 this.result = text; | ||||||
|  |                 this.swipes = swipes; | ||||||
|                 this.onProgressStreaming(this.messageId, message_already_generated + text); |                 this.onProgressStreaming(this.messageId, message_already_generated + text); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -3729,6 +3753,8 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, | |||||||
|                     let title = extractTitleFromData(data); |                     let title = extractTitleFromData(data); | ||||||
|                     kobold_horde_model = title; |                     kobold_horde_model = title; | ||||||
|  |  | ||||||
|  |                     const swipes = extractMultiSwipes(data, type); | ||||||
|  |  | ||||||
|                     messageChunk = cleanUpMessage(getMessage, isImpersonate, isContinue, false); |                     messageChunk = cleanUpMessage(getMessage, isImpersonate, isContinue, false); | ||||||
|  |  | ||||||
|                     if (isContinue) { |                     if (isContinue) { | ||||||
| @@ -3751,10 +3777,10 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject, | |||||||
|                         else { |                         else { | ||||||
|                             // Without streaming we'll be having a full message on continuation. Treat it as a last chunk. |                             // Without streaming we'll be having a full message on continuation. Treat it as a last chunk. | ||||||
|                             if (originalType !== 'continue') { |                             if (originalType !== 'continue') { | ||||||
|                                 ({ type, getMessage } = await saveReply(type, getMessage, false, title)); |                                 ({ type, getMessage } = await saveReply(type, getMessage, false, title, swipes)); | ||||||
|                             } |                             } | ||||||
|                             else { |                             else { | ||||||
|                                 ({ type, getMessage } = await saveReply('appendFinal', getMessage, false, title)); |                                 ({ type, getMessage } = await saveReply('appendFinal', getMessage, false, title, swipes)); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                         activateSendButtons(); |                         activateSendButtons(); | ||||||
| @@ -4337,6 +4363,35 @@ function extractMessageFromData(data) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Extracts multiswipe swipes from the response data. | ||||||
|  |  * @param {Object} data Response data | ||||||
|  |  * @param {string} type Type of generation | ||||||
|  |  * @returns {string[]} Array of extra swipes | ||||||
|  |  */ | ||||||
|  | function extractMultiSwipes(data, type) { | ||||||
|  |     const swipes = []; | ||||||
|  |  | ||||||
|  |     if (type === 'continue' || type === 'impersonate') { | ||||||
|  |         return swipes; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (main_api === 'textgenerationwebui' && textgenerationwebui_settings.type === textgen_types.APHRODITE) { | ||||||
|  |         const multiSwipeCount = data.choices.length - 1; | ||||||
|  |  | ||||||
|  |         if (multiSwipeCount <= 0) { | ||||||
|  |             return swipes; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         for (let i = 1; i < data.choices.length; i++) { | ||||||
|  |             const text = cleanUpMessage(data.choices[i].text, false, false, false); | ||||||
|  |             swipes.push(text); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return swipes; | ||||||
|  | } | ||||||
|  |  | ||||||
| function cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncompleteSentences = false) { | function cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncompleteSentences = false) { | ||||||
|     if (!getMessage) { |     if (!getMessage) { | ||||||
|         return ''; |         return ''; | ||||||
| @@ -4471,7 +4526,7 @@ function cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncomplete | |||||||
|     return getMessage; |     return getMessage; | ||||||
| } | } | ||||||
|  |  | ||||||
| async function saveReply(type, getMessage, fromStreaming, title) { | async function saveReply(type, getMessage, fromStreaming, title, swipes) { | ||||||
|     if (type != 'append' && type != 'continue' && type != 'appendFinal' && chat.length && (chat[chat.length - 1]['swipe_id'] === undefined || |     if (type != 'append' && type != 'continue' && type != 'appendFinal' && chat.length && (chat[chat.length - 1]['swipe_id'] === undefined || | ||||||
|         chat[chat.length - 1]['is_user'])) { |         chat[chat.length - 1]['is_user'])) { | ||||||
|         type = 'normal'; |         type = 'normal'; | ||||||
| @@ -4605,6 +4660,21 @@ async function saveReply(type, getMessage, fromStreaming, title) { | |||||||
|             extra: JSON.parse(JSON.stringify(chat[chat.length - 1]['extra'])), |             extra: JSON.parse(JSON.stringify(chat[chat.length - 1]['extra'])), | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (Array.isArray(swipes) && swipes.length > 0) { | ||||||
|  |         const swipeInfo = { | ||||||
|  |             send_date: item.send_date, | ||||||
|  |             gen_started: item.gen_started, | ||||||
|  |             gen_finished: item.gen_finished, | ||||||
|  |             extra: structuredClone(item.extra), | ||||||
|  |         }; | ||||||
|  |         const swipeInfoArray = []; | ||||||
|  |         swipeInfoArray.length = swipes.length; | ||||||
|  |         swipeInfoArray.fill(swipeInfo, 0, swipes.length); | ||||||
|  |         item.swipes.push(...swipes); | ||||||
|  |         item.swipe_info.push(...swipeInfoArray); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     statMesProcess(chat[chat.length - 1], type, characters, this_chid, oldMessage); |     statMesProcess(chat[chat.length - 1], type, characters, this_chid, oldMessage); | ||||||
|     return { type, getMessage }; |     return { type, getMessage }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -183,7 +183,7 @@ export async function generateKoboldWithStreaming(generate_data, signal) { | |||||||
|                     if (subEvent.startsWith('data')) { |                     if (subEvent.startsWith('data')) { | ||||||
|                         let data = JSON.parse(subEvent.substring(5)); |                         let data = JSON.parse(subEvent.substring(5)); | ||||||
|                         getMessage += (data?.token || ''); |                         getMessage += (data?.token || ''); | ||||||
|                         yield getMessage; |                         yield { text: getMessage, swipes: [] }; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -714,7 +714,7 @@ export async function generateNovelWithStreaming(generate_data, signal) { | |||||||
|                     if (subEvent.startsWith('data')) { |                     if (subEvent.startsWith('data')) { | ||||||
|                         let data = JSON.parse(subEvent.substring(5)); |                         let data = JSON.parse(subEvent.substring(5)); | ||||||
|                         getMessage += (data?.token || ''); |                         getMessage += (data?.token || ''); | ||||||
|                         yield getMessage; |                         yield { text: getMessage, swipes: [] }; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -1614,7 +1614,7 @@ async function sendOpenAIRequest(type, messages, signal) { | |||||||
|                     let data = JSON.parse(event.substring(6)); |                     let data = JSON.parse(event.substring(6)); | ||||||
|                     // the first and last messages are undefined, protect against that |                     // the first and last messages are undefined, protect against that | ||||||
|                     getMessage = getStreamingReply(getMessage, data); |                     getMessage = getStreamingReply(getMessage, data); | ||||||
|                     yield getMessage; |                     yield { text: getMessage, swipes: [] }; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (done) { |                 if (done) { | ||||||
|   | |||||||
| @@ -88,6 +88,7 @@ const textgenerationwebui_settings = { | |||||||
|     mancer_model: 'mytholite', |     mancer_model: 'mytholite', | ||||||
|     legacy_api: false, |     legacy_api: false, | ||||||
|     sampler_order: KOBOLDCPP_ORDER, |     sampler_order: KOBOLDCPP_ORDER, | ||||||
|  |     n: 1, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export let textgenerationwebui_banned_in_macros = []; | export let textgenerationwebui_banned_in_macros = []; | ||||||
| @@ -139,6 +140,7 @@ const setting_names = [ | |||||||
|     //'log_probs_aphrodite', |     //'log_probs_aphrodite', | ||||||
|     //'prompt_log_probs_aphrodite' |     //'prompt_log_probs_aphrodite' | ||||||
|     'sampler_order', |     'sampler_order', | ||||||
|  |     'n', | ||||||
| ]; | ]; | ||||||
|  |  | ||||||
| async function selectPreset(name) { | async function selectPreset(name) { | ||||||
| @@ -495,6 +497,7 @@ async function generateTextGenWithStreaming(generate_data, signal) { | |||||||
|         const reader = response.body.getReader(); |         const reader = response.body.getReader(); | ||||||
|         let getMessage = ''; |         let getMessage = ''; | ||||||
|         let messageBuffer = ''; |         let messageBuffer = ''; | ||||||
|  |         const swipes = []; | ||||||
|         while (true) { |         while (true) { | ||||||
|             const { done, value } = await reader.read(); |             const { done, value } = await reader.read(); | ||||||
|             // We don't want carriage returns in our messages |             // We don't want carriage returns in our messages | ||||||
| @@ -523,9 +526,15 @@ async function generateTextGenWithStreaming(generate_data, signal) { | |||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|                 let data = JSON.parse(event.substring(6)); |                 let data = JSON.parse(event.substring(6)); | ||||||
|                 // the first and last messages are undefined, protect against that |  | ||||||
|                 getMessage += data?.choices[0]?.text || ''; |                 if (data?.choices[0]?.index > 0) { | ||||||
|                 yield getMessage; |                     const swipeIndex = data.choices[0].index - 1; | ||||||
|  |                     swipes[swipeIndex] = (swipes[swipeIndex] || '') + data.choices[0].text; | ||||||
|  |                 } else { | ||||||
|  |                     getMessage += data?.choices[0]?.text || ''; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 yield { text: getMessage, swipes: swipes }; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (done) { |             if (done) { | ||||||
| @@ -578,6 +587,7 @@ function getModel() { | |||||||
| } | } | ||||||
|  |  | ||||||
| export function getTextGenGenerationData(finalPrompt, maxTokens, isImpersonate, isContinue, cfgValues) { | export function getTextGenGenerationData(finalPrompt, maxTokens, isImpersonate, isContinue, cfgValues) { | ||||||
|  |     const canMultiSwipe = !isContinue && !isImpersonate; | ||||||
|     let APIflags = { |     let APIflags = { | ||||||
|         'prompt': finalPrompt, |         'prompt': finalPrompt, | ||||||
|         'model': getModel(), |         'model': getModel(), | ||||||
| @@ -632,8 +642,8 @@ export function getTextGenGenerationData(finalPrompt, maxTokens, isImpersonate, | |||||||
|         'grammar_string': textgenerationwebui_settings.grammar_string, |         'grammar_string': textgenerationwebui_settings.grammar_string, | ||||||
|     }; |     }; | ||||||
|     let aphroditeFlags = { |     let aphroditeFlags = { | ||||||
|         //'n': textgenerationwebui_settings.n_aphrodite, |         'n': canMultiSwipe ? textgenerationwebui_settings.n : 1, | ||||||
|         //'best_of': textgenerationwebui_settings.n_aphrodite, //n must always == best_of and vice versa |         'best_of': canMultiSwipe ? textgenerationwebui_settings.n : 1, | ||||||
|         'ignore_eos': textgenerationwebui_settings.ignore_eos_token_aphrodite, |         'ignore_eos': textgenerationwebui_settings.ignore_eos_token_aphrodite, | ||||||
|         'spaces_between_special_tokens': textgenerationwebui_settings.spaces_between_special_tokens_aphrodite, |         'spaces_between_special_tokens': textgenerationwebui_settings.spaces_between_special_tokens_aphrodite, | ||||||
|         //'logits_processors': textgenerationwebui_settings.logits_processors_aphrodite, |         //'logits_processors': textgenerationwebui_settings.logits_processors_aphrodite, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user