Reasoning template
| @@ -786,5 +786,9 @@ | |||
| 786 | { | 786 | { |
| 787 | "filename": "presets/context/DeepSeek-V2.5.json", | 787 | "filename": "presets/context/DeepSeek-V2.5.json", |
| 788 | "type": "context" | 788 | "type": "context" |
| 789 | }, | ||
| 790 | { | ||
| 791 | "filename": "presets/reasoning/DeepSeek R1.json", | ||
| 792 | "type": "reasoning" | ||
| 789 | } | 793 | } |
| 790 | ] | 794 | ] |
| @@ -0,0 +1,6 @@ | |||
| 1 | { | ||
| 2 | "name": "DeepSeek R1", | ||
| 3 | "prefix": "<think>\n", | ||
| 4 | "suffix": "\n</think>", | ||
| 5 | "separator": "\n\n" | ||
| 6 | } | ||
| @@ -3917,6 +3917,19 @@ | |||
| 3917 | <summary data-i18n="Reasoning Formatting"> | 3917 | <summary data-i18n="Reasoning Formatting"> |
| 3918 | Reasoning Formatting | 3918 | Reasoning Formatting |
| 3919 | </summary> | 3919 | </summary> |
| 3920 | <div class="flex-container" title="Select your current Reasoning Template" data-i18n="[title]Select your current Reasoning Template"> | ||
| 3921 | <select id="reasoning_select" data-preset-manager-for="reasoning" class="flex1 text_pole"></select> | ||
| 3922 | <div class="flex-container margin0 justifyCenter gap3px"> | ||
| 3923 | <input type="file" hidden data-preset-manager-file="reasoning" accept=".json, .settings"> | ||
| 3924 | <i data-preset-manager-update="reasoning" class="menu_button fa-solid fa-save" title="Update current template" data-i18n="[title]Update current template"></i> | ||
| 3925 | <i data-preset-manager-rename="reasoning" class="menu_button fa-pencil fa-solid" title="Rename current template" data-i18n="[title]Rename current template"></i> | ||
| 3926 | <i data-preset-manager-new="reasoning" class="menu_button fa-solid fa-file-circle-plus" title="Save template as" data-i18n="[title]Save template as"></i> | ||
| 3927 | <i data-preset-manager-import="reasoning" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i> | ||
| 3928 | <i data-preset-manager-export="reasoning" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i> | ||
| 3929 | <i data-preset-manager-restore="reasoning" class="menu_button fa-solid fa-recycle" title="Restore current template" data-i18n="[title]Restore current template"></i> | ||
| 3930 | <i data-preset-manager-delete="reasoning" class="menu_button fa-solid fa-trash-can" title="Delete template" data-i18n="[title]Delete template"></i> | ||
| 3931 | </div> | ||
| 3932 | </div> | ||
| 3920 | <div class="flex-container"> | 3933 | <div class="flex-container"> |
| 3921 | <div class="flex1" title="Inserted before the reasoning content." data-i18n="[title]reasoning_prefix"> | 3934 | <div class="flex1" title="Inserted before the reasoning content." data-i18n="[title]reasoning_prefix"> |
| 3922 | <small data-i18n="Prefix">Prefix</small> | 3935 | <small data-i18n="Prefix">Prefix</small> |
| @@ -55,6 +55,7 @@ import { POPUP_TYPE, callGenericPopup } from './popup.js'; | |||
| 55 | import { loadSystemPrompts } from './sysprompt.js'; | 55 | import { loadSystemPrompts } from './sysprompt.js'; |
| 56 | import { fuzzySearchCategories } from './filters.js'; | 56 | import { fuzzySearchCategories } from './filters.js'; |
| 57 | import { accountStorage } from './util/AccountStorage.js'; | 57 | import { accountStorage } from './util/AccountStorage.js'; |
| 58 | import { loadReasoningTemplates } from './reasoning.js'; | ||
| 58 | 59 | ||
| 59 | export { | 60 | export { |
| 60 | loadPowerUserSettings, | 61 | loadPowerUserSettings, |
| @@ -255,6 +256,7 @@ let power_user = { | |||
| 255 | }, | 256 | }, |
| 256 | 257 | ||
| 257 | reasoning: { | 258 | reasoning: { |
| 259 | name: 'DeepSeek R1', | ||
| 258 | auto_parse: false, | 260 | auto_parse: false, |
| 259 | add_to_prompts: false, | 261 | add_to_prompts: false, |
| 260 | auto_expand: false, | 262 | auto_expand: false, |
| @@ -1622,6 +1624,7 @@ async function loadPowerUserSettings(settings, data) { | |||
| 1622 | await loadInstructMode(data); | 1624 | await loadInstructMode(data); |
| 1623 | await loadContextSettings(); | 1625 | await loadContextSettings(); |
| 1624 | await loadSystemPrompts(data); | 1626 | await loadSystemPrompts(data); |
| 1627 | await loadReasoningTemplates(data); | ||
| 1625 | loadMaxContextUnlocked(); | 1628 | loadMaxContextUnlocked(); |
| 1626 | switchWaifuMode(); | 1629 | switchWaifuMode(); |
| 1627 | switchSpoilerMode(); | 1630 | switchSpoilerMode(); |
| @@ -21,7 +21,7 @@ import { groups, selected_group } from './group-chats.js'; | |||
| 21 | import { instruct_presets } from './instruct-mode.js'; | 21 | import { instruct_presets } from './instruct-mode.js'; |
| 22 | import { kai_settings } from './kai-settings.js'; | 22 | import { kai_settings } from './kai-settings.js'; |
| 23 | import { convertNovelPreset } from './nai-settings.js'; | 23 | import { convertNovelPreset } from './nai-settings.js'; |
| 24 | import { openai_settings, openai_setting_names, oai_settings } from './openai.js'; | 24 | import { openai_settings, openai_setting_names } from './openai.js'; |
| 25 | import { Popup, POPUP_RESULT, POPUP_TYPE } from './popup.js'; | 25 | import { Popup, POPUP_RESULT, POPUP_TYPE } from './popup.js'; |
| 26 | import { context_presets, getContextSettings, power_user } from './power-user.js'; | 26 | import { context_presets, getContextSettings, power_user } from './power-user.js'; |
| 27 | import { SlashCommand } from './slash-commands/SlashCommand.js'; | 27 | import { SlashCommand } from './slash-commands/SlashCommand.js'; |
| @@ -38,6 +38,7 @@ import { | |||
| 38 | } from './textgen-settings.js'; | 38 | } from './textgen-settings.js'; |
| 39 | import { download, parseJsonFile, waitUntilCondition } from './utils.js'; | 39 | import { download, parseJsonFile, waitUntilCondition } from './utils.js'; |
| 40 | import { t } from './i18n.js'; | 40 | import { t } from './i18n.js'; |
| 41 | import { reasoning_templates } from './reasoning.js'; | ||
| 41 | 42 | ||
| 42 | const presetManagers = {}; | 43 | const presetManagers = {}; |
| 43 | 44 | ||
| @@ -168,6 +169,20 @@ class PresetManager { | |||
| 168 | }, | 169 | }, |
| 169 | isValid: (data) => PresetManager.isPossiblyTextCompletionData(data), | 170 | isValid: (data) => PresetManager.isPossiblyTextCompletionData(data), |
| 170 | }, | 171 | }, |
| 172 | 'reasoning': { | ||
| 173 | name: 'Reasoning Formatting', | ||
| 174 | getData: () => { | ||
| 175 | const manager = getPresetManager('reasoning'); | ||
| 176 | const name = manager.getSelectedPresetName(); | ||
| 177 | return manager.getPresetSettings(name); | ||
| 178 | }, | ||
| 179 | setData: (data) => { | ||
| 180 | const manager = getPresetManager('reasoning'); | ||
| 181 | const name = data.name; | ||
| 182 | return manager.savePreset(name, data); | ||
| 183 | }, | ||
| 184 | isValid: (data) => PresetManager.isPossiblyReasoningData(data), | ||
| 185 | }, | ||
| 171 | }; | 186 | }; |
| 172 | 187 | ||
| 173 | static isPossiblyInstructData(data) { | 188 | static isPossiblyInstructData(data) { |
| @@ -190,6 +205,11 @@ class PresetManager { | |||
| 190 | return data && textCompletionProps.every(prop => Object.keys(data).includes(prop)); | 205 | return data && textCompletionProps.every(prop => Object.keys(data).includes(prop)); |
| 191 | } | 206 | } |
| 192 | 207 | ||
| 208 | static isPossiblyReasoningData(data) { | ||
| 209 | const reasoningProps = ['name', 'prefix', 'suffix', 'separator']; | ||
| 210 | return data && reasoningProps.every(prop => Object.keys(data).includes(prop)); | ||
| 211 | } | ||
| 212 | |||
| 193 | /** | 213 | /** |
| 194 | * Imports master settings from JSON data. | 214 | * Imports master settings from JSON data. |
| 195 | * @param {object} data Data to import | 215 | * @param {object} data Data to import |
| @@ -227,6 +247,12 @@ class PresetManager { | |||
| 227 | return await getPresetManager('textgenerationwebui').savePreset(fileName, data); | 247 | return await getPresetManager('textgenerationwebui').savePreset(fileName, data); |
| 228 | } | 248 | } |
| 229 | 249 | ||
| 250 | // 5. Reasoning Template | ||
| 251 | if (this.isPossiblyReasoningData(data)) { | ||
| 252 | toastr.info(t`Importing as reasoning template...`, t`Reasoning template detected`); | ||
| 253 | return await getPresetManager('reasoning').savePreset(data.name, data); | ||
| 254 | } | ||
| 255 | |||
| 230 | const validSections = []; | 256 | const validSections = []; |
| 231 | for (const [key, section] of Object.entries(this.masterSections)) { | 257 | for (const [key, section] of Object.entries(this.masterSections)) { |
| 232 | if (key in data && section.isValid(data[key])) { | 258 | if (key in data && section.isValid(data[key])) { |
| @@ -478,6 +504,10 @@ class PresetManager { | |||
| 478 | presets = system_prompts; | 504 | presets = system_prompts; |
| 479 | preset_names = system_prompts.map(x => x.name); | 505 | preset_names = system_prompts.map(x => x.name); |
| 480 | break; | 506 | break; |
| 507 | case 'reasoning': | ||
| 508 | presets = reasoning_templates; | ||
| 509 | preset_names = reasoning_templates.map(x => x.name); | ||
| 510 | break; | ||
| 481 | default: | 511 | default: |
| 482 | console.warn(`Unknown API ID ${api}`); | 512 | console.warn(`Unknown API ID ${api}`); |
| 483 | } | 513 | } |
| @@ -490,7 +520,7 @@ class PresetManager { | |||
| 490 | } | 520 | } |
| 491 | 521 | ||
| 492 | isAdvancedFormatting() { | 522 | isAdvancedFormatting() { |
| 493 | return this.apiId == 'context' || this.apiId == 'instruct' || this.apiId == 'sysprompt'; | 523 | return ['context', 'instruct', 'sysprompt', 'reasoning'].includes(this.apiId); |
| 494 | } | 524 | } |
| 495 | 525 | ||
| 496 | updateList(name, preset) { | 526 | updateList(name, preset) { |
| @@ -553,6 +583,11 @@ class PresetManager { | |||
| 553 | sysprompt_preset['name'] = name || power_user.sysprompt.preset; | 583 | sysprompt_preset['name'] = name || power_user.sysprompt.preset; |
| 554 | return sysprompt_preset; | 584 | return sysprompt_preset; |
| 555 | } | 585 | } |
| 586 | case 'reasoning': { | ||
| 587 | const reasoning_preset = structuredClone(power_user.reasoning); | ||
| 588 | reasoning_preset['name'] = name || power_user.reasoning.preset; | ||
| 589 | return reasoning_preset; | ||
| 590 | } | ||
| 556 | default: | 591 | default: |
| 557 | console.warn(`Unknown API ID ${apiId}`); | 592 | console.warn(`Unknown API ID ${apiId}`); |
| 558 | return {}; | 593 | return {}; |
| @@ -599,6 +634,13 @@ class PresetManager { | |||
| 599 | 'include_reasoning', | 634 | 'include_reasoning', |
| 600 | 'global_banned_tokens', | 635 | 'global_banned_tokens', |
| 601 | 'send_banned_tokens', | 636 | 'send_banned_tokens', |
| 637 | |||
| 638 | // Reasoning exclusions | ||
| 639 | 'auto_parse', | ||
| 640 | 'add_to_prompts', | ||
| 641 | 'auto_expand', | ||
| 642 | 'show_hidden', | ||
| 643 | 'max_additions', | ||
| 602 | ]; | 644 | ]; |
| 603 | const settings = Object.assign({}, getSettingsByApiId(this.apiId)); | 645 | const settings = Object.assign({}, getSettingsByApiId(this.apiId)); |
| 604 | 646 | ||
| @@ -1,4 +1,5 @@ | |||
| 1 | import { | 1 | import { |
| 2 | Fuse, | ||
| 2 | moment, | 3 | moment, |
| 3 | } from '../lib.js'; | 4 | } from '../lib.js'; |
| 4 | import { chat, closeMessageEditor, event_types, eventSource, main_api, messageFormatting, saveChatConditional, saveChatDebounced, saveSettingsDebounced, substituteParams, syncMesToSwipe, updateMessageBlock } from '../script.js'; | 5 | import { chat, closeMessageEditor, event_types, eventSource, main_api, messageFormatting, saveChatConditional, saveChatDebounced, saveSettingsDebounced, substituteParams, syncMesToSwipe, updateMessageBlock } from '../script.js'; |
| @@ -14,7 +15,36 @@ import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCom | |||
| 14 | import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js'; | 15 | import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js'; |
| 15 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; | 16 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; |
| 16 | import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js'; | 17 | import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js'; |
| 17 | import { copyText, escapeRegex, isFalseBoolean, setDatasetProperty, trimSpaces } from './utils.js'; | 18 | import { copyText, escapeRegex, isFalseBoolean, isTrueBoolean, setDatasetProperty, trimSpaces } from './utils.js'; |
| 19 | |||
| 20 | /** | ||
| 21 | * @typedef {object} ReasoningTemplate | ||
| 22 | * @property {string} name - The name of the template | ||
| 23 | * @property {string} prefix - Reasoning prefix | ||
| 24 | * @property {string} suffix - Reasoning suffix | ||
| 25 | * @property {string} separator - Reasoning separator | ||
| 26 | */ | ||
| 27 | |||
| 28 | /** | ||
| 29 | * @type {ReasoningTemplate[]} List of reasoning templates | ||
| 30 | */ | ||
| 31 | export const reasoning_templates = []; | ||
| 32 | |||
| 33 | /** | ||
| 34 | * @type {Record<string, JQuery<HTMLElement>>} List of UI elements for reasoning settings | ||
| 35 | * @readonly | ||
| 36 | */ | ||
| 37 | const UI = { | ||
| 38 | $select: $('#reasoning_select'), | ||
| 39 | $suffix: $('#reasoning_suffix'), | ||
| 40 | $prefix: $('#reasoning_prefix'), | ||
| 41 | $separator: $('#reasoning_separator'), | ||
| 42 | $autoParse: $('#reasoning_auto_parse'), | ||
| 43 | $autoExpand: $('#reasoning_auto_expand'), | ||
| 44 | $showHidden: $('#reasoning_show_hidden'), | ||
| 45 | $addToPrompts: $('#reasoning_add_to_prompts'), | ||
| 46 | $maxAdditions: $('#reasoning_max_additions'), | ||
| 47 | }; | ||
| 18 | 48 | ||
| 19 | /** | 49 | /** |
| 20 | * Enum representing the type of the reasoning for a message (where it came from) | 50 | * Enum representing the type of the reasoning for a message (where it came from) |
| @@ -664,57 +694,103 @@ export class PromptReasoning { | |||
| 664 | } | 694 | } |
| 665 | 695 | ||
| 666 | function loadReasoningSettings() { | 696 | function loadReasoningSettings() { |
| 667 | $('#reasoning_add_to_prompts').prop('checked', power_user.reasoning.add_to_prompts); | 697 | UI.$addToPrompts.prop('checked', power_user.reasoning.add_to_prompts); |
| 668 | $('#reasoning_add_to_prompts').on('change', function () { | 698 | UI.$addToPrompts.on('change', function () { |
| 669 | power_user.reasoning.add_to_prompts = !!$(this).prop('checked'); | 699 | power_user.reasoning.add_to_prompts = !!$(this).prop('checked'); |
| 670 | saveSettingsDebounced(); | 700 | saveSettingsDebounced(); |
| 671 | }); | 701 | }); |
| 672 | 702 | ||
| 673 | $('#reasoning_prefix').val(power_user.reasoning.prefix); | 703 | UI.$prefix.val(power_user.reasoning.prefix); |
| 674 | $('#reasoning_prefix').on('input', function () { | 704 | UI.$prefix.on('input', function () { |
| 675 | power_user.reasoning.prefix = String($(this).val()); | 705 | power_user.reasoning.prefix = String($(this).val()); |
| 676 | saveSettingsDebounced(); | 706 | saveSettingsDebounced(); |
| 677 | }); | 707 | }); |
| 678 | 708 | ||
| 679 | $('#reasoning_suffix').val(power_user.reasoning.suffix); | 709 | UI.$suffix.val(power_user.reasoning.suffix); |
| 680 | $('#reasoning_suffix').on('input', function () { | 710 | UI.$suffix.on('input', function () { |
| 681 | power_user.reasoning.suffix = String($(this).val()); | 711 | power_user.reasoning.suffix = String($(this).val()); |
| 682 | saveSettingsDebounced(); | 712 | saveSettingsDebounced(); |
| 683 | }); | 713 | }); |
| 684 | 714 | ||
| 685 | $('#reasoning_separator').val(power_user.reasoning.separator); | 715 | UI.$separator.val(power_user.reasoning.separator); |
| 686 | $('#reasoning_separator').on('input', function () { | 716 | UI.$separator.on('input', function () { |
| 687 | power_user.reasoning.separator = String($(this).val()); | 717 | power_user.reasoning.separator = String($(this).val()); |
| 688 | saveSettingsDebounced(); | 718 | saveSettingsDebounced(); |
| 689 | }); | 719 | }); |
| 690 | 720 | ||
| 691 | $('#reasoning_max_additions').val(power_user.reasoning.max_additions); | 721 | UI.$maxAdditions.val(power_user.reasoning.max_additions); |
| 692 | $('#reasoning_max_additions').on('input', function () { | 722 | UI.$maxAdditions.on('input', function () { |
| 693 | power_user.reasoning.max_additions = Number($(this).val()); | 723 | power_user.reasoning.max_additions = Number($(this).val()); |
| 694 | saveSettingsDebounced(); | 724 | saveSettingsDebounced(); |
| 695 | }); | 725 | }); |
| 696 | 726 | ||
| 697 | $('#reasoning_auto_parse').prop('checked', power_user.reasoning.auto_parse); | 727 | UI.$autoParse.prop('checked', power_user.reasoning.auto_parse); |
| 698 | $('#reasoning_auto_parse').on('change', function () { | 728 | UI.$autoParse.on('change', function () { |
| 699 | power_user.reasoning.auto_parse = !!$(this).prop('checked'); | 729 | power_user.reasoning.auto_parse = !!$(this).prop('checked'); |
| 700 | saveSettingsDebounced(); | 730 | saveSettingsDebounced(); |
| 701 | }); | 731 | }); |
| 702 | 732 | ||
| 703 | $('#reasoning_auto_expand').prop('checked', power_user.reasoning.auto_expand); | 733 | UI.$autoExpand.prop('checked', power_user.reasoning.auto_expand); |
| 704 | $('#reasoning_auto_expand').on('change', function () { | 734 | UI.$autoExpand.on('change', function () { |
| 705 | power_user.reasoning.auto_expand = !!$(this).prop('checked'); | 735 | power_user.reasoning.auto_expand = !!$(this).prop('checked'); |
| 706 | toggleReasoningAutoExpand(); | 736 | toggleReasoningAutoExpand(); |
| 707 | saveSettingsDebounced(); | 737 | saveSettingsDebounced(); |
| 708 | }); | 738 | }); |
| 709 | toggleReasoningAutoExpand(); | 739 | toggleReasoningAutoExpand(); |
| 710 | 740 | ||
| 711 | $('#reasoning_show_hidden').prop('checked', power_user.reasoning.show_hidden); | 741 | UI.$showHidden.prop('checked', power_user.reasoning.show_hidden); |
| 712 | $('#reasoning_show_hidden').on('change', function () { | 742 | UI.$showHidden.on('change', function () { |
| 713 | power_user.reasoning.show_hidden = !!$(this).prop('checked'); | 743 | power_user.reasoning.show_hidden = !!$(this).prop('checked'); |
| 714 | $('#chat').attr('data-show-hidden-reasoning', power_user.reasoning.show_hidden ? 'true' : null); | 744 | $('#chat').attr('data-show-hidden-reasoning', power_user.reasoning.show_hidden ? 'true' : null); |
| 715 | saveSettingsDebounced(); | 745 | saveSettingsDebounced(); |
| 716 | }); | 746 | }); |
| 717 | $('#chat').attr('data-show-hidden-reasoning', power_user.reasoning.show_hidden ? 'true' : null); | 747 | $('#chat').attr('data-show-hidden-reasoning', power_user.reasoning.show_hidden ? 'true' : null); |
| 748 | |||
| 749 | UI.$select.on('change', async function () { | ||
| 750 | const name = String($(this).val()); | ||
| 751 | const template = reasoning_templates.find(p => p.name === name); | ||
| 752 | if (!template) { | ||
| 753 | return; | ||
| 754 | } | ||
| 755 | |||
| 756 | UI.$prefix.val(template.prefix); | ||
| 757 | UI.$suffix.val(template.suffix); | ||
| 758 | UI.$separator.val(template.separator); | ||
| 759 | |||
| 760 | power_user.reasoning.name = name; | ||
| 761 | power_user.reasoning.prefix = template.prefix; | ||
| 762 | power_user.reasoning.suffix = template.suffix; | ||
| 763 | power_user.reasoning.separator = template.separator; | ||
| 764 | |||
| 765 | saveSettingsDebounced(); | ||
| 766 | }); | ||
| 767 | } | ||
| 768 | |||
| 769 | function selectReasoningTemplateCallback(args, name) { | ||
| 770 | if (!name) { | ||
| 771 | return power_user.reasoning.name ?? ''; | ||
| 772 | } | ||
| 773 | |||
| 774 | const quiet = isTrueBoolean(args?.quiet); | ||
| 775 | const templateNames = reasoning_templates.map(preset => preset.name); | ||
| 776 | let foundName = templateNames.find(x => x.toLowerCase() === name.toLowerCase()); | ||
| 777 | |||
| 778 | if (!foundName) { | ||
| 779 | const fuse = new Fuse(templateNames); | ||
| 780 | const result = fuse.search(name); | ||
| 781 | |||
| 782 | if (result.length === 0) { | ||
| 783 | !quiet && toastr.warning(`Reasoning template "${name}" not found`); | ||
| 784 | return ''; | ||
| 785 | } | ||
| 786 | |||
| 787 | foundName = result[0].item; | ||
| 788 | } | ||
| 789 | |||
| 790 | UI.$select.val(foundName).trigger('change'); | ||
| 791 | !quiet && toastr.success(`Reasoning template "${foundName}" selected`); | ||
| 792 | return foundName; | ||
| 793 | |||
| 718 | } | 794 | } |
| 719 | 795 | ||
| 720 | function registerReasoningSlashCommands() { | 796 | function registerReasoningSlashCommands() { |
| @@ -848,6 +924,42 @@ function registerReasoningSlashCommands() { | |||
| 848 | : parsedReasoning.reasoning; | 924 | : parsedReasoning.reasoning; |
| 849 | }, | 925 | }, |
| 850 | })); | 926 | })); |
| 927 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | ||
| 928 | name: 'reasoning-template', | ||
| 929 | aliases: ['reasoning-formatting', 'reasoning-preset'], | ||
| 930 | callback: selectReasoningTemplateCallback, | ||
| 931 | returns: 'template name', | ||
| 932 | namedArgumentList: [ | ||
| 933 | SlashCommandNamedArgument.fromProps({ | ||
| 934 | name: 'quiet', | ||
| 935 | description: 'Suppress the toast message on template change', | ||
| 936 | typeList: [ARGUMENT_TYPE.BOOLEAN], | ||
| 937 | defaultValue: 'false', | ||
| 938 | enumList: commonEnumProviders.boolean('trueFalse')(), | ||
| 939 | }), | ||
| 940 | ], | ||
| 941 | unnamedArgumentList: [ | ||
| 942 | SlashCommandArgument.fromProps({ | ||
| 943 | description: 'reasoning template name', | ||
| 944 | typeList: [ARGUMENT_TYPE.STRING], | ||
| 945 | enumProvider: () => reasoning_templates.map(x => new SlashCommandEnumValue(x.name, null, enumTypes.enum, enumIcons.preset)), | ||
| 946 | }), | ||
| 947 | ], | ||
| 948 | helpString: ` | ||
| 949 | <div> | ||
| 950 | Selects a reasoning template by name, using fuzzy search to find the closest match. | ||
| 951 | Gets the current template if no name is provided. | ||
| 952 | </div> | ||
| 953 | <div> | ||
| 954 | <strong>Example:</strong> | ||
| 955 | <ul> | ||
| 956 | <li> | ||
| 957 | <pre><code class="language-stscript">/reasoning-template DeepSeek R1</code></pre> | ||
| 958 | </li> | ||
| 959 | </ul> | ||
| 960 | </div> | ||
| 961 | `, | ||
| 962 | })); | ||
| 851 | } | 963 | } |
| 852 | 964 | ||
| 853 | function registerReasoningMacros() { | 965 | function registerReasoningMacros() { |
| @@ -1207,6 +1319,31 @@ function registerReasoningAppEvents() { | |||
| 1207 | } | 1319 | } |
| 1208 | } | 1320 | } |
| 1209 | 1321 | ||
| 1322 | /** | ||
| 1323 | * Loads reasoning templates from the settings data. | ||
| 1324 | * @param {object} data Settings data | ||
| 1325 | * @param {ReasoningTemplate[]} data.reasoning Reasoning templates | ||
| 1326 | * @returns {Promise<void>} | ||
| 1327 | */ | ||
| 1328 | export async function loadReasoningTemplates(data) { | ||
| 1329 | if (data.reasoning !== undefined) { | ||
| 1330 | reasoning_templates.splice(0, reasoning_templates.length, ...data.reasoning); | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | for (const template of reasoning_templates) { | ||
| 1334 | $('<option>').val(template.name).text(template.name).appendTo(UI.$select); | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | if (!power_user.reasoning.name) { | ||
| 1338 | power_user.reasoning.name = reasoning_templates[0]?.name ?? ''; | ||
| 1339 | } | ||
| 1340 | |||
| 1341 | UI.$select.val(power_user.reasoning.name); | ||
| 1342 | } | ||
| 1343 | |||
| 1344 | /** | ||
| 1345 | * Initializes reasoning settings and event handlers. | ||
| 1346 | */ | ||
| 1210 | export function initReasoning() { | 1347 | export function initReasoning() { |
| 1211 | loadReasoningSettings(); | 1348 | loadReasoningSettings(); |
| 1212 | setReasoningEventHandlers(); | 1349 | setReasoningEventHandlers(); |
| @@ -43,6 +43,7 @@ export const USER_DIRECTORY_TEMPLATE = Object.freeze({ | |||
| 43 | vectors: 'vectors', | 43 | vectors: 'vectors', |
| 44 | backups: 'backups', | 44 | backups: 'backups', |
| 45 | sysprompt: 'sysprompt', | 45 | sysprompt: 'sysprompt', |
| 46 | reasoning: 'reasoning', | ||
| 46 | }); | 47 | }); |
| 47 | 48 | ||
| 48 | /** | 49 | /** |
| @@ -48,6 +48,7 @@ export const CONTENT_TYPES = { | |||
| 48 | MOVING_UI: 'moving_ui', | 48 | MOVING_UI: 'moving_ui', |
| 49 | QUICK_REPLIES: 'quick_replies', | 49 | QUICK_REPLIES: 'quick_replies', |
| 50 | SYSPROMPT: 'sysprompt', | 50 | SYSPROMPT: 'sysprompt', |
| 51 | REASONING: 'reasoning', | ||
| 51 | }; | 52 | }; |
| 52 | 53 | ||
| 53 | /** | 54 | /** |
| @@ -61,7 +62,7 @@ export function getDefaultPresets(directories) { | |||
| 61 | const presets = []; | 62 | const presets = []; |
| 62 | 63 | ||
| 63 | for (const contentItem of contentIndex) { | 64 | for (const contentItem of contentIndex) { |
| 64 | if (contentItem.type.endsWith('_preset') || contentItem.type === 'instruct' || contentItem.type === 'context' || contentItem.type === 'sysprompt') { | 65 | if (contentItem.type.endsWith('_preset') || ['instruct', 'context', 'sysprompt', 'reasoning'].includes(contentItem.type)) { |
| 65 | contentItem.name = path.parse(contentItem.filename).name; | 66 | contentItem.name = path.parse(contentItem.filename).name; |
| 66 | contentItem.folder = getTargetByType(contentItem.type, directories); | 67 | contentItem.folder = getTargetByType(contentItem.type, directories); |
| 67 | presets.push(contentItem); | 68 | presets.push(contentItem); |
| @@ -299,6 +300,8 @@ function getTargetByType(type, directories) { | |||
| 299 | return directories.quickreplies; | 300 | return directories.quickreplies; |
| 300 | case CONTENT_TYPES.SYSPROMPT: | 301 | case CONTENT_TYPES.SYSPROMPT: |
| 301 | return directories.sysprompt; | 302 | return directories.sysprompt; |
| 303 | case CONTENT_TYPES.REASONING: | ||
| 304 | return directories.reasoning; | ||
| 302 | default: | 305 | default: |
| 303 | return null; | 306 | return null; |
| 304 | } | 307 | } |
| @@ -30,6 +30,8 @@ function getPresetSettingsByAPI(apiId, directories) { | |||
| 30 | return { folder: directories.context, extension: '.json' }; | 30 | return { folder: directories.context, extension: '.json' }; |
| 31 | case 'sysprompt': | 31 | case 'sysprompt': |
| 32 | return { folder: directories.sysprompt, extension: '.json' }; | 32 | return { folder: directories.sysprompt, extension: '.json' }; |
| 33 | case 'reasoning': | ||
| 34 | return { folder: directories.reasoning, extension: '.json' }; | ||
| 33 | default: | 35 | default: |
| 34 | return { folder: null, extension: null }; | 36 | return { folder: null, extension: null }; |
| 35 | } | 37 | } |
| @@ -254,6 +254,7 @@ router.post('/get', (request, response) => { | |||
| 254 | const instruct = readAndParseFromDirectory(request.user.directories.instruct); | 254 | const instruct = readAndParseFromDirectory(request.user.directories.instruct); |
| 255 | const context = readAndParseFromDirectory(request.user.directories.context); | 255 | const context = readAndParseFromDirectory(request.user.directories.context); |
| 256 | const sysprompt = readAndParseFromDirectory(request.user.directories.sysprompt); | 256 | const sysprompt = readAndParseFromDirectory(request.user.directories.sysprompt); |
| 257 | const reasoning = readAndParseFromDirectory(request.user.directories.reasoning); | ||
| 257 | 258 | ||
| 258 | response.send({ | 259 | response.send({ |
| 259 | settings, | 260 | settings, |
| @@ -272,6 +273,7 @@ router.post('/get', (request, response) => { | |||
| 272 | instruct, | 273 | instruct, |
| 273 | context, | 274 | context, |
| 274 | sysprompt, | 275 | sysprompt, |
| 276 | reasoning, | ||
| 275 | enable_extensions: ENABLE_EXTENSIONS, | 277 | enable_extensions: ENABLE_EXTENSIONS, |
| 276 | enable_extensions_auto_update: ENABLE_EXTENSIONS_AUTO_UPDATE, | 278 | enable_extensions_auto_update: ENABLE_EXTENSIONS_AUTO_UPDATE, |
| 277 | enable_accounts: ENABLE_ACCOUNTS, | 279 | enable_accounts: ENABLE_ACCOUNTS, |
| @@ -95,6 +95,7 @@ const STORAGE_KEYS = { | |||
| 95 | * @property {string} vectors - The directory where the vectors are stored | 95 | * @property {string} vectors - The directory where the vectors are stored |
| 96 | * @property {string} backups - The directory where the backups are stored | 96 | * @property {string} backups - The directory where the backups are stored |
| 97 | * @property {string} sysprompt - The directory where the system prompt data is stored | 97 | * @property {string} sysprompt - The directory where the system prompt data is stored |
| 98 | * @property {string} reasoning - The directory where the reasoning templates are stored | ||
| 98 | */ | 99 | */ |
| 99 | 100 | ||
| 100 | /** | 101 | /** |