Add per-character system prompt overrides

This commit is contained in:
Cohee
2023-06-08 01:47:24 +03:00
parent 9dd2a3b949
commit 0642abbfe5
6 changed files with 63 additions and 33 deletions

View File

@ -205,12 +205,12 @@
"UI Theme Preset":"UI Theme Preset", "UI Theme Preset":"UI Theme Preset",
"Power User Options":"Power User Options", "Power User Options":"Power User Options",
"Swipes":"Swipes", "Swipes":"Swipes",
"Background Sound Only":"Background Sound Only", "Background Sound Only":"BG Sound Only",
"Auto-load Last Chat":"Auto-load Last Chat", "Auto-load Last Chat":"Auto-load Last Chat",
"Auto-save Message Edits":"Auto-save Message Edits", "Auto-save Message Edits":"Auto-save Chat Edits",
"Auto-fix Markdown":"Auto-fix Markdown", "Auto-fix Markdown":"Auto-fix Markdown",
"Allow {{char}}: in bot messages":"Allow {{char}}: in bot messages", "Allow {{char}}: in bot messages":"Show {{char}} in messages",
"Allow {{user}}: in bot messages":"Allow {{user}}: in bot messages", "Allow {{user}}: in bot messages":"Show {{user}} in messages",
"Auto-scroll Chat":"Auto-scroll Chat", "Auto-scroll Chat":"Auto-scroll Chat",
"Render Formulas":"Render Formulas", "Render Formulas":"Render Formulas",
"Send on Enter":"Send on Enter", "Send on Enter":"Send on Enter",

View File

@ -1882,6 +1882,20 @@
</label> </label>
</div> </div>
<div> <div>
<label for="play_message_sound" class="checkbox_label">
<input id="play_message_sound" type="checkbox" />
<audio id="audio_message_sound" src="sounds/message.mp3" hidden></audio>
<span>
<span data-i18n="Message Sound">Message Sound</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#message-sound" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</span>
</label>
<label for="play_sound_unfocused" class="checkbox_label">
<input id="play_sound_unfocused" type="checkbox" />
<span data-i18n="Background Sound Only">Background Sound Only</span>
</label>
<label for="fast_ui_mode" class="checkbox_label" title="removes blur and uses alternative background color for divs"> <label for="fast_ui_mode" class="checkbox_label" title="removes blur and uses alternative background color for divs">
<input id="fast_ui_mode" type="checkbox" /> <input id="fast_ui_mode" type="checkbox" />
<span data-i18n="No Blur Effect">No Blur Effect</span> <span data-i18n="No Blur Effect">No Blur Effect</span>
@ -1900,6 +1914,11 @@
<span data-i18n="Message Timer">Message Timer</span> <span data-i18n="Message Timer">Message Timer</span>
</label> </label>
<label for="auto_scroll_chat_to_bottom" class="checkbox_label">
<input id="auto_scroll_chat_to_bottom" type="checkbox" />
<span data-i18n="Auto-scroll Chat">Auto-scroll Chat</span>
</label>
<label for="hotswapEnabled" class="checkbox_label"> <label for="hotswapEnabled" class="checkbox_label">
<input id="hotswapEnabled" type="checkbox" /> <input id="hotswapEnabled" type="checkbox" />
<span data-i18n="Characters Hotswap">Characters Hotswap</span> <span data-i18n="Characters Hotswap">Characters Hotswap</span>
@ -2012,19 +2031,13 @@
<input id="swipes-checkbox" type="checkbox" /> <input id="swipes-checkbox" type="checkbox" />
<span data-i18n="Swipes">Swipes</span> <span data-i18n="Swipes">Swipes</span>
</label> </label>
<label for="play_message_sound" class="checkbox_label"> <label data-i18n="Prefer Character Card Prompt" for="prefer_character_prompt" title="If checked and the character card contains a prompt override (System Prompt), use that instead." class="checkbox_label">
<input id="play_message_sound" type="checkbox" /> <input id="prefer_character_prompt" type="checkbox" />
<audio id="audio_message_sound" src="sounds/message.mp3" hidden></audio> Prefer Char. Prompt
<span>
<span data-i18n="Message Sound">Message Sound</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#message-sound" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</span>
</label> </label>
<label for="play_sound_unfocused" class="checkbox_label"> <label data-i18n="Prefer Character Card Jailbreak" for="prefer_character_jailbreak" title="If checked and the character card contains a jailbreak override (Post History Instruction), use that instead." class="checkbox_label">
<input id="play_sound_unfocused" type="checkbox" /> <input id="prefer_character_jailbreak" type="checkbox" />
<span data-i18n="Background Sound Only">Background Sound Only</span> Prefer Char. JB
</label> </label>
<label for="auto-load-chat-checkbox"><input id="auto-load-chat-checkbox" type="checkbox" /> <label for="auto-load-chat-checkbox"><input id="auto-load-chat-checkbox" type="checkbox" />
<span data-i18n="Auto-load Last Chat">Auto-load Last Chat</span> <span data-i18n="Auto-load Last Chat">Auto-load Last Chat</span>
@ -2038,15 +2051,11 @@
</label> </label>
<label class="checkbox_label" for="allow_name2_display"> <label class="checkbox_label" for="allow_name2_display">
<input id="allow_name2_display" type="checkbox" /> <input id="allow_name2_display" type="checkbox" />
<span data-i18n="Allow {{char}}: in bot messages">Allow {{char}}: in bot messages</span> <span data-i18n="Allow {{char}}: in bot messages">Show {{char}} responses</span>
</label> </label>
<label class="checkbox_label" for="allow_name1_display"> <label class="checkbox_label" for="allow_name1_display">
<input id="allow_name1_display" type="checkbox" /> <input id="allow_name1_display" type="checkbox" />
<span data-i18n="Allow {{user}}: in bot messages">Allow {{user}}: in bot messages</span> <span data-i18n="Allow {{user}}: in bot messages">Show {{user}} responses</span>
</label>
<label for="auto_scroll_chat_to_bottom">
<input id="auto_scroll_chat_to_bottom" type="checkbox" />
<span data-i18n="Auto-scroll Chat">Auto-scroll Chat</span>
</label> </label>
<label for="console_log_prompts"> <label for="console_log_prompts">
<input id="console_log_prompts" type="checkbox" /> <input id="console_log_prompts" type="checkbox" />

