(Beta) Add instruct mode #250

This commit is contained in:
SillyLossy
2023-05-10 02:13:14 +03:00
parent f5b2a9a213
commit 730e3578ab
3 changed files with 152 additions and 27 deletions

View File

@ -1150,7 +1150,7 @@
</a>
</h3>
<div class="flex-container">
<div name="PygOverrides">
<div name="PygOverrides" class="flex1">
<h4>AutoFormat Overrides</h4>
<label class="checkbox_label" for="disable-description-formatting-checkbox">
<input id="disable-description-formatting-checkbox" type="checkbox" />
@ -1180,28 +1180,45 @@
<input id="custom_chat_separator" class="text_pole" type="text" placeholder="&lt;START&gt;" maxlength="100" />
</div>
</div>
<div id="anchors-block">
<h4>
Anchors Order
<a href="/notes#anchors" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</h4>
<select id="anchor_order">
<option value="0">Character then Style</option>
<option value="1">Style then Character</option>
</select>
<div id="anchor_checkbox">
<label for="character_anchor"><input id="character_anchor" type="checkbox" />
Character Anchor
</label>
<label for="style_anchor"><input id="style_anchor" type="checkbox" />
Style Anchor
</label>
<div>
<h4>Instruct mode</h4>
<label for="instruct_enabled" class="checkbox_label">
<input id="instruct_enabled" type="checkbox" />
Enabled
</label>
<label>
System Prompt
</label>
<textarea id="instruct_system_prompt" class="text_pole textarea_compact"></textarea>
<label for="instruct_system_sequence">
System Sequence
</label>
<div>
<input id="instruct_system_sequence" class="text_pole textarea_compact" type="text" maxlength="100" />
</div>
<label for="instruct_input_sequence">
Input Sequence
</label>
<div>
<input id="instruct_input_sequence" class="text_pole textarea_compact" type="text" maxlength="100" />
</div>
<label for="instruct_output_sequence">
Output Sequence
</label>
<div>
<input id="instruct_output_sequence" class="text_pole textarea_compact" type="text" maxlength="100" />
</div>
<label for="instruct_wrap" class="checkbox_label">
<input id="instruct_wrap" type="checkbox" />
Wrap Sequences with Newline
</label>
<label for="instruct_names" class="checkbox_label">
<input id="instruct_names" type="checkbox" />
Include Names
</label>
</div>
</div>
<div name="ContextFormatting">
<div name="ContextFormatting" class="flex1">
<h4>Context Formatting</h4>
<div>
<h4>Tokenizer
@ -1268,6 +1285,26 @@
</label>
</div>
</div>
<div id="anchors-block">
<h4>
Anchors Order
<a href="/notes#anchors" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</h4>
<select id="anchor_order">
<option value="0">Character then Style</option>
<option value="1">Style then Character</option>
</select>
<div id="anchor_checkbox">
<label for="character_anchor"><input id="character_anchor" type="checkbox" />
Character Anchor
</label>
<label for="style_anchor"><input id="style_anchor" type="checkbox" />
Style Anchor
</label>
</div>
</div>
</div>
</div>
</div>

View File

