Merge pull request #3606 from SillyTavern/reasoning-continue-fix Fix continue duplicating reasoning block

5d255d758ebb2516e54342edae04d2e18a3ae443

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
2 files changed, +57 -8Showing whitespace changes
public/script.js+15 -5
@@ -3135,8 +3135,9 @@ class StreamingProcessor {
31353135 * @param {boolean} forceName2 If true, force the use of name2
31363136 * @param {Date} timeStarted Date when generation was started
31373137 * @param {string} continueMessage Previous message if the type is 'continue'
3138+ * @param {PromptReasoning} promptReasoning Prompt reasoning instance
31383139 */
31393140 constructor(type, forceName2, timeStarted, continueMessage, promptReasoning) {
31403141 this.result = '';
31413142 this.messageId = -1;
31423143 /** @type {HTMLElement} */
@@ -3164,6 +3165,8 @@ class StreamingProcessor {
31643165 this.toolCalls = [];
31653166 // Initialize reasoning in its own handler
31663167 this.reasoningHandler = new ReasoningHandler(timeStarted);
3168+ /** @type {PromptReasoning} */
3169+ this.promptReasoning = promptReasoning;
31673170 }
31683171
31693172 #checkDomElements(messageId) {
@@ -3192,6 +3195,10 @@ class StreamingProcessor {
31923195 }
31933196
31943197 async onStartStreaming(text) {
3198+ if (this.type === 'continue' && this.promptReasoning.prefixReasoning) {
3199+ this.reasoningHandler.initContinue(this.promptReasoning);
3200+ }
3201+
31953202 let messageId = -1;
31963203
31973204 if (this.type == 'impersonate') {
@@ -3882,13 +3889,13 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
38823889 };
38833890 }));
38843891
38853892 const reasoningpromptReasoning = new PromptReasoning();
38863893 for (let i = coreChat.length - 1; i >= 0; i--) {
38873894 const depth = coreChat.length - i - 1;
38883895 const isPrefix = isContinue && i === coreChat.length - 1;
38893896 coreChat[i] = {
38903897 ...coreChat[i],
38913898 mes: reasoningpromptReasoning.addToMessage(
38923899 coreChat[i].mes,
38933900 getRegexedString(
38943901 String(coreChat[i].extra?.reasoning ?? ''),
@@ -3896,9 +3903,10 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
38963903 { isPrompt: true, depth: depth },
38973904 ),
38983905 isPrefix,
3906+ coreChat[i].extra?.reasoning_duration,
38993907 ),
39003908 };
39013909 if (reasoningpromptReasoning.isLimitReached()) {
39023910 break;
39033911 }
39043912 }
@@ -4723,7 +4731,8 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
47234731 console.debug(`pushed prompt bits to itemizedPrompts array. Length is now: ${itemizedPrompts.length}`);
47244732
47254733 if (isStreamingEnabled() && type !== 'quiet') {
4726- streamingProcessor = new StreamingProcessor(type, force_name2, generation_started, continue_mag);
4734+ continue_mag = promptReasoning.removePrefix(continue_mag);
4735+ streamingProcessor = new StreamingProcessor(type, force_name2, generation_started, continue_mag, promptReasoning);
47274736 if (isContinue) {
47284737 // Save reply does add cycle text to the prompt, so it's not needed here
47294738 streamingProcessor.firstMessageText = '';
@@ -4824,6 +4833,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
48244833 }
48254834
48264835 if (isContinue) {
4836+ continue_mag = promptReasoning.removePrefix(continue_mag);
48274837 getMessage = continue_mag + getMessage;
48284838 }
48294839
public/scripts/reasoning.js+42 -3
@@ -189,6 +189,17 @@ export class ReasoningHandler {
189189 }
190190
191191 /**
192+ * Sets the reasoning state when continuing a prompt.
193+ * @param {PromptReasoning} promptReasoning Prompt reasoning object
194+ */
195+ initContinue(promptReasoning) {
196+ this.reasoning = promptReasoning.prefixReasoning;
197+ this.state = ReasoningState.Done;
198+ this.startTime = this.initialTime;
199+ this.endTime = promptReasoning.prefixDuration ? new Date(this.initialTime.getTime() + promptReasoning.prefixDuration) : null;
200+ }
201+
202+ /**
192203 * Initializes the reasoning handler for a specific message.
193204 *
194205 * Can be used to update the DOM elements or read other reasoning states.
@@ -514,6 +525,9 @@ export class PromptReasoning {
514525
515526 constructor() {
516527 this.counter = 0;
528+ this.prefixLength = -1;
529+ this.prefixReasoning = '';
530+ this.prefixDuration = null;
517531 }
518532
519533 /**
@@ -533,9 +547,10 @@ export class PromptReasoning {
533547 * @param {string} content Message content
534548 * @param {string} reasoning Message reasoning
535549 * @param {boolean} isPrefix Whether this is the last message prefix
550+ * @param {number?} duration Duration of the reasoning
536551 * @returns {string} Message content with reasoning
537552 */
538553 addToMessage(content, reasoning, isPrefix, duration) {
539554 // Disabled or reached limit of additions
540555 if (!isPrefix && (!power_user.reasoning.add_to_prompts || this.counter >= power_user.reasoning.max_additions)) {
541556 return content;
@@ -556,11 +571,35 @@ export class PromptReasoning {
556571
557572 // Combine parts with reasoning only
558573 if (isPrefix && !content) {
559574 returnconst formattedReasoning = `${prefix}${reasoning}`;
575+ if (isPrefix) {
576+ this.prefixReasoning = reasoning;
577+ this.prefixLength = formattedReasoning.length;
578+ this.prefixDuration = duration;
579+ }
580+ return formattedReasoning;
560581 }
561582
562583 // Combine parts with reasoning and content
563584 returnconst formattedReasoning = `${prefix}${reasoning}${suffix}${separator}${content}`;
585+ if (isPrefix) {
586+ this.prefixReasoning = reasoning;
587+ this.prefixLength = formattedReasoning.length;
588+ this.prefixDuration = duration;
589+ }
590+ return `${formattedReasoning}${content}`;
591+ }
592+
593+ /**
594+ * Removes the reasoning prefix from the content.
595+ * @param {string} content Content with the reasoning prefix
596+ * @returns {string} Content without the reasoning prefix
597+ */
598+ removePrefix(content) {
599+ if (this.prefixLength > 0) {
600+ return content.slice(this.prefixLength);
601+ }
602+ return content;
564603 }
565604}
566605