mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Add character card macros
This commit is contained in:
112
public/script.js
112
public/script.js
@ -1799,7 +1799,7 @@ function getLastMessageId() {
|
|||||||
* @param {*} _group - The group members list for {{group}} substitution.
|
* @param {*} _group - The group members list for {{group}} substitution.
|
||||||
* @returns {string} The string with substituted parameters.
|
* @returns {string} The string with substituted parameters.
|
||||||
*/
|
*/
|
||||||
function substituteParams(content, _name1, _name2, _original, _group) {
|
function substituteParams(content, _name1, _name2, _original, _group, _replaceCharacterCard = true) {
|
||||||
_name1 = _name1 ?? name1;
|
_name1 = _name1 ?? name1;
|
||||||
_name2 = _name2 ?? name2;
|
_name2 = _name2 ?? name2;
|
||||||
_group = _group ?? name2;
|
_group = _group ?? name2;
|
||||||
@ -1814,7 +1814,18 @@ function substituteParams(content, _name1, _name2, _original, _group) {
|
|||||||
if (typeof _original === 'string') {
|
if (typeof _original === 'string') {
|
||||||
content = content.replace(/{{original}}/i, _original);
|
content = content.replace(/{{original}}/i, _original);
|
||||||
}
|
}
|
||||||
|
|
||||||
content = content.replace(/{{input}}/gi, String($('#send_textarea').val()));
|
content = content.replace(/{{input}}/gi, String($('#send_textarea').val()));
|
||||||
|
|
||||||
|
if (_replaceCharacterCard) {
|
||||||
|
const fields = getCharacterCardFields();
|
||||||
|
content = content.replace(/{{description}}/gi, fields.description || '');
|
||||||
|
content = content.replace(/{{personality}}/gi, fields.personality || '');
|
||||||
|
content = content.replace(/{{scenario}}/gi, fields.scenario || '');
|
||||||
|
content = content.replace(/{{persona}}/gi, fields.persona || '');
|
||||||
|
content = content.replace(/{{mesExamples}}/gi, fields.mesExamples || '');
|
||||||
|
}
|
||||||
|
|
||||||
content = content.replace(/{{user}}/gi, _name1);
|
content = content.replace(/{{user}}/gi, _name1);
|
||||||
content = content.replace(/{{char}}/gi, _name2);
|
content = content.replace(/{{char}}/gi, _name2);
|
||||||
content = content.replace(/{{charIfNotGroup}}/gi, _group);
|
content = content.replace(/{{charIfNotGroup}}/gi, _group);
|
||||||
@ -2180,7 +2191,8 @@ function getExtensionPrompt(position = 0, depth = undefined, separator = "\n") {
|
|||||||
|
|
||||||
export function baseChatReplace(value, name1, name2) {
|
export function baseChatReplace(value, name1, name2) {
|
||||||
if (value !== undefined && value.length > 0) {
|
if (value !== undefined && value.length > 0) {
|
||||||
value = substituteParams(value, name1, name2);
|
const _ = undefined;
|
||||||
|
value = substituteParams(value, name1, name2, _, _, false);
|
||||||
|
|
||||||
if (power_user.collapse_newlines) {
|
if (power_user.collapse_newlines) {
|
||||||
value = collapseNewlines(value);
|
value = collapseNewlines(value);
|
||||||
@ -2191,6 +2203,41 @@ export function baseChatReplace(value, name1, name2) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the character card fields for the current character.
|
||||||
|
* @returns {{system: string, mesExamples: string, description: string, personality: string, persona: string, scenario: string, jailbreak: string}}
|
||||||
|
*/
|
||||||
|
function getCharacterCardFields() {
|
||||||
|
const result = { system: '', mesExamples: '', description: '', personality: '', persona: '', scenario: '', jailbreak: '' };
|
||||||
|
const character = characters[this_chid];
|
||||||
|
|
||||||
|
if (!character) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scenarioText = chat_metadata['scenario'] || characters[this_chid].scenario;
|
||||||
|
result.description = baseChatReplace(characters[this_chid].description.trim(), name1, name2);
|
||||||
|
result.personality = baseChatReplace(characters[this_chid].personality.trim(), name1, name2);
|
||||||
|
result.scenario = baseChatReplace(scenarioText.trim(), name1, name2);
|
||||||
|
result.mesExamples = baseChatReplace(characters[this_chid].mes_example.trim(), name1, name2);
|
||||||
|
result.persona = baseChatReplace(power_user.persona_description.trim(), name1, name2);
|
||||||
|
result.system = power_user.prefer_character_prompt ? baseChatReplace(characters[this_chid].data?.system_prompt?.trim(), name1, name2) : '';
|
||||||
|
result.jailbreak = power_user.prefer_character_jailbreak ? baseChatReplace(characters[this_chid].data?.post_history_instructions?.trim(), name1, name2) : '';
|
||||||
|
|
||||||
|
if (selected_group) {
|
||||||
|
const groupCards = getGroupCharacterCards(selected_group, Number(this_chid));
|
||||||
|
|
||||||
|
if (groupCards) {
|
||||||
|
result.description = groupCards.description;
|
||||||
|
result.personality = groupCards.personality;
|
||||||
|
result.scenario = groupCards.scenario;
|
||||||
|
result.mesExamples = groupCards.mesExamples;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function isStreamingEnabled() {
|
function isStreamingEnabled() {
|
||||||
const noStreamSources = [chat_completion_sources.SCALE, chat_completion_sources.AI21, chat_completion_sources.PALM];
|
const noStreamSources = [chat_completion_sources.SCALE, chat_completion_sources.AI21, chat_completion_sources.PALM];
|
||||||
return ((main_api == 'openai' && oai_settings.stream_openai && !noStreamSources.includes(oai_settings.chat_completion_source))
|
return ((main_api == 'openai' && oai_settings.stream_openai && !noStreamSources.includes(oai_settings.chat_completion_source))
|
||||||
@ -2673,30 +2720,19 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
await sendMessageAsUser(oai_settings.send_if_empty.trim(), messageBias);
|
await sendMessageAsUser(oai_settings.send_if_empty.trim(), messageBias);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////
|
let {
|
||||||
const scenarioText = chat_metadata['scenario'] || characters[this_chid].scenario;
|
description,
|
||||||
let charDescription = baseChatReplace(characters[this_chid].description.trim(), name1, name2);
|
personality,
|
||||||
let charPersonality = baseChatReplace(characters[this_chid].personality.trim(), name1, name2);
|
persona,
|
||||||
let scenario = baseChatReplace(scenarioText.trim(), name1, name2);
|
scenario,
|
||||||
let mesExamples = baseChatReplace(characters[this_chid].mes_example.trim(), name1, name2);
|
mesExamples,
|
||||||
let systemPrompt = power_user.prefer_character_prompt ? baseChatReplace(characters[this_chid].data?.system_prompt?.trim(), name1, name2) : '';
|
system,
|
||||||
let jailbreakPrompt = power_user.prefer_character_jailbreak ? baseChatReplace(characters[this_chid].data?.post_history_instructions?.trim(), name1, name2) : '';
|
jailbreak,
|
||||||
let personaDescription = baseChatReplace(power_user.persona_description.trim(), name1, name2);
|
} = getCharacterCardFields();
|
||||||
|
|
||||||
if (isInstruct) {
|
if (isInstruct) {
|
||||||
systemPrompt = power_user.prefer_character_prompt && systemPrompt ? systemPrompt : baseChatReplace(power_user.instruct.system_prompt, name1, name2);
|
system = power_user.prefer_character_prompt && system ? system : baseChatReplace(power_user.instruct.system_prompt, name1, name2);
|
||||||
systemPrompt = formatInstructModeSystemPrompt(substituteParams(systemPrompt, name1, name2, power_user.instruct.system_prompt));
|
system = formatInstructModeSystemPrompt(substituteParams(system, name1, name2, power_user.instruct.system_prompt));
|
||||||
}
|
|
||||||
|
|
||||||
if (selected_group) {
|
|
||||||
const groupCards = getGroupCharacterCards(selected_group, Number(this_chid));
|
|
||||||
|
|
||||||
if (groupCards) {
|
|
||||||
charDescription = groupCards.description;
|
|
||||||
charPersonality = groupCards.personality;
|
|
||||||
scenario = groupCards.scenario;
|
|
||||||
mesExamples = groupCards.mesExample;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depth prompt (character-specific A/N)
|
// Depth prompt (character-specific A/N)
|
||||||
@ -2850,11 +2886,11 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
let zeroDepthAnchor = getExtensionPrompt(extension_prompt_types.IN_CHAT, 0, ' ');
|
let zeroDepthAnchor = getExtensionPrompt(extension_prompt_types.IN_CHAT, 0, ' ');
|
||||||
|
|
||||||
const storyStringParams = {
|
const storyStringParams = {
|
||||||
description: charDescription,
|
description: description,
|
||||||
personality: charPersonality,
|
personality: personality,
|
||||||
persona: personaDescription,
|
persona: persona,
|
||||||
scenario: scenario,
|
scenario: scenario,
|
||||||
system: isInstruct ? systemPrompt : '',
|
system: isInstruct ? system : '',
|
||||||
char: name2,
|
char: name2,
|
||||||
user: name1,
|
user: name1,
|
||||||
wiBefore: worldInfoBefore,
|
wiBefore: worldInfoBefore,
|
||||||
@ -3282,8 +3318,8 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
else if (main_api == 'openai') {
|
else if (main_api == 'openai') {
|
||||||
let [prompt, counts] = prepareOpenAIMessages({
|
let [prompt, counts] = prepareOpenAIMessages({
|
||||||
name2: name2,
|
name2: name2,
|
||||||
charDescription: charDescription,
|
charDescription: description,
|
||||||
charPersonality: charPersonality,
|
charPersonality: personality,
|
||||||
Scenario: scenario,
|
Scenario: scenario,
|
||||||
worldInfoBefore: worldInfoBefore,
|
worldInfoBefore: worldInfoBefore,
|
||||||
worldInfoAfter: worldInfoAfter,
|
worldInfoAfter: worldInfoAfter,
|
||||||
@ -3292,9 +3328,9 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
type: type,
|
type: type,
|
||||||
quietPrompt: quiet_prompt,
|
quietPrompt: quiet_prompt,
|
||||||
cyclePrompt: cyclePrompt,
|
cyclePrompt: cyclePrompt,
|
||||||
systemPromptOverride: systemPrompt,
|
systemPromptOverride: system,
|
||||||
jailbreakPromptOverride: jailbreakPrompt,
|
jailbreakPromptOverride: jailbreak,
|
||||||
personaDescription: personaDescription
|
personaDescription: persona
|
||||||
}, dryRun);
|
}, dryRun);
|
||||||
generate_data = { prompt: prompt };
|
generate_data = { prompt: prompt };
|
||||||
|
|
||||||
@ -3338,13 +3374,13 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
generatedPromptCache: generatedPromptCache,
|
generatedPromptCache: generatedPromptCache,
|
||||||
promptBias: promptBias,
|
promptBias: promptBias,
|
||||||
finalPrompt: finalPrompt,
|
finalPrompt: finalPrompt,
|
||||||
charDescription: charDescription,
|
charDescription: description,
|
||||||
charPersonality: charPersonality,
|
charPersonality: personality,
|
||||||
scenarioText: scenarioText,
|
scenarioText: scenario,
|
||||||
this_max_context: this_max_context,
|
this_max_context: this_max_context,
|
||||||
padding: power_user.token_padding,
|
padding: power_user.token_padding,
|
||||||
main_api: main_api,
|
main_api: main_api,
|
||||||
instruction: isInstruct ? substituteParams(power_user.prefer_character_prompt && systemPrompt ? systemPrompt : power_user.instruct.system_prompt) : '',
|
instruction: isInstruct ? substituteParams(power_user.prefer_character_prompt && system ? system : power_user.instruct.system_prompt) : '',
|
||||||
userPersona: (power_user.persona_description || ''),
|
userPersona: (power_user.persona_description || ''),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -5888,7 +5924,7 @@ function select_rm_create() {
|
|||||||
$("#scenario_pole").val(create_save.scenario);
|
$("#scenario_pole").val(create_save.scenario);
|
||||||
$("#depth_prompt_prompt").val(create_save.depth_prompt_prompt);
|
$("#depth_prompt_prompt").val(create_save.depth_prompt_prompt);
|
||||||
$("#depth_prompt_depth").val(create_save.depth_prompt_depth);
|
$("#depth_prompt_depth").val(create_save.depth_prompt_depth);
|
||||||
$("#mes_example_textarea").val(create_save.mes_example.trim().length === 0 ? '<START>' : create_save.mes_example);
|
$("#mes_example_textarea").val(create_save.mes_example);
|
||||||
$('#character_json_data').val('');
|
$('#character_json_data').val('');
|
||||||
$("#avatar_div").css("display", "flex");
|
$("#avatar_div").css("display", "flex");
|
||||||
$("#avatar_load_preview").attr("src", default_avatar);
|
$("#avatar_load_preview").attr("src", default_avatar);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { callPopup, event_types, eventSource, is_send_press, main_api, substituteParams } from "../script.js";
|
import { callPopup, event_types, eventSource, is_send_press, main_api, substituteParams } from "../script.js";
|
||||||
import { is_group_generating } from "./group-chats.js";
|
import { is_group_generating } from "./group-chats.js";
|
||||||
import { TokenHandler } from "./openai.js";
|
import { Message, TokenHandler } from "./openai.js";
|
||||||
import { power_user } from "./power-user.js";
|
import { power_user } from "./power-user.js";
|
||||||
import { debounce, waitUntilCondition, escapeHtml } from "./utils.js";
|
import { debounce, waitUntilCondition, escapeHtml } from "./utils.js";
|
||||||
|
|
||||||
@ -1141,12 +1141,10 @@ PromptManagerModule.prototype.loadMessagesIntoInspectForm = function (messages)
|
|||||||
let drawerHTML = `
|
let drawerHTML = `
|
||||||
<div class="inline-drawer ${this.configuration.prefix}prompt_manager_prompt">
|
<div class="inline-drawer ${this.configuration.prefix}prompt_manager_prompt">
|
||||||
<div class="inline-drawer-toggle inline-drawer-header">
|
<div class="inline-drawer-toggle inline-drawer-header">
|
||||||
<span>Name: ${title}, Role: ${role}, Tokens: ${tokens}</span>
|
<span>Name: ${escapeHtml(title)}, Role: ${role}, Tokens: ${tokens}</span>
|
||||||
<div class="fa-solid fa-circle-chevron-down inline-drawer-icon down"></div>
|
<div class="fa-solid fa-circle-chevron-down inline-drawer-icon down"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="inline-drawer-content">
|
<div class="inline-drawer-content" style="white-space: pre-wrap;">${escapeHtml(content)}</div>
|
||||||
${content}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -1157,9 +1155,11 @@ PromptManagerModule.prototype.loadMessagesIntoInspectForm = function (messages)
|
|||||||
|
|
||||||
const messageList = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_inspect_list');
|
const messageList = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_inspect_list');
|
||||||
|
|
||||||
if (0 === messages.getCollection().length) messageList.innerHTML = `<span>This marker does not contain any prompts.</span>`;
|
const messagesCollection = messages instanceof Message ? [messages] : messages.getCollection();
|
||||||
|
|
||||||
messages.getCollection().forEach(message => {
|
if (0 === messagesCollection.length) messageList.innerHTML = `<span>This marker does not contain any prompts.</span>`;
|
||||||
|
|
||||||
|
messagesCollection.forEach(message => {
|
||||||
messageList.append(createInlineDrawer(message));
|
messageList.append(createInlineDrawer(message));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ export function getGroupDepthPrompts(groupId, characterId) {
|
|||||||
* Combines group members info a single string. Only for groups with generation mode set to APPEND.
|
* Combines group members info a single string. Only for groups with generation mode set to APPEND.
|
||||||
* @param {string} groupId Group ID
|
* @param {string} groupId Group ID
|
||||||
* @param {number} characterId Current Character ID
|
* @param {number} characterId Current Character ID
|
||||||
* @returns {{description: string, personality: string, scenario: string, mesExample: string}} Group character cards combined
|
* @returns {{description: string, personality: string, scenario: string, mesExamples: string}} Group character cards combined
|
||||||
*/
|
*/
|
||||||
export function getGroupCharacterCards(groupId, characterId) {
|
export function getGroupCharacterCards(groupId, characterId) {
|
||||||
console.debug('getGroupCharacterCards entered for group: ', groupId);
|
console.debug('getGroupCharacterCards entered for group: ', groupId);
|
||||||
@ -271,7 +271,7 @@ export function getGroupCharacterCards(groupId, characterId) {
|
|||||||
let descriptions = [];
|
let descriptions = [];
|
||||||
let personalities = [];
|
let personalities = [];
|
||||||
let scenarios = [];
|
let scenarios = [];
|
||||||
let mesExamples = [];
|
let mesExamplesArray = [];
|
||||||
|
|
||||||
for (const member of group.members) {
|
for (const member of group.members) {
|
||||||
const index = characters.findIndex(x => x.avatar === member);
|
const index = characters.findIndex(x => x.avatar === member);
|
||||||
@ -290,15 +290,15 @@ export function getGroupCharacterCards(groupId, characterId) {
|
|||||||
descriptions.push(baseChatReplace(character.description.trim(), name1, character.name));
|
descriptions.push(baseChatReplace(character.description.trim(), name1, character.name));
|
||||||
personalities.push(baseChatReplace(character.personality.trim(), name1, character.name));
|
personalities.push(baseChatReplace(character.personality.trim(), name1, character.name));
|
||||||
scenarios.push(baseChatReplace(character.scenario.trim(), name1, character.name));
|
scenarios.push(baseChatReplace(character.scenario.trim(), name1, character.name));
|
||||||
mesExamples.push(baseChatReplace(character.mes_example.trim(), name1, character.name));
|
mesExamplesArray.push(baseChatReplace(character.mes_example.trim(), name1, character.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
const description = descriptions.join('\n');
|
const description = descriptions.join('\n');
|
||||||
const personality = personalities.join('\n');
|
const personality = personalities.join('\n');
|
||||||
const scenario = scenarioOverride?.trim() || scenarios.join('\n');
|
const scenario = scenarioOverride?.trim() || scenarios.join('\n');
|
||||||
const mesExample = mesExamples.join('\n');
|
const mesExamples = mesExamplesArray.join('\n');
|
||||||
|
|
||||||
return { description, personality, scenario, mesExample };
|
return { description, personality, scenario, mesExamples };
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFirstCharacterMessage(character) {
|
function getFirstCharacterMessage(character) {
|
||||||
|
@ -1033,7 +1033,7 @@ function prepareOpenAIMessages({
|
|||||||
// Pass chat completion to prompt manager for inspection
|
// Pass chat completion to prompt manager for inspection
|
||||||
promptManager.setChatCompletion(chatCompletion);
|
promptManager.setChatCompletion(chatCompletion);
|
||||||
|
|
||||||
if (oai_settings.squash_system_messages) {
|
if (oai_settings.squash_system_messages && dryRun == false) {
|
||||||
chatCompletion.squashSystemMessages();
|
chatCompletion.squashSystemMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,26 @@
|
|||||||
System-wide Replacement Macros:
|
System-wide Replacement Macros (in order of evaluation):
|
||||||
<ul>
|
<ul>
|
||||||
|
<li><tt>{{original}}</tt> - global prompts defined in API settings. Only valid in Advanced Definitions prompt overrides.</li>
|
||||||
|
<li><tt>{{input}}</tt> - the user input</li>
|
||||||
|
<li><tt>{{description}}</tt> - the Character's Description</li>
|
||||||
|
<li><tt>{{personality}}</tt> - the Character's Personality</li>
|
||||||
|
<li><tt>{{scenario}}</tt> - the Character's Scenario</li>
|
||||||
|
<li><tt>{{persona}}</tt> - your current Persona Description</li>
|
||||||
|
<li><tt>{{mesExamples}}</tt> - the Character's Dialogue Examples</li>
|
||||||
<li><tt>{{user}}</tt> - your current Persona username</li>
|
<li><tt>{{user}}</tt> - your current Persona username</li>
|
||||||
<li><tt>{{char}}</tt> - the Character's name</li>
|
<li><tt>{{char}}</tt> - the Character's name</li>
|
||||||
<li><tt>{{input}}</tt> - the user input</li>
|
|
||||||
<li><tt>{{// (note)}}</tt> - you can leave a note here, and the macro will be replaced with blank content. Not visible for the AI.</li>
|
|
||||||
<li><tt>{{lastMessageId}}</tt> - index # of the latest chat message. Useful for slash command batching.</li>
|
<li><tt>{{lastMessageId}}</tt> - index # of the latest chat message. Useful for slash command batching.</li>
|
||||||
|
<li><tt>{{// (note)}}</tt> - you can leave a note here, and the macro will be replaced with blank content. Not visible for the AI.</li>
|
||||||
<li><tt>{{time}}</tt> - the current time</li>
|
<li><tt>{{time}}</tt> - the current time</li>
|
||||||
<li><tt>{{date}}</tt> - the current date</li>
|
<li><tt>{{date}}</tt> - the current date</li>
|
||||||
<li><tt>{{weekday}}</tt> - the current weekday</li>
|
<li><tt>{{weekday}}</tt> - the current weekday</li>
|
||||||
<li><tt>{{isotime}}</tt> - the current ISO date (YYYY-MM-DD)</li>
|
<li><tt>{{isotime}}</tt> - the current ISO date (YYYY-MM-DD)</li>
|
||||||
<li><tt>{{isodate}}</tt> - the current ISO time (24-hour clock)</li>
|
<li><tt>{{isodate}}</tt> - the current ISO time (24-hour clock)</li>
|
||||||
<li><tt>{{datetimeformat …}}</tt> - the current date/time in the specified format, e. g. for German date/time: <tt>{{datetimeformat DD.MM.YYYY HH:mm}}</tt></li>
|
<li><tt>{{datetimeformat …}}</tt> - the current date/time in the specified format, e. g. for German date/time: <tt>{{datetimeformat DD.MM.YYYY HH:mm}}</tt></li>
|
||||||
<li><tt>{{bias "text here"}}</tt> - sets a behavioral bias for the AI until the next user input. Quotes around the text are important.</li>
|
<li><tt>{{time_UTC±#}}</tt> - the current time in the specified UTC time zone offset, e.g. UTC-4 or UTC+2</li>
|
||||||
<li><tt>{{banned "text here"}}</tt> - 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.</li>
|
|
||||||
<li><tt>{{idle_duration}}</tt> - the time since the last user message was sent</li>
|
<li><tt>{{idle_duration}}</tt> - the time since the last user message was sent</li>
|
||||||
|
<li><tt>{{bias "text here"}}</tt> - sets a behavioral bias for the AI until the next user input. Quotes around the text are important.</li>
|
||||||
<li><tt>{{random:(args)}}</tt> - 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.</li>
|
<li><tt>{{random:(args)}}</tt> - 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.</li>
|
||||||
<li><tt>{{roll:(formula)}}</tt> - rolls a dice. (ex: {{roll:1d6}} will roll a 6-sided dice and return a number between 1 and 6)</li>
|
<li><tt>{{roll:(formula)}}</tt> - rolls a dice. (ex: {{roll:1d6}} will roll a 6-sided dice and return a number between 1 and 6)</li>
|
||||||
|
<li><tt>{{banned "text here"}}</tt> - 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.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
Reference in New Issue
Block a user