Add regex processing for reasoning blocks

6fc342d446f8bf6368852c0a2528c901a6e0a1b7

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

3 files changed, +49 -17Showing whitespace changes
public/script.js+42 -17
@@ -1993,9 +1993,10 @@ export async function sendTextareaMessage() {
19931993 * @param {boolean} isUser If the message was sent by the user
19941994 * @param {number} messageId Message index in chat array
19951995 * @param {object} [sanitizerOverrides] DOMPurify sanitizer option overrides
1996+ * @param {boolean} [isReasoning] If the message is reasoning output
19961997 * @returns {string} HTML string
19971998 */
19981999export function messageFormatting(mes, ch_name, isSystem, isUser, messageId, sanitizerOverrides = {}, isReasoning = false) {
19992000 if (!mes) {
20002001 return '';
20012002 }
@@ -2029,6 +2030,9 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId, san
20292030 if (!isSystem) {
20302031 function getRegexPlacement() {
20312032 try {
2033+ if (isReasoning) {
2034+ return regex_placement.REASONING;
2035+ }
20322036 if (isUser) {
20332037 return regex_placement.USER_INPUT;
20342038 } else if (chat[messageId]?.extra?.type === 'narrator') {
@@ -2250,8 +2254,8 @@ function getMessageFromTemplate({
22502254export function updateMessageBlock(messageId, message) {
22512255 const messageElement = $(`#chat [mesid="${messageId}"]`);
22522256 const text = message?.extra?.display_text ?? message.mes;
22532257 messageElement.find('.mes_text').html(messageFormatting(text, message.name, message.is_system, message.is_user, messageId, {}, false));
22542258 messageElement.find('.mes_reasoning').html(messageFormatting(message.extra?.reasoning ?? '', '', false, false, -1messageId, {}, true));
22552259 addCopyToCodeBlocks(messageElement);
22562260 appendMediaToMessage(message, messageElement);
22572261}
@@ -2408,9 +2412,10 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll
24082412 mes.is_user,
24092413 chat.indexOf(mes),
24102414 sanitizerOverrides,
2415+ false,
24112416 );
24122417 const bias = messageFormatting(mes.extra?.bias ?? '', '', false, false, -1, {}, false);
24132418 const reasoning = messageFormatting(mes.extra?.reasoning ?? '', '', false, false, -1chat.indexOf(mes), {}, true);
24142419 let bookmarkLink = mes?.extra?.bookmark_link ?? '';
24152420
24162421 let params = {
@@ -3205,7 +3210,7 @@ class StreamingProcessor {
32053210 if (this.reasoning) {
32063211 chat[messageId]['extra']['reasoning'] = this.reasoning;
32073212 if (this.messageReasoningDom instanceof HTMLElement) {
32083213 const formattedReasoning = messageFormatting(this.reasoning, '', false, false, -1messageId, {}, true);
32093214 this.messageReasoningDom.innerHTML = formattedReasoning;
32103215 }
32113216 }
@@ -3232,6 +3237,8 @@ class StreamingProcessor {
32323237 chat[messageId].is_system,
32333238 chat[messageId].is_user,
32343239 messageId,
3240+ {},
3241+ false,
32353242 );
32363243 if (this.messageTextDom instanceof HTMLElement) {
32373244 this.messageTextDom.innerHTML = formattedText;
@@ -3383,7 +3390,7 @@ class StreamingProcessor {
33833390 if (logprobs) {
33843391 this.messageLogprobs.push(...(Array.isArray(logprobs) ? logprobs : [logprobs]));
33853392 }
33863393 this.reasoning = getRegexedString(state?.reasoning ?? '', regex_placement.REASONING);
33873394 await eventSource.emit(event_types.STREAM_TOKEN_RECEIVED, text);
33883395 await sw.tick(() => this.onProgressStreaming(this.messageId, this.continueMessage + text));
33893396 }
@@ -3850,14 +3857,6 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
38503857 coreChat.pop();
38513858 }
38523859
3853- const reasoning = new PromptReasoning();
3854- for (let i = coreChat.length - 1; i >= 0; i--) {
3855- if (reasoning.isLimitReached()) {
3856- break;
3857- }
3858- coreChat[i] = { ...coreChat[i], mes: reasoning.addToMessage(coreChat[i].mes, coreChat[i].extra?.reasoning) };
3859- }
3860-
38613860 coreChat = await Promise.all(coreChat.map(async (chatItem, index) => {
38623861 let message = chatItem.mes;
38633862 let regexType = chatItem.is_user ? regex_placement.USER_INPUT : regex_placement.AI_OUTPUT;
@@ -3877,6 +3876,25 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
38773876 };
38783877 }));
38793878
3879+ const reasoning = new PromptReasoning();
3880+ for (let i = coreChat.length - 1; i >= 0; i--) {
3881+ if (reasoning.isLimitReached()) {
3882+ break;
3883+ }
3884+ const depth = coreChat.length - i - 1;
3885+ coreChat[i] = {
3886+ mes: reasoning.addToMessage(
3887+ coreChat[i].mes,
3888+ getRegexedString(
3889+ coreChat[i].extra?.reasoning,
3890+ regex_placement.REASONING,
3891+ { isPrompt: true, depth: depth },
3892+ ),
3893+ ),
3894+ ...coreChat[i],
3895+ };
3896+ }
3897+
38803898 // Determine token limit
38813899 let this_max_context = getMaxContextSize();
38823900
@@ -4785,6 +4803,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
47854803 const swipes = extractMultiSwipes(data, type);
47864804
47874805 messageChunk = cleanUpMessage(getMessage, isImpersonate, isContinue, false);
4806+ reasoning = getRegexedString(reasoning, regex_placement.REASONING);
47884807
47894808 if (isContinue) {
47904809 getMessage = continue_mag + getMessage;
@@ -7177,9 +7196,11 @@ function messageEditAuto(div) {
71777196 mes.is_system,
71787197 mes.is_user,
71797198 this_edit_mes_id,
7199+ {},
7200+ false,
71807201 ));
71817202 mesBlock.find('.mes_bias').empty();
71827203 mesBlock.find('.mes_bias').append(messageFormatting(bias, '', false, false, -1, {}, false));
71837204 saveChatDebounced();
71847205}
71857206
@@ -7201,10 +7222,12 @@ async function messageEditDone(div) {
72017222 mes.is_system,
72027223 mes.is_user,
72037224 this_edit_mes_id,
7225+ {},
7226+ false,
72047227 ),
72057228 );
72067229 mesBlock.find('.mes_bias').empty();
72077230 mesBlock.find('.mes_bias').append(messageFormatting(bias, '', false, false, -1, {}, false));
72087231 appendMediaToMessage(mes, div.closest('.mes'));
72097232 addCopyToCodeBlocks(div.closest('.mes'));
72107233
@@ -10841,6 +10864,8 @@ jQuery(async function () {
1084110864 chat[this_edit_mes_id].is_system,
1084210865 chat[this_edit_mes_id].is_user,
1084310866 this_edit_mes_id,
10867+ {},
10868+ false,
1084410869 ));
1084510870 appendMediaToMessage(chat[this_edit_mes_id], $(this).closest('.mes'));
1084610871 addCopyToCodeBlocks($(this).closest('.mes'));
public/scripts/extensions/regex/editor.html+6 -0
@@ -94,6 +94,12 @@
9494 <span data-i18n="World Info">World Info</span>
9595 </label>
9696 </div>
97+ <div data-i18n="[title]ext_regex_reasoning_desc" title="Reasoning block contents. When 'Only Format Prompt' is checked, it will also affect the reasoning contents added to the prompt.">
98+ <label class="checkbox flex-container">
99+ <input type="checkbox" name="replace_position" value="6">
100+ <span data-i18n="Reasoning">Reasoning</span>
101+ </label>
102+ </div>
97103 <div class="flex-container wide100p marginTop5">
98104 <div class="flex1 flex-container flexNoGap">
99105 <small data-i18n="[title]ext_regex_min_depth_desc" title="When applied to prompts or display, only affect messages that are at least N levels deep. 0 = last message, 1 = penultimate message, etc. Only counts WI entries @Depth and usable messages, i.e. not hidden or system.">
public/scripts/extensions/regex/engine.js+1 -0
@@ -20,6 +20,7 @@ const regex_placement = {
2020 SLASH_COMMAND: 3,
2121 // 4 - sendAs (legacy)
2222 WORLD_INFO: 5,
23+ REASONING: 6,
2324};
2425
2526export const substitute_find_regex = {