From 70adee3c631a0290ce182f8612e33e99ab62ad74 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Mon, 1 Apr 2024 01:47:56 +0200 Subject: [PATCH] Add {{pick}} macro replacement - Pick macro that works like random, but is consistent for the chat and context - Change help text for random to actually utilize the new, preferred syntax --- public/scripts/macros.js | 30 ++++++++++++++++++++++++++-- public/scripts/templates/macros.html | 3 ++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/public/scripts/macros.js b/public/scripts/macros.js index f3527d451..a8d178604 100644 --- a/public/scripts/macros.js +++ b/public/scripts/macros.js @@ -1,5 +1,5 @@ -import { chat, main_api, getMaxContextSize } from '../script.js'; -import { timestampToMoment, isDigitsOnly } from './utils.js'; +import { chat, main_api, getMaxContextSize, getCurrentChatId } from '../script.js'; +import { timestampToMoment, isDigitsOnly, getStringHash } from './utils.js'; import { textgenerationwebui_banned_in_macros } from './textgen-settings.js'; import { replaceInstructMacros } from './instruct-mode.js'; import { replaceVariableMacros } from './variables.js'; @@ -211,6 +211,29 @@ function randomReplace(input, emptyListPlaceholder = '') { return input; } +function pickReplace(input, rawContent, emptyListPlaceholder = '') { + const pickPattern = /{{pick\s?::\s?([^}]+)}}/gi; + const chatIdHash = getStringHash(getCurrentChatId()); + const rawContentHash = getStringHash(rawContent); + + return input.replace(pickPattern, (match, listString, offset) => { + const list = listString.includes('::') + ? listString.split('::').filter(item => item.length > 0) + : listString.split(',').map(item => item.trim()).filter(item => item.length > 0); + + if (list.length === 0) { + return emptyListPlaceholder; + } + + const combinedSeedString = `${chatIdHash}-${rawContentHash}-${offset}`; + const finalSeed = getStringHash(combinedSeedString); + const rng = new Math.seedrandom(finalSeed); + + const randomIndex = Math.floor(rng() * list.length); + return list[randomIndex].trim(); + }); +} + function diceRollReplace(input, invalidRollPlaceholder = '') { const rollPattern = /{{roll[ : ]([^}]+)}}/gi; @@ -245,6 +268,8 @@ export function evaluateMacros(content, env) { return ''; } + const rawContent = content; + // Legacy non-macro substitutions content = content.replace(//gi, typeof env.user === 'function' ? env.user() : env.user); content = content.replace(//gi, typeof env.char === 'function' ? env.char() : env.char); @@ -300,5 +325,6 @@ export function evaluateMacros(content, env) { }); content = bannedWordsReplace(content); content = randomReplace(content); + content = pickReplace(content, rawContent); return content; } diff --git a/public/scripts/templates/macros.html b/public/scripts/templates/macros.html index 1b137122a..1c27718cc 100644 --- a/public/scripts/templates/macros.html +++ b/public/scripts/templates/macros.html @@ -34,8 +34,9 @@
  • {{idle_duration}} – the time since the last user message was sent
  • {{bias "text here"}} – sets a behavioral bias for the AI until the next user input. Quotes around the text are important.
  • {{roll:(formula)}} – rolls a dice. (ex: >{{roll:1d6}} will roll a 6-sided dice and return a number between 1 and 6)
  • -
  • {{random:(args)}} – returns a random item from the list. (ex: {{random:1,2,3,4}} will return 1 of the 4 numbers at random. Works with text lists too.
  • +
  • {{random::(args)}} – returns a random item from the list. (ex: {{random::1,2,3,4}} will return 1 of the 4 numbers at random. Works with text lists too.
  • {{random::(arg1)::(arg2)}} – alternative syntax for random that allows to use commas in the list items.
  • +
  • {{pick::(args)}} – picks a random item from the list. Works the same as {{random}}, with the same possible syntax options, but the pick will stay consistent for this chat once picked and won't be re-rolled on consecutive messages and prompt processing.
  • {{banned "text here"}} – dynamically add text in the quotes to banned words sequences, if Text Generation WebUI backend used. Do nothing for others backends. Can be used anywhere (Character description, WI, AN, etc.) Quotes around the text are important.