(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> </a>
</h3> </h3>
<div class="flex-container"> <div class="flex-container">
<div name="PygOverrides"> <div name="PygOverrides" class="flex1">
<h4>AutoFormat Overrides</h4> <h4>AutoFormat Overrides</h4>
<label class="checkbox_label" for="disable-description-formatting-checkbox"> <label class="checkbox_label" for="disable-description-formatting-checkbox">
<input id="disable-description-formatting-checkbox" type="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" /> <input id="custom_chat_separator" class="text_pole" type="text" placeholder="&lt;START&gt;" maxlength="100" />
</div> </div>
</div> </div>
<div id="anchors-block"> <div>
<h4> <h4>Instruct mode</h4>
Anchors Order <label for="instruct_enabled" class="checkbox_label">
<a href="/notes#anchors" class="notes-link" target="_blank"> <input id="instruct_enabled" type="checkbox" />
<span class="note-link-span">?</span> Enabled
</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>
<label for="style_anchor"><input id="style_anchor" type="checkbox" /> <label>
Style Anchor 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> </label>
</div> </div>
</div> </div>
</div> <div name="ContextFormatting" class="flex1">
<div name="ContextFormatting">
<h4>Context Formatting</h4> <h4>Context Formatting</h4>
<div> <div>
<h4>Tokenizer <h4>Tokenizer
@ -1268,6 +1285,26 @@
</label> </label>
</div> </div>
</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> </div>
</div> </div>

View File

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

View File

@ -7,9 +7,11 @@ import {
reloadMarkdownProcessor, reloadMarkdownProcessor,
reloadCurrentChat, reloadCurrentChat,
getRequestHeaders, getRequestHeaders,
substituteParams,
} from "../script.js"; } from "../script.js";
import { import {
groups, groups,
selected_group,
} from "./group-chats.js"; } from "./group-chats.js";
export { export {
@ -109,6 +111,16 @@ let power_user = {
allow_name2_display: false, allow_name2_display: false,
hotswap_enabled: true, hotswap_enabled: true,
timer_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 = []; 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); $(`#character_sort_order option[data-order="${power_user.sort_order}"][data-field="${power_user.sort_field}"]`).prop("selected", true);
sortCharactersList(); sortCharactersList();
reloadMarkdownProcessor(power_user.render_formulas); 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); const sortFunc = (a, b) => power_user.sort_order == 'asc' ? compareFunc(a, b) : compareFunc(b, a);