diff --git a/public/script.js b/public/script.js
index f77bd991f..c2096a108 100644
--- a/public/script.js
+++ b/public/script.js
@@ -2845,20 +2845,22 @@ class StreamingProcessor {
* @param {string} prompt Prompt to generate a message from
* @param {string} api API to use. Main API is used if not specified.
* @param {boolean} instructOverride true to override instruct mode, false to use the default value
+ * @param {boolean} quietToLoud true to generate a message in system mode, false to generate a message in character mode
* @returns {Promise} Generated message
*/
-export async function generateRaw(prompt, api, instructOverride) {
+export async function generateRaw(prompt, api, instructOverride, quietToLoud) {
if (!api) {
api = main_api;
}
const abortController = new AbortController();
const isInstruct = power_user.instruct.enabled && main_api !== 'openai' && main_api !== 'novel' && !instructOverride;
+ const isQuiet = true;
prompt = substituteParams(prompt);
prompt = api == 'novel' ? adjustNovelInstructionPrompt(prompt) : prompt;
prompt = isInstruct ? formatInstructModeChat(name1, prompt, false, true, '', name1, name2, false) : prompt;
- prompt = isInstruct ? (prompt + formatInstructModePrompt(name2, false, '', name1, name2)) : (prompt + '\n');
+ prompt = isInstruct ? (prompt + formatInstructModePrompt(name2, false, '', name1, name2, isQuiet, quietToLoud)) : (prompt + '\n');
let generateData = {};
@@ -3561,7 +3563,8 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
// Get instruct mode line
if (isInstruct && !isContinue) {
const name = (quiet_prompt && !quietToLoud) ? (quietName ?? 'System') : (isImpersonate ? name1 : name2);
- lastMesString += formatInstructModePrompt(name, isImpersonate, promptBias, name1, name2);
+ const isQuiet = quiet_prompt && type == 'quiet';
+ lastMesString += formatInstructModePrompt(name, isImpersonate, promptBias, name1, name2, isQuiet, quietToLoud);
}
// Get non-instruct impersonation line
@@ -8351,7 +8354,7 @@ function addDebugFunctions() {
registerDebugFunction('generationTest', 'Send a generation request', 'Generates text using the currently selected API.', async () => {
const text = prompt('Input text:', 'Hello');
toastr.info('Working on it...');
- const message = await generateRaw(text, null, '');
+ const message = await generateRaw(text, null, false, false);
alert(message);
});
diff --git a/public/scripts/instruct-mode.js b/public/scripts/instruct-mode.js
index e30d81a3f..eaf0df137 100644
--- a/public/scripts/instruct-mode.js
+++ b/public/scripts/instruct-mode.js
@@ -46,40 +46,25 @@ const controls = [
*/
function migrateInstructModeSettings(settings) {
// Separator sequence => Output suffix
- if (settings.separator_sequence === undefined) {
- return;
+ if (settings.separator_sequence !== undefined) {
+ settings.output_suffix = settings.separator_sequence || '';
+ delete settings.separator_sequence;
}
- settings.output_suffix = settings.separator_sequence || '';
- delete settings.separator_sequence;
+ const defaults = {
+ input_suffix: '',
+ system_sequence: '',
+ system_suffix: '',
+ user_alignment_message: '',
+ names_force_groups: true,
+ skip_examples: false,
+ system_same_as_user: false,
+ };
- // Init the rest with default values
- if (settings.input_suffix === undefined) {
- settings.input_suffix = '';
- }
-
- if (settings.system_sequence === undefined) {
- settings.system_sequence = '';
- }
-
- if (settings.system_suffix === undefined) {
- settings.system_suffix = '';
- }
-
- if (settings.user_alignment_message === undefined) {
- settings.user_alignment_message = '';
- }
-
- if (settings.names_force_groups === undefined) {
- settings.names_force_groups = true;
- }
-
- if (settings.skip_examples === undefined) {
- settings.skip_examples = false;
- }
-
- if (settings.system_same_as_user === undefined) {
- settings.system_same_as_user = false;
+ for (let key in defaults) {
+ if (settings[key] === undefined) {
+ settings[key] = defaults[key];
+ }
}
}
@@ -436,12 +421,34 @@ export function formatInstructModeExamples(mesExamplesArray, name1, name2) {
* @param {string} promptBias Prompt bias string.
* @param {string} name1 User name.
* @param {string} name2 Character name.
+ * @param {boolean} isQuiet Is quiet mode generation.
+ * @param {boolean} isQuietToLoud Is quiet to loud generation.
* @returns {string} Formatted instruct mode last prompt line.
*/
-export function formatInstructModePrompt(name, isImpersonate, promptBias, name1, name2) {
- const includeNames = name && (power_user.instruct.names || (!!selected_group && power_user.instruct.names_force_groups));
- const getOutputSequence = () => power_user.instruct.last_output_sequence || power_user.instruct.output_sequence;
- let sequence = isImpersonate ? power_user.instruct.input_sequence : getOutputSequence();
+export function formatInstructModePrompt(name, isImpersonate, promptBias, name1, name2, isQuiet, isQuietToLoud) {
+ const includeNames = name && (power_user.instruct.names || (!!selected_group && power_user.instruct.names_force_groups)) && !(isQuiet && !isQuietToLoud);
+
+ function getSequence() {
+ // User impersonation prompt
+ if (isImpersonate) {
+ return power_user.instruct.input_sequence;
+ }
+
+ // Neutral / system prompt
+ if (isQuiet && !isQuietToLoud) {
+ return power_user.instruct.output_sequence;
+ }
+
+ // Quiet in-character prompt
+ if (isQuiet && isQuietToLoud) {
+ return power_user.instruct.last_output_sequence || power_user.instruct.output_sequence;
+ }
+
+ // Default AI response
+ return power_user.instruct.last_output_sequence || power_user.instruct.output_sequence;
+ }
+
+ let sequence = getSequence() || '';
if (power_user.instruct.macro) {
sequence = substituteParams(sequence, name1, name2);
diff --git a/public/scripts/openai.js b/public/scripts/openai.js
index bdfd3b827..e7b83c285 100644
--- a/public/scripts/openai.js
+++ b/public/scripts/openai.js
@@ -448,8 +448,10 @@ function convertChatCompletionToInstruct(messages, type) {
const isImpersonate = type === 'impersonate';
const isContinue = type === 'continue';
+ const isQuiet = type === 'quiet';
+ const isQuietToLoud = false; // Quiet to loud not implemented for Chat Completion
const promptName = isImpersonate ? name1 : name2;
- const promptLine = isContinue ? '' : formatInstructModePrompt(promptName, isImpersonate, '', name1, name2).trimStart();
+ const promptLine = isContinue ? '' : formatInstructModePrompt(promptName, isImpersonate, '', name1, name2, isQuiet, isQuietToLoud).trimStart();
let prompt = [systemPromptText, examplesText, chatMessagesText, promptLine]
.filter(x => x)
diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js
index 20f3e8666..7d4c63dbe 100644
--- a/public/scripts/slash-commands.js
+++ b/public/scripts/slash-commands.js
@@ -231,7 +231,7 @@ parser.addCommand('delswipe', deleteSwipeCallback, ['swipedel'], '(title=string severity=info/warning/error/success [text]) – echoes the text to toast message. Useful for pipes debugging.', true, true);
//parser.addCommand('#', (_, value) => '', [], ' – a comment, does nothing, e.g. /# the next three commands switch variables a and b', true, true);
parser.addCommand('gen', generateCallback, [], '(lock=on/off name="System" [prompt]) – generates text using the provided prompt and passes it to the next command through the pipe, optionally locking user input while generating and allowing to configure the in-prompt name for instruct mode (default = "System").', true, true);
-parser.addCommand('genraw', generateRawCallback, [], '(lock=on/off [prompt]) – generates text using the provided prompt and passes it to the next command through the pipe, optionally locking user input while generating. Does not include chat history or character card. Use instruct=off to skip instruct formatting, e.g. /genraw instruct=off Why is the sky blue?. Use stop=... with a JSON-serialized array to add one-time custom stop strings, e.g. /genraw stop=["\\n"] Say hi', true, true);
+parser.addCommand('genraw', generateRawCallback, [], '(lock=on/off instruct=on/off stop=[] as=system/char [prompt]) – generates text using the provided prompt and passes it to the next command through the pipe, optionally locking user input while generating. Does not include chat history or character card. Use instruct=off to skip instruct formatting, e.g. /genraw instruct=off Why is the sky blue?. Use stop=... with a JSON-serialized array to add one-time custom stop strings, e.g. /genraw stop=["\\n"] Say hi. "as" argument controls the role of the output prompt: system (default) or char.', true, true);
parser.addCommand('addswipe', addSwipeCallback, ['swipeadd'], '(text) – adds a swipe to the last chat message.', true, true);
parser.addCommand('abort', abortCallback, [], ' – aborts the slash command batch execution', true, true);
parser.addCommand('fuzzy', fuzzyCallback, [], 'list=["a","b","c"] threshold=0.4 (text to search) – performs a fuzzy match of each items of list within the text to search. If any item matches then its name is returned. If no item list matches the text to search then no value is returned. The optional threshold (default is 0.4) allows some control over the matching. A low value (min 0.0) means the match is very strict. At 1.0 (max) the match is very loose and probably matches anything. The returned value passes to the next command through the pipe.', true, true); parser.addCommand('pass', (_, arg) => arg, ['return'], '(text) – passes the text to the next command through the pipe.', true, true);
@@ -659,6 +659,8 @@ async function generateRawCallback(args, value) {
// Prevent generate recursion
$('#send_textarea').val('').trigger('input');
const lock = isTrueBoolean(args?.lock);
+ const as = args?.as || 'system';
+ const quietToLoud = as === 'char';
try {
if (lock) {
@@ -666,7 +668,7 @@ async function generateRawCallback(args, value) {
}
setEphemeralStopStrings(resolveVariable(args?.stop));
- const result = await generateRaw(value, '', isFalseBoolean(args?.instruct));
+ const result = await generateRaw(value, '', isFalseBoolean(args?.instruct), quietToLoud);
return result;
} finally {
if (lock) {