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>

eeda4d377ee2d4fb21f536ae793cda6d1673b449

Copilot <198982749+Copilot@users.noreply.github.com>

Signed
4 files changed, +70 -22Showing whitespace changes
public/script.js+37 -15
@@ -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};
330332
331/**333/**
@@ -4359,7 +4361,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
4359 }4361 }
43604362
4361 // Determine token limit4363 // Determine token limit
4362 let this_max_context = getMaxContextSize();4364 let this_max_context = getMaxPromptTokens();
43634365
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}
57215723
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 */
5727export function getMaxContextSize(overrideResponseLength = null) {5728export 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 whatnot5750 // 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}
57575760
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 */
5765export 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;
5762 }5771 }
5763 return this_max_context;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 */
5780export function getMaxPromptTokens(overrideResponseLength = null) {
5781 if (typeof overrideResponseLength !== 'number' || overrideResponseLength <= 0 || isNaN(overrideResponseLength)) {
5782 overrideResponseLength = null;
5783 }
5784
5785 return getMaxContextTokens() - (overrideResponseLength || getMaxResponseTokens());
5764}5786}
57655787
5766function parseTokenCounts(counts, thisPromptBits) {5788function parseTokenCounts(counts, thisPromptBits) {
public/scripts/extensions/memory/index.js+2 -2
@@ -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 }
7373
74 return getMaxContextSize(overrideLength);74 return getMaxPromptTokens(overrideLength);
75}75}
7676
77const formatMemoryValue = function (value) {77const formatMemoryValue = function (value) {
public/scripts/macros.js+7 -2
@@ -1,5 +1,5 @@
1import { Handlebars, moment, seedrandom, droll } from '../lib.js';1import { Handlebars, moment, seedrandom, droll } from '../lib.js';
2import { chat, chat_metadata, main_api, getMaxContextSize, getCurrentChatId, substituteParams, eventSource, event_types, extension_prompts } from '../script.js';2import { chat, chat_metadata, main_api, getMaxPromptTokens, getMaxContextTokens, getMaxResponseTokens, getCurrentChatId, substituteParams, eventSource, event_types, extension_prompts } from '../script.js';
3import { timestampToMoment, isDigitsOnly, getStringHash, escapeRegex, uuidv4 } from './utils.js';3import { timestampToMoment, isDigitsOnly, getStringHash, escapeRegex, uuidv4 } from './utils.js';
4import { textgenerationwebui_banned_in_macros } from './textgen-settings.js';4import { textgenerationwebui_banned_in_macros } from './textgen-settings.js';
5import { getInstructMacros } from './instruct-mode.js';5import { 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() },
public/scripts/macros/definitions/core-macros.js+24 -3
@@ -1,5 +1,5 @@
1import { seedrandom, droll } from '../../../lib.js';1import { seedrandom, droll } from '../../../lib.js';
2import { chat_metadata, main_api, getMaxContextSize, extension_prompts, getCurrentChatId } from '../../../script.js';2import { chat_metadata, main_api, getMaxPromptTokens, getMaxContextTokens, getMaxResponseTokens, extension_prompts, getCurrentChatId } from '../../../script.js';
3import { getStringHash, isFalseBoolean } from '../../utils.js';3import { getStringHash, isFalseBoolean } from '../../utils.js';
4import { textgenerationwebui_banned_in_macros } from '../../textgen-settings.js';4import { textgenerationwebui_banned_in_macros } from '../../textgen-settings.js';
5import { inject_ids } from '../../constants.js';5import { 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 });
234234
235 // {{maxPrompt}} -> max context size235 // {{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 });
243264
244 // String utilities265 // String utilities