View File

@ -1898,6 +1898,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
let charPersonality = baseChatReplace(characters[this_chid].personality.trim(), name1, name2); let charPersonality = baseChatReplace(characters[this_chid].personality.trim(), name1, name2);
let Scenario = baseChatReplace(scenarioText.trim(), name1, name2); let Scenario = baseChatReplace(scenarioText.trim(), name1, name2);
let mesExamples = baseChatReplace(characters[this_chid].mes_example.trim(), name1, name2); let mesExamples = baseChatReplace(characters[this_chid].mes_example.trim(), name1, name2);
let systemPrompt = baseChatReplace(characters[this_chid].data?.system_prompt?.trim(), name1, name2);
// Parse example messages // Parse example messages
if (!mesExamples.startsWith('<START>')) { if (!mesExamples.startsWith('<START>')) {
@ -1956,7 +1957,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
} }
if (isInstruct) { if (isInstruct) {
storyString = formatInstructStoryString(storyString); storyString = formatInstructStoryString(storyString, systemPrompt);
} }
////////////////////////////////// //////////////////////////////////
@ -2278,7 +2279,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
generate_data = getNovelGenerationData(finalPromt, this_settings, this_amount_gen); generate_data = getNovelGenerationData(finalPromt, this_settings, this_amount_gen);
} }
else if (main_api == 'openai') { else if (main_api == 'openai') {
let [prompt, counts] = await prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldInfoAfter, afterScenarioAnchor, promptBias, type, quiet_prompt); let [prompt, counts] = await prepareOpenAIMessages(systemPrompt, name2, storyString, worldInfoBefore, worldInfoAfter, afterScenarioAnchor, promptBias, type, quiet_prompt);
generate_data = { prompt: prompt }; generate_data = { prompt: prompt };
// counts will return false if the user has not enabled the token breakdown feature // counts will return false if the user has not enabled the token breakdown feature

View File

@ -310,7 +310,7 @@ function formatWorldInfo(value) {
return stringFormat(oai_settings.wi_format, value); return stringFormat(oai_settings.wi_format, value);
} }
async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldInfoAfter, extensionPrompt, bias, type, quietPrompt) { async function prepareOpenAIMessages(systemPrompt, name2, storyString, worldInfoBefore, worldInfoAfter, extensionPrompt, bias, type, quietPrompt) {
const isImpersonate = type == "impersonate"; const isImpersonate = type == "impersonate";
let this_max_context = oai_settings.openai_max_context; let this_max_context = oai_settings.openai_max_context;
let enhance_definitions_prompt = ""; let enhance_definitions_prompt = "";
@ -324,7 +324,7 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
const wiBefore = formatWorldInfo(worldInfoBefore); const wiBefore = formatWorldInfo(worldInfoBefore);
const wiAfter = formatWorldInfo(worldInfoAfter); const wiAfter = formatWorldInfo(worldInfoAfter);
let whole_prompt = getSystemPrompt(nsfw_toggle_prompt, enhance_definitions_prompt, wiBefore, storyString, wiAfter, extensionPrompt, isImpersonate); let whole_prompt = getSystemPrompt(systemPrompt, nsfw_toggle_prompt, enhance_definitions_prompt, wiBefore, storyString, wiAfter, extensionPrompt, isImpersonate);
// Join by a space and replace placeholders with real user/char names // Join by a space and replace placeholders with real user/char names
storyString = substituteParams(whole_prompt.join("\n")).replace(/\r/gm, '').trim(); storyString = substituteParams(whole_prompt.join("\n")).replace(/\r/gm, '').trim();
@ -488,7 +488,9 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
]; ];
} }
function getSystemPrompt(nsfw_toggle_prompt, enhance_definitions_prompt, wiBefore, storyString, wiAfter, extensionPrompt, isImpersonate) { function getSystemPrompt(systemPrompt, nsfw_toggle_prompt, enhance_definitions_prompt, wiBefore, storyString, wiAfter, extensionPrompt, isImpersonate) {
// If the character has a custom system prompt AND user has it preferred, use that instead of the default
let prompt = power_user.prefer_character_prompt && systemPrompt ? systemPrompt : oai_settings.main_prompt;
let whole_prompt = []; let whole_prompt = [];
if (isImpersonate) { if (isImpersonate) {
@ -497,10 +499,10 @@ function getSystemPrompt(nsfw_toggle_prompt, enhance_definitions_prompt, wiBefor
else { else {
// If it's toggled, NSFW prompt goes first. // If it's toggled, NSFW prompt goes first.
if (oai_settings.nsfw_first) { if (oai_settings.nsfw_first) {
whole_prompt = [nsfw_toggle_prompt, oai_settings.main_prompt, enhance_definitions_prompt + "\n\n" + wiBefore, storyString, wiAfter, extensionPrompt]; whole_prompt = [nsfw_toggle_prompt, prompt, enhance_definitions_prompt + "\n\n" + wiBefore, storyString, wiAfter, extensionPrompt];
} }
else { else {
whole_prompt = [oai_settings.main_prompt, nsfw_toggle_prompt, enhance_definitions_prompt, "\n", wiBefore, storyString, wiAfter, extensionPrompt].filter(elem => elem); whole_prompt = [prompt, nsfw_toggle_prompt, enhance_definitions_prompt, "\n", wiBefore, storyString, wiAfter, extensionPrompt].filter(elem => elem);
} }
} }
return whole_prompt; return whole_prompt;

View File

@ -128,6 +128,8 @@ let power_user = {
hotswap_enabled: true, hotswap_enabled: true,
timer_enabled: true, timer_enabled: true,
max_context_unlocked: false, max_context_unlocked: false,
prefer_character_prompt: true,
prefer_character_jailbreak: true,
instruct: { instruct: {
enabled: false, enabled: false,
@ -527,6 +529,8 @@ function loadPowerUserSettings(settings, data) {
$("#allow_name2_display").prop("checked", power_user.allow_name2_display); $("#allow_name2_display").prop("checked", power_user.allow_name2_display);
$("#hotswapEnabled").prop("checked", power_user.hotswap_enabled); $("#hotswapEnabled").prop("checked", power_user.hotswap_enabled);
$("#messageTimerEnabled").prop("checked", power_user.timer_enabled); $("#messageTimerEnabled").prop("checked", power_user.timer_enabled);
$("#prefer_character_prompt").prop("checked", power_user.prefer_character_prompt);
$("#prefer_character_jailbreak").prop("checked", power_user.prefer_character_jailbreak);
$(`input[name="avatar_style"][value="${power_user.avatar_style}"]`).prop("checked", true); $(`input[name="avatar_style"][value="${power_user.avatar_style}"]`).prop("checked", true);
$(`input[name="chat_display"][value="${power_user.chat_display}"]`).prop("checked", true); $(`input[name="chat_display"][value="${power_user.chat_display}"]`).prop("checked", true);
$(`input[name="sheld_width"][value="${power_user.sheld_width}"]`).prop("checked", true); $(`input[name="sheld_width"][value="${power_user.sheld_width}"]`).prop("checked", true);
@ -657,11 +661,13 @@ export function formatInstructModeChat(name, mes, isUser, isNarrator, forceAvata
return text; return text;
} }
export function formatInstructStoryString(story) { export function formatInstructStoryString(story, systemPrompt) {
// If the character has a custom system prompt AND user has it preferred, use that instead of the default
systemPrompt = power_user.prefer_character_prompt && systemPrompt ? systemPrompt : power_user.instruct.system_prompt;
const sequence = power_user.instruct.system_sequence || ''; const sequence = power_user.instruct.system_sequence || '';
const prompt = substituteParams(power_user.instruct.system_prompt) || ''; const prompt = substituteParams(systemPrompt) || '';
const separator = power_user.instruct.wrap ? '\n' : ''; const separator = power_user.instruct.wrap ? '\n' : '';
const textArray = [sequence, prompt, story, separator]; const textArray = [sequence, prompt + '\n' + story, separator];
const text = textArray.filter(x => x).join(separator); const text = textArray.filter(x => x).join(separator);
return text; return text;
} }
@ -1170,6 +1176,18 @@ $(document).ready(() => {
switchHotswap(); switchHotswap();
}); });
$("#prefer_character_prompt").on("input", function () {
const value = !!$(this).prop('checked');
power_user.prefer_character_prompt = value;
saveSettingsDebounced();
});
$("#prefer_character_jailbreak").on("input", function () {
const value = !!$(this).prop('checked');
power_user.prefer_character_jailbreak = value;
saveSettingsDebounced();
});
$(window).on('focus', function () { $(window).on('focus', function () {
browser_has_focus = true; browser_has_focus = true;
}); });

View File

@ -4576,4 +4576,4 @@ body.waifuMode #avatar_zoom_popup {
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
} }
} }