Add {{maxContext}}, {{maxResponse}} macros and {{maxPromptTokens}} alias (#5176) * Initial plan * Add maxContext, maxResponse macros and maxPromptTokens alias Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com> * Refactor getMaxContextSize to use getMaxContextTokens/getMaxResponseTokens and remove maxReply aliases Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com> * Align aliases in single line * Rename getMaxPromptTokens --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com>
Signed| @@ -326,6 +326,8 @@ export { | |||
| 326 | setCharacterSettingsOverrides as setScenarioOverride, | 326 | setCharacterSettingsOverrides as setScenarioOverride, |
| 327 | /** @deprecated Use appendMediaToMessage instead. */ | 327 | /** @deprecated Use appendMediaToMessage instead. */ |
| 328 | appendMediaToMessage as appendImageToMessage, | 328 | appendMediaToMessage as appendImageToMessage, |
| 329 | /** @deprecated Use getMaxPromptTokens instead. */ | ||
| 330 | getMaxPromptTokens as getMaxContextSize, | ||
| 329 | }; | 331 | }; |
| 330 | 332 | ||
| 331 | /** | 333 | /** |
| @@ -4359,7 +4361,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4359 | } | 4361 | } |
| 4360 | 4362 | ||
| 4361 | // Determine token limit | 4363 | // Determine token limit |
| 4362 | let this_max_context = getMaxContextSize(); | 4364 | let this_max_context = getMaxPromptTokens(); |
| 4363 | 4365 | ||
| 4364 | if (!dryRun) { | 4366 | if (!dryRun) { |
| 4365 | console.debug('Running extension interceptors'); | 4367 | console.debug('Running extension interceptors'); |
| @@ -5720,21 +5722,15 @@ export async function sendMessageAsUser(messageText, messageBias, insertAt = nul | |||
| 5720 | } | 5722 | } |
| 5721 | 5723 | ||
| 5722 | /** | 5724 | /** |
| 5723 | * Gets the maximum usable context size for the current API. | 5725 | * Gets the maximum context token limit (the full context window size before subtracting response length). |
| 5724 | * @param {number|null} overrideResponseLength Optional override for the response length. | 5726 | * @returns {number} The maximum context token limit for the current API. |
| 5725 | * @returns {number} Maximum usable context size. | ||
| 5726 | */ | 5727 | */ |
| 5727 | export function getMaxContextSize(overrideResponseLength = null) { | 5728 | export function getMaxContextTokens() { |
| 5728 | if (typeof overrideResponseLength !== 'number' || overrideResponseLength <= 0 || isNaN(overrideResponseLength)) { | ||
| 5729 | overrideResponseLength = null; | ||
| 5730 | } | ||
| 5731 | |||
| 5732 | let this_max_context = 1487; | ||
| 5733 | if (main_api == 'kobold' || main_api == 'koboldhorde' || main_api == 'textgenerationwebui') { | 5729 | if (main_api == 'kobold' || main_api == 'koboldhorde' || main_api == 'textgenerationwebui') { |
| 5734 | this_max_context = (max_context - (overrideResponseLength || amount_gen)); | 5730 | return max_context; |
| 5735 | } | 5731 | } |
| 5736 | if (main_api == 'novel') { | 5732 | if (main_api == 'novel') { |
| 5737 | this_max_context = Number(max_context); | 5733 | let this_max_context = Number(max_context); |
| 5738 | if (nai_settings.model_novel.includes('clio')) { | 5734 | if (nai_settings.model_novel.includes('clio')) { |
| 5739 | this_max_context = Math.min(max_context, 8192); | 5735 | this_max_context = Math.min(max_context, 8192); |
| 5740 | } | 5736 | } |
| @@ -5754,13 +5750,39 @@ export function getMaxContextSize(overrideResponseLength = null) { | |||
| 5754 | // Added special tokens and whatnot | 5750 | // Added special tokens and whatnot |
| 5755 | this_max_context -= 10; | 5751 | this_max_context -= 10; |
| 5756 | } | 5752 | } |
| 5753 | return this_max_context; | ||
| 5754 | } | ||
| 5755 | if (main_api == 'openai') { | ||
| 5756 | return oai_settings.openai_max_context; | ||
| 5757 | } | ||
| 5758 | return 1487; | ||
| 5759 | } | ||
| 5757 | 5760 | ||
| 5758 | this_max_context = this_max_context - (overrideResponseLength || amount_gen); | 5761 | /** |
| 5762 | * Gets the maximum response token limit (the max generation/reply length). | ||
| 5763 | * @returns {number} The maximum response token limit for the current API. | ||
| 5764 | */ | ||
| 5765 | export function getMaxResponseTokens() { | ||
| 5766 | if (main_api == 'kobold' || main_api == 'koboldhorde' || main_api == 'textgenerationwebui' || main_api == 'novel') { | ||
| 5767 | return amount_gen; | ||
| 5759 | } | 5768 | } |
| 5760 | if (main_api == 'openai') { | 5769 | if (main_api == 'openai') { |
| 5761 | this_max_context = oai_settings.openai_max_context - (overrideResponseLength || oai_settings.openai_max_tokens); | 5770 | return oai_settings.openai_max_tokens; |
| 5771 | } | ||
| 5772 | return 0; | ||
| 5773 | } | ||
| 5774 | |||
| 5775 | /** | ||
| 5776 | * Gets the maximum usable prompt size for the current API. | ||
| 5777 | * @param {number|null} overrideResponseLength Optional override for the response length. | ||
| 5778 | * @returns {number} Maximum usable prompt size. | ||
| 5779 | */ | ||
| 5780 | export function getMaxPromptTokens(overrideResponseLength = null) { | ||
| 5781 | if (typeof overrideResponseLength !== 'number' || overrideResponseLength <= 0 || isNaN(overrideResponseLength)) { | ||
| 5782 | overrideResponseLength = null; | ||
| 5762 | } | 5783 | } |
| 5763 | return this_max_context; | 5784 | |
| 5785 | return getMaxContextTokens() - (overrideResponseLength || getMaxResponseTokens()); | ||
| 5764 | } | 5786 | } |
| 5765 | 5787 | ||
| 5766 | function parseTokenCounts(counts, thisPromptBits) { | 5788 | function parseTokenCounts(counts, thisPromptBits) { |
| @@ -13,7 +13,7 @@ import { | |||
| 13 | saveSettingsDebounced, | 13 | saveSettingsDebounced, |
| 14 | substituteParamsExtended, | 14 | substituteParamsExtended, |
| 15 | generateRaw, | 15 | generateRaw, |
| 16 | getMaxContextSize, | 16 | getMaxPromptTokens, |
| 17 | setExtensionPrompt, | 17 | setExtensionPrompt, |
| 18 | streamingProcessor, | 18 | streamingProcessor, |
| 19 | animation_easing, | 19 | animation_easing, |
| @@ -71,7 +71,7 @@ async function getSourceContextSize() { | |||
| 71 | return 1024 - 64; | 71 | return 1024 - 64; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | return getMaxContextSize(overrideLength); | 74 | return getMaxPromptTokens(overrideLength); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | const formatMemoryValue = function (value) { | 77 | const formatMemoryValue = function (value) { |
| @@ -1,5 +1,5 @@ | |||
| 1 | import { Handlebars, moment, seedrandom, droll } from '../lib.js'; | 1 | import { Handlebars, moment, seedrandom, droll } from '../lib.js'; |
| 2 | import { chat, chat_metadata, main_api, getMaxContextSize, getCurrentChatId, substituteParams, eventSource, event_types, extension_prompts } from '../script.js'; | 2 | import { chat, chat_metadata, main_api, getMaxPromptTokens, getMaxContextTokens, getMaxResponseTokens, getCurrentChatId, substituteParams, eventSource, event_types, extension_prompts } from '../script.js'; |
| 3 | import { timestampToMoment, isDigitsOnly, getStringHash, escapeRegex, uuidv4 } from './utils.js'; | 3 | import { timestampToMoment, isDigitsOnly, getStringHash, escapeRegex, uuidv4 } from './utils.js'; |
| 4 | import { textgenerationwebui_banned_in_macros } from './textgen-settings.js'; | 4 | import { textgenerationwebui_banned_in_macros } from './textgen-settings.js'; |
| 5 | import { getInstructMacros } from './instruct-mode.js'; | 5 | import { getInstructMacros } from './instruct-mode.js'; |
| @@ -639,7 +639,12 @@ export function evaluateMacros(content, env, postProcessFn) { | |||
| 639 | * @type {Macro[]} | 639 | * @type {Macro[]} |
| 640 | */ | 640 | */ |
| 641 | const postEnvMacros = [ | 641 | const postEnvMacros = [ |
| 642 | { regex: /{{maxPrompt}}/gi, replace: () => String(getMaxContextSize()) }, | 642 | { regex: /{{maxPrompt}}/gi, replace: () => String(getMaxPromptTokens()) }, |
| 643 | { regex: /{{maxPromptTokens}}/gi, replace: () => String(getMaxPromptTokens()) }, | ||
| 644 | { regex: /{{maxContext}}/gi, replace: () => String(getMaxContextTokens()) }, | ||
| 645 | { regex: /{{maxContextTokens}}/gi, replace: () => String(getMaxContextTokens()) }, | ||
| 646 | { regex: /{{maxResponse}}/gi, replace: () => String(getMaxResponseTokens()) }, | ||
| 647 | { regex: /{{maxResponseTokens}}/gi, replace: () => String(getMaxResponseTokens()) }, | ||
| 643 | { regex: /{{lastMessage}}/gi, replace: () => getLastMessage() }, | 648 | { regex: /{{lastMessage}}/gi, replace: () => getLastMessage() }, |
| 644 | { regex: /{{lastMessageId}}/gi, replace: () => String(getLastMessageId() ?? '') }, | 649 | { regex: /{{lastMessageId}}/gi, replace: () => String(getLastMessageId() ?? '') }, |
| 645 | { regex: /{{lastUserMessage}}/gi, replace: () => getLastUserMessage() }, | 650 | { regex: /{{lastUserMessage}}/gi, replace: () => getLastUserMessage() }, |
| @@ -1,5 +1,5 @@ | |||
| 1 | import { seedrandom, droll } from '../../../lib.js'; | 1 | import { seedrandom, droll } from '../../../lib.js'; |
| 2 | import { chat_metadata, main_api, getMaxContextSize, extension_prompts, getCurrentChatId } from '../../../script.js'; | 2 | import { chat_metadata, main_api, getMaxPromptTokens, getMaxContextTokens, getMaxResponseTokens, extension_prompts, getCurrentChatId } from '../../../script.js'; |
| 3 | import { getStringHash, isFalseBoolean } from '../../utils.js'; | 3 | import { getStringHash, isFalseBoolean } from '../../utils.js'; |
| 4 | import { textgenerationwebui_banned_in_macros } from '../../textgen-settings.js'; | 4 | import { textgenerationwebui_banned_in_macros } from '../../textgen-settings.js'; |
| 5 | import { inject_ids } from '../../constants.js'; | 5 | import { inject_ids } from '../../constants.js'; |
| @@ -232,13 +232,34 @@ export function registerCoreMacros() { | |||
| 232 | handler: () => (/** @type {HTMLTextAreaElement} */(document.querySelector('#send_textarea')))?.value ?? '', | 232 | handler: () => (/** @type {HTMLTextAreaElement} */(document.querySelector('#send_textarea')))?.value ?? '', |
| 233 | }); | 233 | }); |
| 234 | 234 | ||
| 235 | // {{maxPrompt}} -> max context size | 235 | // {{maxPrompt}} -> max context size (context minus response) |
| 236 | MacroRegistry.registerMacro('maxPrompt', { | 236 | MacroRegistry.registerMacro('maxPrompt', { |
| 237 | aliases: [{ alias: 'maxPromptTokens', visible: true }], | ||
| 237 | category: MacroCategory.STATE, | 238 | category: MacroCategory.STATE, |
| 238 | description: 'Maximum prompt context size.', | 239 | description: 'Maximum prompt context size.', |
| 239 | returns: 'Maximum prompt context size.', | 240 | returns: 'Maximum prompt context size.', |
| 240 | returnType: MacroValueType.INTEGER, | 241 | returnType: MacroValueType.INTEGER, |
| 241 | handler: () => String(getMaxContextSize()), | 242 | handler: () => String(getMaxPromptTokens()), |
| 243 | }); | ||
| 244 | |||
| 245 | // {{maxContext}} -> max context token limit | ||
| 246 | MacroRegistry.registerMacro('maxContext', { | ||
| 247 | aliases: [{ alias: 'maxContextTokens', visible: true }], | ||
| 248 | category: MacroCategory.STATE, | ||
| 249 | description: 'Maximum context token limit.', | ||
| 250 | returns: 'Maximum context token limit.', | ||
| 251 | returnType: MacroValueType.INTEGER, | ||
| 252 | handler: () => String(getMaxContextTokens()), | ||
| 253 | }); | ||
| 254 | |||
| 255 | // {{maxResponse}} -> max response token limit | ||
| 256 | MacroRegistry.registerMacro('maxResponse', { | ||
| 257 | aliases: [{ alias: 'maxResponseTokens', visible: true }], | ||
| 258 | category: MacroCategory.STATE, | ||
| 259 | description: 'Maximum response token limit.', | ||
| 260 | returns: 'Maximum response token limit.', | ||
| 261 | returnType: MacroValueType.INTEGER, | ||
| 262 | handler: () => String(getMaxResponseTokens()), | ||
| 242 | }); | 263 | }); |
| 243 | 264 | ||
| 244 | // String utilities | 265 | // String utilities |