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>
Signed| @@ -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 value | 3059 | * @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 mode | 3060 | * @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 | */ |
| 3064 | export function createRawPrompt(prompt, api, instructOverride, quietToLoud, systemPrompt) { | 3065 | export 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; |
| 3066 | 3067 | ||
| 3067 | // If the prompt was given as a string, convert to a message-style object assuming user role | 3068 | // 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 | } |
| 3076 | 3077 | ||
| 3078 | // Substitute the prefill if provided | ||
| 3079 | prefill = substituteParams(prefill ?? ''); | ||
| 3080 | |||
| 3077 | // Format each message in the prompt, accounting for the provided roles | 3081 | // 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 | } |
| 3098 | 3102 | ||
| 3099 | // If text completion, convert to text prompt by concatenating all message contents | 3103 | // 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 line | 3113 | prompt = prompt + (isInstruct ? formatInstructModePrompt(name2, false, prefill, name1, name2, true, quietToLoud) : `\n${prefill}`); // add last line |
| 3105 | } | 3114 | } |
| 3106 | 3115 | ||
| 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 value | 3124 | * @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 mode | 3125 | * @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 message | 3130 | * @returns {Promise<string>} Generated message |
| 3121 | */ | 3131 | */ |
| 3122 | export async function generateRaw(prompt, api, instructOverride, quietToLoud, systemPrompt, responseLength, trimNames = true) { | 3132 | export 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 = () => { }; |
| 3130 | 3140 | ||
| 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); |
| 3133 | 3143 | ||
| 3134 | try { | 3144 | try { |
| 3135 | if (responseLengthCustomized) { | 3145 | if (responseLengthCustomized) { |
| @@ -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); | ||
| 3632 | 3641 | ||
| 3633 | try { | 3642 | try { |
| 3634 | if (lock) { | 3643 | if (lock) { |
| @@ -3636,7 +3645,7 @@ async function generateRawCallback(args, value) { | |||
| 3636 | } | 3645 | } |
| 3637 | 3646 | ||
| 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); |