@ -60,6 +60,9 @@ import {
power_user,
pygmalion_options,
tokenizers,
formatInstructModeChat,
formatInstructStoryString,
formatInstructModePrompt,
} from "./scripts/power-user.js";
import {
@ -1218,6 +1221,15 @@ function getStoppingStrings(isImpersonate, addSpace) {
}
}
if (power_user.instruct.enabled) {
if (power_user.instruct.input_sequence) {
result.push(`\n${power_user.instruct.input_sequence}`);
}
if (power_user.instruct.output_sequence) {
result.push(`\n${power_user.instruct.output_sequence}`);
}
}
return addSpace ? result.map(x => `${x} `) : result;
}
@ -1542,6 +1554,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
generation_started = new Date();
const isImpersonate = type == "impersonate";
const isInstruct = power_user.instruct.enabled;
message_already_generated = isImpersonate ? `${name1}: ` : `${name2}: `;
const interruptedByCommand = processCommands($("#send_textarea").val(), type);
@ -1720,6 +1733,10 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
force_name2 = false;
}
if (isInstruct) {
storyString = formatInstructStoryString(storyString);
}
//////////////////////////////////
let chat2 = [];
@ -1733,7 +1750,6 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
let charName = selected_group ? coreChat[j].name : name2;
let this_mes_ch_name = '';
if (coreChat[j]['is_user']) {
//this_mes_ch_name = name1;
this_mes_ch_name = coreChat[j]['name'];
} else {
this_mes_ch_name = charName;
@ -1744,10 +1760,12 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
chat2[i] = coreChat[j]['mes'] + '\n';
}
if (isInstruct) {
chat2[i] = formatInstructModeChat(this_mes_ch_name, coreChat[j]['mes'], coreChat[j]['is_user']);
}
// replace bias markup
//chat2[i] = (chat2[i] ?? '').replace(/{.*}/g, '');
chat2[i] = (chat2[i] ?? '').replace(/{{(\*?.*\*?)}}/g, '');
//console.log('replacing chat2 {}s');
}
//chat2 = chat2.reverse();
@ -1904,7 +1922,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
item += anchorBottom + "\n";
}
}
if (is_pygmalion) {
if (is_pygmalion && !isInstruct) {
if (i === arrMes.length - 1 && item.trim().startsWith(name1 + ":")) {//for add name2 when user sent
item = item + name2 + ":";
}
@ -1951,9 +1969,14 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
mesExmString = pinExmString ?? mesExamplesArray.slice(0, count_exm_add).join('');
mesSendString = '';
for (let j = 0; j < mesSend.length; j++) {
const isBottom = j === mesSend.length - 1;
mesSendString += mesSend[j];
if (isImpersonate && j === mesSend.length - 1 && tokens_already_generated === 0) {
if (isInstruct && isBottom && tokens_already_generated === 0) {
mesSendString += formatInstructModePrompt(isImpersonate);
}
if (!isInstruct && isImpersonate && isBottom && tokens_already_generated === 0) {
const name = is_pygmalion ? 'You' : name1;
if (!mesSendString.endsWith('\n')) {
mesSendString += '\n';
@ -1961,7 +1984,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
mesSendString += name + ':';
}
if (force_name2 && j === mesSend.length - 1 && tokens_already_generated === 0) {
if (force_name2 && isBottom && tokens_already_generated === 0) {
if (!mesSendString.endsWith('\n')) {
mesSendString += '\n';
}

View File

@ -7,9 +7,11 @@ import {
reloadMarkdownProcessor,
reloadCurrentChat,
getRequestHeaders,
substituteParams,
} from "../script.js";
import {
groups,
selected_group,
} from "./group-chats.js";
export {
@ -109,6 +111,16 @@ let power_user = {
allow_name2_display: false,
hotswap_enabled: true,
timer_enabled: true,
instruct: {
enabled: false,
wrap: true,
names: false,
system_prompt: "Below is an instruction that describes a task. Write a response that appropriately completes the request.\n\nWrite {{char}}'s next reply in a fictional roleplay chat between {{user}} and {{char}}. Write 1 reply only.",
system_sequence: '',
input_sequence: '### Instruction:',
output_sequence: '### Response:',
}
};
let themes = [];
@ -514,6 +526,59 @@ function loadPowerUserSettings(settings, data) {
$(`#character_sort_order option[data-order="${power_user.sort_order}"][data-field="${power_user.sort_field}"]`).prop("selected", true);
sortCharactersList();
reloadMarkdownProcessor(power_user.render_formulas);
loadInstructMode();
}
function loadInstructMode() {
const controls = [
{ id: "instruct_enabled", property: "enabled", isCheckbox: true },
{ id: "instruct_wrap", property: "wrap", isCheckbox: true },
{ id: "instruct_system_prompt", property: "system_prompt", isCheckbox: false },
{ id: "instruct_system_sequence", property: "system_sequence", isCheckbox: false },
{ id: "instruct_input_sequence", property: "input_sequence", isCheckbox: false },
{ id: "instruct_output_sequence", property: "output_sequence", isCheckbox: false },
{ id: "instruct_names", property: "names", isCheckbox: true },
];
controls.forEach(control => {
const $element = $(`#${control.id}`);
if (control.isCheckbox) {
$element.prop('checked', power_user.instruct[control.property]);
} else {
$element.val(power_user.instruct[control.property]);
}
$element.on('input', function () {
power_user.instruct[control.property] = control.isCheckbox ? $(this).prop('checked') : $(this).val();
saveSettingsDebounced();
});
});
}
export function formatInstructModeChat(name, mes, isUser) {
const includeNames = power_user.instruct.names || (selected_group && !isUser);
const sequence = isUser ? power_user.instruct.input_sequence : power_user.instruct.output_sequence;
const separator = power_user.instruct.wrap ? '\n' : '';
const textArray = includeNames ? [sequence, name, ': ', mes, separator] : [sequence, mes, separator];
const text = textArray.filter(x => x).join(separator);
return text;
}
export function formatInstructStoryString(story) {
const sequence = power_user.instruct.system_sequence || '';
const prompt = substituteParams(power_user.instruct.system_prompt) || '';
const separator = power_user.instruct.wrap ? '\n' : '';
const textArray = [sequence, prompt, story, separator];
const text = textArray.filter(x => x).join(separator);
return text;
}
export function formatInstructModePrompt(isImpersonate) {
const sequence = isImpersonate ? power_user.instruct.input_sequence : power_user.instruct.output_sequence;
const separator = power_user.instruct.wrap ? '\n' : '';
const text = separator + sequence;
return text;
}
const sortFunc = (a, b) => power_user.sort_order == 'asc' ? compareFunc(a, b) : compareFunc(b, a);