Move reasoning stuff to reasoning.js

This commit is contained in:
Wolfsblvt
2025-02-06 21:50:33 +01:00
parent 1acee3d4c9
commit 06303bb62f
2 changed files with 81 additions and 77 deletions

View File

@ -225,7 +225,7 @@ import {
instruct_presets, instruct_presets,
selectContextPreset, selectContextPreset,
} from './scripts/instruct-mode.js'; } from './scripts/instruct-mode.js';
import { getCurrentLocale, initLocales, t } from './scripts/i18n.js'; import { initLocales, t } from './scripts/i18n.js';
import { getFriendlyTokenizerName, getTokenCount, getTokenCountAsync, initTokenizers, saveTokenCache, TOKENIZER_SUPPORTED_KEY } from './scripts/tokenizers.js'; import { getFriendlyTokenizerName, getTokenCount, getTokenCountAsync, initTokenizers, saveTokenCache, TOKENIZER_SUPPORTED_KEY } from './scripts/tokenizers.js';
import { import {
user_avatar, user_avatar,
@ -269,7 +269,7 @@ import { initSettingsSearch } from './scripts/setting-search.js';
import { initBulkEdit } from './scripts/bulk-edit.js'; import { initBulkEdit } from './scripts/bulk-edit.js';
import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js'; import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js';
import { getContext } from './scripts/st-context.js'; import { getContext } from './scripts/st-context.js';
import { initReasoning, PromptReasoning } from './scripts/reasoning.js'; import { extractReasoningFromData, initReasoning, PromptReasoning, updateReasoningTimeUI } from './scripts/reasoning.js';
// API OBJECT FOR EXTERNAL WIRING // API OBJECT FOR EXTERNAL WIRING
globalThis.SillyTavern = { globalThis.SillyTavern = {
@ -5763,56 +5763,6 @@ function extractMessageFromData(data) {
} }
} }
/**
* Extracts the reasoning from the response data.
* @param {object} data Response data
* @returns {string} Extracted reasoning
*/
function extractReasoningFromData(data) {
switch (main_api) {
case 'textgenerationwebui':
switch (textgen_settings.type) {
case textgen_types.OPENROUTER:
return data?.choices?.[0]?.reasoning ?? '';
}
break;
case 'openai':
if (!oai_settings.show_thoughts) break;
switch (oai_settings.chat_completion_source) {
case chat_completion_sources.DEEPSEEK:
return data?.choices?.[0]?.message?.reasoning_content ?? '';
case chat_completion_sources.OPENROUTER:
return data?.choices?.[0]?.message?.reasoning ?? '';
case chat_completion_sources.MAKERSUITE:
return data?.responseContent?.parts?.filter(part => part.thought)?.map(part => part.text)?.join('\n\n') ?? '';
}
break;
}
return '';
}
/**
* Updates the Reasoning controls
* @param {HTMLElement} element The element to update
* @param {number?} duration The duration of the reasoning in milliseconds
* @param {object} [options={}] Options for the function
* @param {boolean} [options.forceEnd=false] If true, there will be no "Thinking..." when no duration exists
*/
function updateReasoningTimeUI(element, duration, { forceEnd = false } = {}) {
if (duration) {
const durationStr = moment.duration(duration).locale(getCurrentLocale()).humanize({ s: 50, ss: 9 });
element.textContent = t`Thought for ${durationStr}`;
} else if (forceEnd) {
element.textContent = t`Thought for some time`;
} else {
element.textContent = t`Thinking...`;
}
}
/** /**
* Extracts multiswipe swipes from the response data. * Extracts multiswipe swipes from the response data.
* @param {Object} data Response data * @param {Object} data Response data
@ -10872,18 +10822,6 @@ jQuery(async function () {
} }
}); });
$(document).on('click', '.mes_reasoning_header', function () {
// If we are in message edit mode and reasoning area is closed, a click opens and edits it
const mes = $(this).closest('.mes');
const mesEditArea = mes.find('#curEditTextarea');
if (mesEditArea.length) {
const summary = $(mes).find('.mes_reasoning_summary');
if (!summary.attr('open')) {
summary.find('.mes_reasoning_edit').trigger('click');
}
}
});
$(document).on('input', '#curEditTextarea', function () { $(document).on('input', '#curEditTextarea', function () {
if (power_user.auto_save_msg_edits === true) { if (power_user.auto_save_msg_edits === true) {
messageEditAuto($(this)); messageEditAuto($(this));
@ -11438,17 +11376,6 @@ jQuery(async function () {
} }
}); });
$(document).on('click', '.mes_reasoning_summary', function () {
// If you toggle summary header while editing reasoning, yup - we just cancel it
$(this).closest('.mes').find('.mes_reasoning_edit_cancel:visible').trigger('click');
});
$(document).on('click', '.mes_reasoning_details', function (e) {
if (!e.target.closest('.mes_reasoning_actions') && !e.target.closest('.mes_reasoning_header')) {
e.preventDefault();
}
});
$(document).keyup(function (e) { $(document).keyup(function (e) {
if (e.key === 'Escape') { if (e.key === 'Escape') {
const isEditVisible = $('#curEditTextarea').is(':visible') || $('.reasoning_edit_textarea').length > 0; const isEditVisible = $('#curEditTextarea').is(':visible') || $('.reasoning_edit_textarea').length > 0;

View File

@ -1,13 +1,18 @@
import { chat, closeMessageEditor, event_types, eventSource, saveChatConditional, saveSettingsDebounced, substituteParams, updateMessageBlock } from '../script.js'; import {
moment,
} from '../lib.js';
import { chat, closeMessageEditor, event_types, eventSource, main_api, saveChatConditional, saveSettingsDebounced, substituteParams, updateMessageBlock } from '../script.js';
import { getRegexedString, regex_placement } from './extensions/regex/engine.js'; import { getRegexedString, regex_placement } from './extensions/regex/engine.js';
import { t } from './i18n.js'; import { getCurrentLocale, t } from './i18n.js';
import { MacrosParser } from './macros.js'; import { MacrosParser } from './macros.js';
import { chat_completion_sources, oai_settings } from './openai.js';
import { Popup } from './popup.js'; import { Popup } from './popup.js';
import { power_user } from './power-user.js'; import { power_user } from './power-user.js';
import { SlashCommand } from './slash-commands/SlashCommand.js'; import { SlashCommand } from './slash-commands/SlashCommand.js';
import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js'; import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js';
import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js'; import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js';
import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js';
import { copyText, escapeRegex, isFalseBoolean } from './utils.js'; import { copyText, escapeRegex, isFalseBoolean } from './utils.js';
/** /**
@ -34,6 +39,55 @@ function toggleReasoningAutoExpand() {
}); });
} }
/**
* Extracts the reasoning from the response data.
* @param {object} data Response data
* @returns {string} Extracted reasoning
*/
export function extractReasoningFromData(data) {
switch (main_api) {
case 'textgenerationwebui':
switch (textgenerationwebui_settings.type) {
case textgen_types.OPENROUTER:
return data?.choices?.[0]?.reasoning ?? '';
}
break;
case 'openai':
if (!oai_settings.show_thoughts) break;
switch (oai_settings.chat_completion_source) {
case chat_completion_sources.DEEPSEEK:
return data?.choices?.[0]?.message?.reasoning_content ?? '';
case chat_completion_sources.OPENROUTER:
return data?.choices?.[0]?.message?.reasoning ?? '';
case chat_completion_sources.MAKERSUITE:
return data?.responseContent?.parts?.filter(part => part.thought)?.map(part => part.text)?.join('\n\n') ?? '';
}
break;
}
return '';
}
/**
* Updates the Reasoning controls
* @param {HTMLElement} element The element to update
* @param {number?} duration The duration of the reasoning in milliseconds
* @param {object} [options={}] Options for the function
* @param {boolean} [options.forceEnd=false] If true, there will be no "Thinking..." when no duration exists
*/
export function updateReasoningTimeUI(element, duration, { forceEnd = false } = {}) {
if (duration) {
const durationStr = moment.duration(duration).locale(getCurrentLocale()).humanize({ s: 50, ss: 9 });
element.textContent = t`Thought for ${durationStr}`;
} else if (forceEnd) {
element.textContent = t`Thought for some time`;
} else {
element.textContent = t`Thinking...`;
}
}
/** /**
* Helper class for adding reasoning to messages. * Helper class for adding reasoning to messages.
* Keeps track of the number of reasoning additions. * Keeps track of the number of reasoning additions.
@ -247,6 +301,29 @@ function registerReasoningMacros() {
} }
function setReasoningEventHandlers() { function setReasoningEventHandlers() {
$(document).on('click', '.mes_reasoning_summary', function () {
// If you toggle summary header while editing reasoning, yup - we just cancel it
$(this).closest('.mes').find('.mes_reasoning_edit_cancel:visible').trigger('click');
});
$(document).on('click', '.mes_reasoning_details', function (e) {
if (!e.target.closest('.mes_reasoning_actions') && !e.target.closest('.mes_reasoning_header')) {
e.preventDefault();
}
});
$(document).on('click', '.mes_reasoning_header', function () {
// If we are in message edit mode and reasoning area is closed, a click opens and edits it
const mes = $(this).closest('.mes');
const mesEditArea = mes.find('#curEditTextarea');
if (mesEditArea.length) {
const summary = $(mes).find('.mes_reasoning_summary');
if (!summary.attr('open')) {
summary.find('.mes_reasoning_edit').trigger('click');
}
}
});
$(document).on('click', '.mes_reasoning_copy', (e) => { $(document).on('click', '.mes_reasoning_copy', (e) => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();