Merge branch 'parse-reasoning-command-args' into reasoning-parsing-streaming
| @@ -10,7 +10,8 @@ import { Popup } from './popup.js'; | |||
| 10 | import { power_user } from './power-user.js'; | 10 | import { power_user } from './power-user.js'; |
| 11 | import { SlashCommand } from './slash-commands/SlashCommand.js'; | 11 | import { SlashCommand } from './slash-commands/SlashCommand.js'; |
| 12 | import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js'; | 12 | import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js'; |
| 13 | import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js'; | 13 | import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; |
| 14 | import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js'; | ||
| 14 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; | 15 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; |
| 15 | import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js'; | 16 | import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js'; |
| 16 | import { copyText, escapeRegex, isFalseBoolean, setDatasetProperty, trimSpaces } from './utils.js'; | 17 | import { copyText, escapeRegex, isFalseBoolean, setDatasetProperty, trimSpaces } from './utils.js'; |
| @@ -678,7 +679,26 @@ function registerReasoningSlashCommands() { | |||
| 678 | typeList: [ARGUMENT_TYPE.BOOLEAN], | 679 | typeList: [ARGUMENT_TYPE.BOOLEAN], |
| 679 | defaultValue: 'true', | 680 | defaultValue: 'true', |
| 680 | isRequired: false, | 681 | isRequired: false, |
| 681 | enumProvider: commonEnumProviders.boolean('trueFalse'), | 682 | enumList: commonEnumProviders.boolean('trueFalse')(), |
| 683 | }), | ||
| 684 | SlashCommandNamedArgument.fromProps({ | ||
| 685 | name: 'return', | ||
| 686 | description: 'Whether to return the parsed reasoning or the content without reasoning', | ||
| 687 | typeList: [ARGUMENT_TYPE.STRING], | ||
| 688 | defaultValue: 'reasoning', | ||
| 689 | isRequired: false, | ||
| 690 | enumList: [ | ||
| 691 | new SlashCommandEnumValue('reasoning', null, enumTypes.enum, enumIcons.reasoning), | ||
| 692 | new SlashCommandEnumValue('content', null, enumTypes.enum, enumIcons.message), | ||
| 693 | ], | ||
| 694 | }), | ||
| 695 | SlashCommandNamedArgument.fromProps({ | ||
| 696 | name: 'strict', | ||
| 697 | description: 'Whether to require the reasoning block to be at the beginning of the string (excluding whitespaces).', | ||
| 698 | typeList: [ARGUMENT_TYPE.BOOLEAN], | ||
| 699 | defaultValue: 'true', | ||
| 700 | isRequired: false, | ||
| 701 | enumList: commonEnumProviders.boolean('trueFalse')(), | ||
| 682 | }), | 702 | }), |
| 683 | ], | 703 | ], |
| 684 | unnamedArgumentList: [ | 704 | unnamedArgumentList: [ |
| @@ -688,19 +708,27 @@ function registerReasoningSlashCommands() { | |||
| 688 | }), | 708 | }), |
| 689 | ], | 709 | ], |
| 690 | callback: (args, value) => { | 710 | callback: (args, value) => { |
| 691 | if (!value) { | 711 | if (!value || typeof value !== 'string') { |
| 692 | return ''; | 712 | return ''; |
| 693 | } | 713 | } |
| 694 | 714 | ||
| 695 | if (!power_user.reasoning.prefix || !power_user.reasoning.suffix) { | 715 | if (!power_user.reasoning.prefix || !power_user.reasoning.suffix) { |
| 696 | toastr.warning(t`Both prefix and suffix must be set in the Reasoning Formatting settings.`); | 716 | toastr.warning(t`Both prefix and suffix must be set in the Reasoning Formatting settings.`, t`Reasoning Parse`); |
| 697 | return String(value); | 717 | return value; |
| 718 | } | ||
| 719 | if (typeof args.return !== 'string' || !['reasoning', 'content'].includes(args.return)) { | ||
| 720 | toastr.warning(t`Invalid return type '${args.return}', defaulting to 'reasoning'.`, t`Reasoning Parse`); | ||
| 698 | } | 721 | } |
| 699 | 722 | ||
| 700 | const parsedReasoning = parseReasoningFromString(String(value)); | 723 | const returnMessage = args.return === 'content'; |
| 701 | 724 | ||
| 725 | const parsedReasoning = parseReasoningFromString(value, { strict: !isFalseBoolean(String(args.strict ?? '')) }); | ||
| 702 | if (!parsedReasoning) { | 726 | if (!parsedReasoning) { |
| 703 | return ''; | 727 | return returnMessage ? value : ''; |
| 728 | } | ||
| 729 | |||
| 730 | if (returnMessage) { | ||
| 731 | return parsedReasoning.content; | ||
| 704 | } | 732 | } |
| 705 | 733 | ||
| 706 | const applyRegex = !isFalseBoolean(String(args.regex ?? '')); | 734 | const applyRegex = !isFalseBoolean(String(args.regex ?? '')); |
| @@ -902,16 +930,18 @@ export function removeReasoningFromString(str) { | |||
| 902 | * @property {string} reasoning Reasoning block | 930 | * @property {string} reasoning Reasoning block |
| 903 | * @property {string} content Message content | 931 | * @property {string} content Message content |
| 904 | * @param {string} str Content of the message | 932 | * @param {string} str Content of the message |
| 933 | * @param {Object} options Optional arguments | ||
| 934 | * @param {boolean} [options.strict=true] Whether the reasoning block **has** to be at the beginning of the provided string (excluding whitespaces), or can be anywhere in it | ||
| 905 | * @returns {ParsedReasoning|null} Parsed reasoning block and message content | 935 | * @returns {ParsedReasoning|null} Parsed reasoning block and message content |
| 906 | */ | 936 | */ |
| 907 | function parseReasoningFromString(str) { | 937 | function parseReasoningFromString(str, { strict = true } = {}) { |
| 908 | // Both prefix and suffix must be defined | 938 | // Both prefix and suffix must be defined |
| 909 | if (!power_user.reasoning.prefix || !power_user.reasoning.suffix) { | 939 | if (!power_user.reasoning.prefix || !power_user.reasoning.suffix) { |
| 910 | return null; | 940 | return null; |
| 911 | } | 941 | } |
| 912 | 942 | ||
| 913 | try { | 943 | try { |
| 914 | const regex = new RegExp(`${escapeRegex(power_user.reasoning.prefix)}(.*?)${escapeRegex(power_user.reasoning.suffix)}`, 's'); | 944 | const regex = new RegExp(`${(strict ? '^\\s*?' : '')}${escapeRegex(power_user.reasoning.prefix)}(.*?)${escapeRegex(power_user.reasoning.suffix)}`, 's'); |
| 915 | 945 | ||
| 916 | let didReplace = false; | 946 | let didReplace = false; |
| 917 | let reasoning = ''; | 947 | let reasoning = ''; |
| @@ -34,6 +34,7 @@ export const enumIcons = { | |||
| 34 | preset: '⚙️', | 34 | preset: '⚙️', |
| 35 | file: '📄', | 35 | file: '📄', |
| 36 | message: '💬', | 36 | message: '💬', |
| 37 | reasoning: '💡', | ||
| 37 | voice: '🎤', | 38 | voice: '🎤', |
| 38 | server: '🖥️', | 39 | server: '🖥️', |
| 39 | popup: '🗔', | 40 | popup: '🗔', |