adding prefill parameter to generateRaw() (#4266) * adding prefill parameter to generateRaw() * additional comments * Substitute params in prefill * Add prefill prompt for /genraw command * Fix param comment * fixing generateRaw param comment * fixing param comment --------- Co-authored-by: qvink <qvink@users.noreply.github.com> Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>

556fb4ba087a432fea7667079194cbb7bc48aebc

qvink <191186569+qvink@users.noreply.github.com>

Signed
2 files changed, +31 -12Ignore whitespace
public/script.js+17 -7
@@ -3058,10 +3058,11 @@ class StreamingProcessor {
3058 * @param {string} api API to use.3058 * @param {string} api API to use.
3059 * @param {boolean} instructOverride true to override instruct mode, false to use the default value3059 * @param {boolean} instructOverride true to override instruct mode, false to use the default value
3060 * @param {boolean} quietToLoud true to generate a message in system mode, false to generate a message in character mode3060 * @param {boolean} quietToLoud true to generate a message in system mode, false to generate a message in character mode
3061 * @param {string} [systemPrompt] System prompt to use. Only Instruct mode or OpenAI.3061 * @param {string} [systemPrompt] System prompt to use.
3062 * @param {string} [prefill] Prefill for the prompt.
3062 * @returns {string | object[]} Prompt ready for use in generation. If using TC, this will be a string. If using CC, this will be an array of chat-style messages.3063 * @returns {string | object[]} Prompt ready for use in generation. If using TC, this will be a string. If using CC, this will be an array of chat-style messages.
3063 */3064 */
3064export function createRawPrompt(prompt, api, instructOverride, quietToLoud, systemPrompt) {3065export function createRawPrompt(prompt, api, instructOverride, quietToLoud, systemPrompt, prefill) {
3065 const isInstruct = power_user.instruct.enabled && api !== 'openai' && api !== 'novel' && !instructOverride;3066 const isInstruct = power_user.instruct.enabled && api !== 'openai' && api !== 'novel' && !instructOverride;
30663067
3067 // If the prompt was given as a string, convert to a message-style object assuming user role3068 // If the prompt was given as a string, convert to a message-style object assuming user role
@@ -3074,6 +3075,9 @@ export function createRawPrompt(prompt, api, instructOverride, quietToLoud, syst
3074 if (prompt.length === 0 && !systemPrompt) throw Error('No messages provided');3075 if (prompt.length === 0 && !systemPrompt) throw Error('No messages provided');
3075 }3076 }
30763077
3078 // Substitute the prefill if provided
3079 prefill = substituteParams(prefill ?? '');
3080
3077 // Format each message in the prompt, accounting for the provided roles3081 // Format each message in the prompt, accounting for the provided roles
3078 for (const message of prompt) {3082 for (const message of prompt) {
3079 let name = '';3083 let name = '';
@@ -3096,12 +3100,17 @@ export function createRawPrompt(prompt, api, instructOverride, quietToLoud, syst
3096 prompt.unshift({ role: 'system', content: systemPrompt });3100 prompt.unshift({ role: 'system', content: systemPrompt });
3097 }3101 }
30983102
3099 // If text completion, convert to text prompt by concatenating all message contents3103 // with Chat Completion, the prefill is an additional assistant message at the end.
3104 if (api === 'openai' && prefill) {
3105 prompt.push({ role: 'assistant', content: prefill });
3106 }
3107
3108 // if text completion, convert to text prompt by concatenating all message contents and adding the prefill as a promptBias.
3100 if (api !== 'openai') {3109 if (api !== 'openai') {
3101 const joiner = isInstruct ? '' : '\n';3110 const joiner = isInstruct ? '' : '\n';
3102 prompt = prompt.map(message => message.content).join(joiner);3111 prompt = prompt.map(message => message.content).join(joiner);
3103 prompt = api === 'novel' ? adjustNovelInstructionPrompt(prompt) : prompt;3112 prompt = api === 'novel' ? adjustNovelInstructionPrompt(prompt) : prompt;
3104 prompt = prompt + (isInstruct ? formatInstructModePrompt(name2, false, '', name1, name2, true, quietToLoud) : '\n'); // add last line3113 prompt = prompt + (isInstruct ? formatInstructModePrompt(name2, false, prefill, name1, name2, true, quietToLoud) : `\n${prefill}`); // add last line
3105 }3114 }
31063115
3107 return prompt;3116 return prompt;
@@ -3114,12 +3123,13 @@ export function createRawPrompt(prompt, api, instructOverride, quietToLoud, syst
3114 * @param {string} api API to use. Main API is used if not specified.3123 * @param {string} api API to use. Main API is used if not specified.
3115 * @param {boolean} instructOverride true to override instruct mode, false to use the default value3124 * @param {boolean} instructOverride true to override instruct mode, false to use the default value
3116 * @param {boolean} quietToLoud true to generate a message in system mode, false to generate a message in character mode3125 * @param {boolean} quietToLoud true to generate a message in system mode, false to generate a message in character mode
3117 * @param {string} [systemPrompt] System prompt to use. Only Instruct mode or OpenAI.3126 * @param {string} [systemPrompt] System prompt to use.
3118 * @param {number} [responseLength] Maximum response length. If unset, the global default value is used.3127 * @param {number} [responseLength] Maximum response length. If unset, the global default value is used.
3119 * @param {boolean} [trimNames] Whether to allow trimming "{{user}}:" and "{{char}}:" from the response.3128 * @param {boolean} [trimNames] Whether to allow trimming "{{user}}:" and "{{char}}:" from the response.
3129 * @param {string} [prefill] An optional prefill for the prompt.
3120 * @returns {Promise<string>} Generated message3130 * @returns {Promise<string>} Generated message
3121 */3131 */
3122export async function generateRaw(prompt, api, instructOverride, quietToLoud, systemPrompt, responseLength, trimNames = true) {3132export async function generateRaw(prompt, api, instructOverride, quietToLoud, systemPrompt, responseLength, trimNames = true, prefill = '') {
3123 if (!api) {3133 if (!api) {
3124 api = main_api;3134 api = main_api;
3125 }3135 }
@@ -3129,7 +3139,7 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy
3129 let eventHook = () => { };3139 let eventHook = () => { };
31303140
3131 // construct final prompt from the input. Can either be a string or an array of chat-style messages.3141 // construct final prompt from the input. Can either be a string or an array of chat-style messages.
3132 prompt = createRawPrompt(prompt, api, instructOverride, quietToLoud, systemPrompt);3142 prompt = createRawPrompt(prompt, api, instructOverride, quietToLoud, systemPrompt, prefill);
31333143
3134 try {3144 try {
3135 if (responseLengthCustomized) {3145 if (responseLengthCustomized) {
public/scripts/slash-commands.js+14 -5
@@ -1672,17 +1672,18 @@ export function initDefaultSlashCommands() {
1672 returns: 'generated text',1672 returns: 'generated text',
1673 namedArgumentList: [1673 namedArgumentList: [
1674 new SlashCommandNamedArgument(1674 new SlashCommandNamedArgument(
1675 'lock', 'lock user input during generation', [ARGUMENT_TYPE.BOOLEAN], false, false, null, commonEnumProviders.boolean('onOff')(),1675 'lock', 'lock user input during generation', [ARGUMENT_TYPE.BOOLEAN], false, false, 'off', commonEnumProviders.boolean('onOff')(),
1676 ),1676 ),
1677 new SlashCommandNamedArgument(1677 new SlashCommandNamedArgument(
1678 'instruct', 'use instruct mode', [ARGUMENT_TYPE.BOOLEAN], false, false, 'on', commonEnumProviders.boolean('onOff')(),1678 'instruct', 'use instruct mode', [ARGUMENT_TYPE.BOOLEAN], false, false, 'on', commonEnumProviders.boolean('onOff')(),
1679 ),1679 ),
1680 new SlashCommandNamedArgument(1680 new SlashCommandNamedArgument(
1681 'stop', 'one-time custom stop strings', [ARGUMENT_TYPE.LIST], false,1681 'stop', 'one-time custom stop strings', [ARGUMENT_TYPE.LIST], false, false, '[]',
1682 ),1682 ),
1683 SlashCommandNamedArgument.fromProps({1683 SlashCommandNamedArgument.fromProps({
1684 name: 'as',1684 name: 'as',
1685 description: 'role of the output prompt',1685 description: 'role of the output prompt',
1686 defaultValue: 'system',
1686 typeList: [ARGUMENT_TYPE.STRING],1687 typeList: [ARGUMENT_TYPE.STRING],
1687 enumList: [1688 enumList: [
1688 new SlashCommandEnumValue('system', null, enumTypes.enum, enumIcons.assistant),1689 new SlashCommandEnumValue('system', null, enumTypes.enum, enumIcons.assistant),
@@ -1690,10 +1691,16 @@ export function initDefaultSlashCommands() {
1690 ],1691 ],
1691 }),1692 }),
1692 new SlashCommandNamedArgument(1693 new SlashCommandNamedArgument(
1693 'system', 'system prompt at the start', [ARGUMENT_TYPE.STRING], false,1694 'system', 'system prompt at the start', [ARGUMENT_TYPE.STRING, ARGUMENT_TYPE.VARIABLE_NAME], false,
1694 ),1695 ),
1695 new SlashCommandNamedArgument(1696 new SlashCommandNamedArgument(
1696 'length', 'API response length in tokens', [ARGUMENT_TYPE.NUMBER], false,1697 'prefill', 'prefill prompt at the end', [ARGUMENT_TYPE.STRING, ARGUMENT_TYPE.VARIABLE_NAME], false,
1698 ),
1699 new SlashCommandNamedArgument(
1700 'length', 'API response length in tokens', [ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.VARIABLE_NAME], false,
1701 ),
1702 new SlashCommandNamedArgument(
1703 'trim', 'trim {{user}} and {{char}} prefixes from the output', [ARGUMENT_TYPE.BOOLEAN], false, false, 'on', commonEnumProviders.boolean('onOff')(),
1697 ),1704 ),
1698 ],1705 ],
1699 unnamedArgumentList: [1706 unnamedArgumentList: [
@@ -3628,7 +3635,9 @@ async function generateRawCallback(args, value) {
3628 const as = args?.as || 'system';3635 const as = args?.as || 'system';
3629 const quietToLoud = as === 'char';3636 const quietToLoud = as === 'char';
3630 const systemPrompt = resolveVariable(args?.system) || '';3637 const systemPrompt = resolveVariable(args?.system) || '';
3638 const prefillPrompt = resolveVariable(args?.prefill) || '';
3631 const length = Number(resolveVariable(args?.length) ?? 0) || 0;3639 const length = Number(resolveVariable(args?.length) ?? 0) || 0;
3640 const trimNames = !isFalseBoolean(args?.trim);
36323641
3633 try {3642 try {
3634 if (lock) {3643 if (lock) {
@@ -3636,7 +3645,7 @@ async function generateRawCallback(args, value) {
3636 }3645 }
36373646
3638 setEphemeralStopStrings(resolveVariable(args?.stop));3647 setEphemeralStopStrings(resolveVariable(args?.stop));
3639 const result = await generateRaw(value, '', isFalseBoolean(args?.instruct), quietToLoud, systemPrompt, length);3648 const result = await generateRaw(value, '', isFalseBoolean(args?.instruct), quietToLoud, systemPrompt, length, trimNames, prefillPrompt);
3640 return result;3649 return result;
3641 } catch (err) {3650 } catch (err) {
3642 console.error('Error on /genraw generation', err);3651 console.error('Error on /genraw generation', err);