Adjust last prompt line of quite gens

This commit is contained in:
Cohee 2024-03-28 21:51:02 +02:00
parent 423a1f85be
commit fcdd90cec4
5 changed files with 58 additions and 44 deletions

View File

@ -2930,7 +2930,7 @@
</div>
</div>
<div class="flex-container">
<div class="flex1" title="Inserted before a System (added by slash commands or extensions) message and as a last prompt line when generating a neutral/system reply.">
<div class="flex1" title="Inserted before a System (added by slash commands or extensions) message.">
<label for="instruct_system_sequence">
<small data-i18n="System Message Prefix">System Message Prefix</small>
</label>
@ -2965,7 +2965,7 @@
<textarea id="instruct_first_output_sequence" class="text_pole textarea_compact autoSetHeight" maxlength="2000" placeholder="&mdash;" rows="1"></textarea>
</div>
</div>
<div class="flex1" title="Inserted before the last Assistant's message.">
<div class="flex1" title="Inserted before the last Assistant's message or as a last prompt line when generating an AI reply (except a neutral/system role).">
<label for="instruct_last_output_sequence">
<small data-i18n="Last Output Prefix">Last Output Prefix</small>
</label>

View File

@ -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<string>} 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);
});

View File

@ -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);

View File

@ -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)

View File

@ -231,7 +231,7 @@ parser.addCommand('delswipe', deleteSwipeCallback, ['swipedel'], '<span class="m
parser.addCommand('echo', echoCallback, [], '<span class="monospace">(title=string severity=info/warning/error/success [text])</span> echoes the text to toast message. Useful for pipes debugging.', true, true);
//parser.addCommand('#', (_, value) => '', [], ' a comment, does nothing, e.g. <tt>/# the next three commands switch variables a and b</tt>', true, true);
parser.addCommand('gen', generateCallback, [], '<span class="monospace">(lock=on/off name="System" [prompt])</span> 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, [], '<span class="monospace">(lock=on/off [prompt])</span> 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. <tt>/genraw instruct=off Why is the sky blue?</tt>. Use stop=... with a JSON-serialized array to add one-time custom stop strings, e.g. <tt>/genraw stop=["\\n"] Say hi</tt>', true, true);
parser.addCommand('genraw', generateRawCallback, [], '<span class="monospace">(lock=on/off instruct=on/off stop=[] as=system/char [prompt])</span> 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. <tt>/genraw instruct=off Why is the sky blue?</tt>. Use stop=... with a JSON-serialized array to add one-time custom stop strings, e.g. <tt>/genraw stop=["\\n"] Say hi</tt>. "as" argument controls the role of the output prompt: system (default) or char.', true, true);
parser.addCommand('addswipe', addSwipeCallback, ['swipeadd'], '<span class="monospace">(text)</span> 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'], '<span class="monospace">(text)</span> 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) {