Merge pull request #3737 from qvink/staging Adding option to disable removal of "{{user}}:" and "{{char}}:" in generateRaw()

97172597761c9ba026928cfc749d9efefa90390d

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
2 files changed, +106 -22Showing whitespace changes
public/script.js+100 -21
@@ -3315,11 +3315,23 @@ class StreamingProcessor {
33153315
3316 if (!isImpersonate && !isContinue && Array.isArray(this.swipes) && this.swipes.length > 0) {3316 if (!isImpersonate && !isContinue && Array.isArray(this.swipes) && this.swipes.length > 0) {
3317 for (let i = 0; i < this.swipes.length; i++) {3317 for (let i = 0; i < this.swipes.length; i++) {
3318 this.swipes[i] = cleanUpMessage(this.swipes[i], false, false, true, this.stoppingStrings);3318 this.swipes[i] = cleanUpMessage({
3319 getMessage: this.swipes[i],
3320 isImpersonate: false,
3321 isContinue: false,
3322 displayIncompleteSentences: true,
3323 stoppingStrings: this.stoppingStrings,
3324 });
3319 }3325 }
3320 }3326 }
33213327
3322 let processedText = cleanUpMessage(text, isImpersonate, isContinue, !isFinal, this.stoppingStrings);3328 let processedText = cleanUpMessage({
3329 getMessage: text,
3330 isImpersonate: isImpersonate,
3331 isContinue: isContinue,
3332 displayIncompleteSentences: !isFinal,
3333 stoppingStrings: this.stoppingStrings,
3334 });
33233335
3324 const charsToBalance = ['*', '"', '```'];3336 const charsToBalance = ['*', '"', '```'];
3325 for (const char of charsToBalance) {3337 for (const char of charsToBalance) {
@@ -3551,9 +3563,10 @@ class StreamingProcessor {
3551 * @param {boolean} quietToLoud true to generate a message in system mode, false to generate a message in character mode3563 * @param {boolean} quietToLoud true to generate a message in system mode, false to generate a message in character mode
3552 * @param {string} [systemPrompt] System prompt to use. Only Instruct mode or OpenAI.3564 * @param {string} [systemPrompt] System prompt to use. Only Instruct mode or OpenAI.
3553 * @param {number} [responseLength] Maximum response length. If unset, the global default value is used.3565 * @param {number} [responseLength] Maximum response length. If unset, the global default value is used.
3566 * @param {boolean} [trimNames] Whether to allow trimming "{{user}}:" and "{{char}}:" from the response.
3554 * @returns {Promise<string>} Generated message3567 * @returns {Promise<string>} Generated message
3555 */3568 */
3556export async function generateRaw(prompt, api, instructOverride, quietToLoud, systemPrompt, responseLength) {3569export async function generateRaw(prompt, api, instructOverride, quietToLoud, systemPrompt, responseLength, trimNames = true) {
3557 if (!api) {3570 if (!api) {
3558 api = main_api;3571 api = main_api;
3559 }3572 }
@@ -3643,7 +3656,15 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy
3643 }3656 }
36443657
3645 // format result, exclude user prompt bias3658 // format result, exclude user prompt bias
3646 const message = cleanUpMessage(extractMessageFromData(data), false, false, true, null, false);3659 const message = cleanUpMessage({
3660 getMessage: extractMessageFromData(data),
3661 isImpersonate: false,
3662 isContinue: false,
3663 displayIncompleteSentences: true,
3664 includeUserPromptBias: false,
3665 trimNames: trimNames,
3666 trimWrongNames: trimNames,
3667 });
36473668
3648 if (!message) {3669 if (!message) {
3649 throw new Error('No message generated');3670 throw new Error('No message generated');
@@ -4844,7 +4865,12 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
48444865
4845 hideSwipeButtons();4866 hideSwipeButtons();
4846 let getMessage = await streamingProcessor.generate();4867 let getMessage = await streamingProcessor.generate();
4847 let messageChunk = cleanUpMessage(getMessage, isImpersonate, isContinue, false);4868 let messageChunk = cleanUpMessage({
4869 getMessage: getMessage,
4870 isImpersonate: isImpersonate,
4871 isContinue: isContinue,
4872 displayIncompleteSentences: false,
4873 });
48484874
4849 if (isContinue) {4875 if (isContinue) {
4850 getMessage = continue_mag + getMessage;4876 getMessage = continue_mag + getMessage;
@@ -4928,7 +4954,14 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
49284954
4929 const swipes = extractMultiSwipes(data, type);4955 const swipes = extractMultiSwipes(data, type);
49304956
4931 messageChunk = cleanUpMessage(getMessage, isImpersonate, isContinue, false);4957 messageChunk = cleanUpMessage({
4958 getMessage: getMessage,
4959 isImpersonate: isImpersonate,
4960 isContinue: isContinue,
4961 displayIncompleteSentences: false,
4962 });
4963
4964
4932 reasoning = getRegexedString(reasoning, regex_placement.REASONING);4965 reasoning = getRegexedString(reasoning, regex_placement.REASONING);
49334966
4934 if (power_user.trim_spaces) {4967 if (power_user.trim_spaces) {
@@ -4942,7 +4975,12 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
49424975
4943 //Formating4976 //Formating
4944 const displayIncomplete = type === 'quiet' && !quietToLoud;4977 const displayIncomplete = type === 'quiet' && !quietToLoud;
4945 getMessage = cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncomplete);4978 getMessage = cleanUpMessage({
4979 getMessage: getMessage,
4980 isImpersonate: isImpersonate,
4981 isContinue: isContinue,
4982 displayIncompleteSentences: displayIncomplete,
4983 });
49464984
4947 if (isImpersonate) {4985 if (isImpersonate) {
4948 $('#send_textarea').val(getMessage)[0].dispatchEvent(new Event('input', { bubbles: true }));4986 $('#send_textarea').val(getMessage)[0].dispatchEvent(new Event('input', { bubbles: true }));
@@ -5908,7 +5946,13 @@ function extractMultiSwipes(data, type) {
59085946
5909 for (let i = 1; i < data.choices.length; i++) {5947 for (let i = 1; i < data.choices.length; i++) {
5910 const text = data?.choices[i]?.message?.content ?? data?.choices[i]?.text ?? '';5948 const text = data?.choices[i]?.message?.content ?? data?.choices[i]?.text ?? '';
5911 const cleanedText = cleanUpMessage(text, false, false, false);5949 const cleanedText = cleanUpMessage({
5950 getMessage: text,
5951 isImpersonate: false,
5952 isContinue: false,
5953 displayIncompleteSentences: false,
5954 });
5955
5912 swipes.push(cleanedText);5956 swipes.push(cleanedText);
5913 }5957 }
5914 }5958 }
@@ -5916,7 +5960,26 @@ function extractMultiSwipes(data, type) {
5916 return swipes;5960 return swipes;
5917}5961}
59185962
5919export function cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncompleteSentences = false, stoppingStrings = null, includeUserPromptBias = true) {5963/**
5964 * Formats a message according to user settings
5965 * @param {object} [options] - Additional options.
5966 * @param {string} [options.getMessage] The message to clean up
5967 * @param {boolean} [options.isImpersonate] Whether this is an impersonated message
5968 * @param {boolean} [options.isContinue] Whether this is a continued message
5969 * @param {boolean} [options.displayIncompleteSentences] Whether to keep incomplete sentences at the end.
5970 * @param {array} [options.stoppingStrings] Array of stopping strings.
5971 * @param {boolean} [options.includeUserPromptBias] Whether to permit prepending the user prompt bias at the beginning.
5972 * @param {boolean} [options.trimNames] Whether to allow trimming "{{char}}:" or "{{user}}:" from the beginning.
5973 * @param {boolean} [options.trimWrongNames] Whether to allow deleting responses prefixed by the incorrect name, depending on isImpersonate
5974 *
5975 * @returns {string} The formatted message
5976 */
5977export function cleanUpMessage({ getMessage, isImpersonate, isContinue, displayIncompleteSentences = false, stoppingStrings = null, includeUserPromptBias = true, trimNames = true, trimWrongNames = true } = {}) {
5978 if (arguments.length > 0 && typeof arguments[0] !== 'object') {
5979 console.trace('cleanUpMessage called with positional arguments. Please use an object instead.');
5980 [getMessage, isImpersonate, isContinue, displayIncompleteSentences, stoppingStrings, includeUserPromptBias, trimNames, trimWrongNames] = arguments;
5981 }
5982
5920 if (!getMessage) {5983 if (!getMessage) {
5921 return '';5984 return '';
5922 }5985 }
@@ -5961,21 +6024,32 @@ export function cleanUpMessage(getMessage, isImpersonate, isContinue, displayInc
5961 // "trailing whitespace on newlines\nevery line of the string\nsample text"6024 // "trailing whitespace on newlines\nevery line of the string\nsample text"
5962 getMessage = getMessage.replace(/[^\S\r\n]+$/gm, '');6025 getMessage = getMessage.replace(/[^\S\r\n]+$/gm, '');
59636026
5964 let nameToTrim = isImpersonate ? name2 : name1;6027 if (trimWrongNames) {
6028 // If this is an impersonation, delete the entire response if it starts with "{{char}}:"
6029 // If this isn't an impersonation, delete the entire response if it starts with "{{user}}:"
6030 // Also delete any trailing text that starts with the wrong name.
6031 // This only occurs if the corresponding "power_user.allow_nameX_display" is false.
59656032
5966 if (isImpersonate) {6033 let wrongName = isImpersonate
5967 nameToTrim = power_user.allow_name2_display ? '' : name2;6034 ? (!power_user.allow_name2_display ? name2 : '') // char
5968 }6035 : (!power_user.allow_name1_display ? name1 : ''); // user
5969 else {6036
5970 nameToTrim = power_user.allow_name1_display ? '' : name1;6037 if (wrongName) {
6038 // If the message starts with the wrong name, delete the entire response
6039 let startIndex = getMessage.indexOf(`${wrongName}:`);
6040 if (startIndex === 0) {
6041 getMessage = '';
6042 console.debug(`Message started with the wrong name: "${wrongName}" - response was deleted.`);
5971 }6043 }
59726044
5973 if (nameToTrim && getMessage.indexOf(`${nameToTrim}:`) == 0) {6045 // If there is trailing text starting with the wrong name, trim it off.
5974 getMessage = getMessage.substring(0, getMessage.indexOf(`${nameToTrim}:`));6046 startIndex = getMessage.indexOf(`\n${wrongName}:`);
6047 if (startIndex >= 0) {
6048 getMessage = getMessage.substring(0, startIndex);
5975 }6049 }
5976 if (nameToTrim && getMessage.indexOf(`\n${nameToTrim}:`) >= 0) {
5977 getMessage = getMessage.substring(0, getMessage.indexOf(`\n${nameToTrim}:`));
5978 }6050 }
6051 }
6052
5979 if (getMessage.indexOf('<|endoftext|>') != -1) {6053 if (getMessage.indexOf('<|endoftext|>') != -1) {
5980 getMessage = getMessage.substring(0, getMessage.indexOf('<|endoftext|>'));6054 getMessage = getMessage.substring(0, getMessage.indexOf('<|endoftext|>'));
5981 }6055 }
@@ -6035,14 +6109,19 @@ export function cleanUpMessage(getMessage, isImpersonate, isContinue, displayInc
6035 getMessage = fixMarkdown(getMessage, false);6109 getMessage = fixMarkdown(getMessage, false);
6036 }6110 }
60376111
6112 if (trimNames) {
6113 // If this is an impersonation, trim "{{user}}:" from the beginning
6114 // If this isn't an impersonation, trim "{{char}}:" from the beginning.
6115 // Only applied when the corresponding "power_user.allow_nameX_display" is false.
6038 const nameToTrim2 = isImpersonate6116 const nameToTrim2 = isImpersonate
6039 ? (!power_user.allow_name1_display ? name1 : '')6117 ? (!power_user.allow_name1_display ? name1 : '') // user
6040 : (!power_user.allow_name2_display ? name2 : '');6118 : (!power_user.allow_name2_display ? name2 : ''); // char
60416119
6042 if (nameToTrim2 && getMessage.startsWith(nameToTrim2 + ':')) {6120 if (nameToTrim2 && getMessage.startsWith(nameToTrim2 + ':')) {
6043 getMessage = getMessage.replace(nameToTrim2 + ':', '');6121 getMessage = getMessage.replace(nameToTrim2 + ':', '');
6044 getMessage = getMessage.trimStart();6122 getMessage = getMessage.trimStart();
6045 }6123 }
6124 }
60466125
6047 if (isImpersonate) {6126 if (isImpersonate) {
6048 getMessage = getMessage.trim();6127 getMessage = getMessage.trim();
public/scripts/logprobs.js+6 -1
@@ -368,7 +368,12 @@ function onToggleLogprobsPanel() {
368function createSwipe(messageId, prompt) {368function createSwipe(messageId, prompt) {
369 // need to call `cleanUpMessage` on our new prompt, because we were working369 // need to call `cleanUpMessage` on our new prompt, because we were working
370 // with raw model output and our new prompt is missing trimming/macro replacements370 // with raw model output and our new prompt is missing trimming/macro replacements
371 const cleanedPrompt = cleanUpMessage(prompt, false, false, true);371 const cleanedPrompt = cleanUpMessage({
372 getMessage: prompt,
373 isImpersonate: false,
374 isContinue: false,
375 displayIncompleteSentences: true,
376 });
372377
373 const msg = chat[messageId];378 const msg = chat[messageId];
374 const newSwipeInfo = {379 const newSwipeInfo = {