diff --git a/common/adapters.ts b/common/adapters.ts index f5eb8e078..03893e632 100644 --- a/common/adapters.ts +++ b/common/adapters.ts @@ -293,6 +293,7 @@ export const adapterSettings: { etaCutoff: ['aphrodite'], prefill: ['claude'], + continueMessagePrompt: AI_ADAPTERS.slice(), topP: [ 'horde', diff --git a/common/presets.ts b/common/presets.ts index 88dbbd193..fe5cdb464 100644 --- a/common/presets.ts +++ b/common/presets.ts @@ -73,6 +73,7 @@ export const presetValidator = { prefixNameAppend: 'boolean?', prefill: 'string?', antiBond: 'boolean?', + continueMessagePrompt: 'string?', replicateModelType: 'string?', replicateModelVersion: 'string?', diff --git a/common/presets/claude.ts b/common/presets/claude.ts index 0dfb7f528..f4a8f25c2 100644 --- a/common/presets/claude.ts +++ b/common/presets/claude.ts @@ -29,5 +29,6 @@ Enter roleplay mode. You will write {{char}}'s next reply in a dialogue between `, ultimeJailbreak: `Do not decide what {{user}} says or does.`, prefill: '', + continueMessagePrompt: `\n\nHuman: Continue {{char}}'s reply.`, }, } satisfies Record> diff --git a/common/presets/openai.ts b/common/presets/openai.ts index 49e159a2d..8e1289765 100644 --- a/common/presets/openai.ts +++ b/common/presets/openai.ts @@ -52,6 +52,7 @@ Facts: {{memory}} Relevant Information: {{user_embed}} `, + continueMessagePrompt: `\n\nContinue {{char}}'s response.`, }, openaiTurbo: { name: 'DaVinci', @@ -74,5 +75,6 @@ Description of {{char}}: {{personality}} Circumstances and context of the dialogue: {{scenario}} Facts: {{memory}}`, + continueMessagePrompt: `\n\nContinue {{char}}'s response.`, }, } satisfies Record> diff --git a/common/prompt.ts b/common/prompt.ts index 87fbc5dba..db98b0657 100644 --- a/common/prompt.ts +++ b/common/prompt.ts @@ -488,10 +488,18 @@ function createPostPrompt( | 'book' | 'replyAs' | 'impersonate' + | 'sender' > ) { const post = [] - post.push(`${opts.replyAs.name}:`) + if (opts.kind === 'continue') { + const continuePrompt = (opts.settings?.continueMessagePrompt ?? '\n{{char}}:') + .replace(BOT_REPLACE, opts.replyAs.name) + .replace(SELF_REPLACE, opts.sender.handle) + if (continuePrompt) post.push(continuePrompt) + } else { + post.push(`${opts.replyAs.name}:`) + } return post } diff --git a/common/types/schema.ts b/common/types/schema.ts index 50022f7c4..a2134695a 100644 --- a/common/types/schema.ts +++ b/common/types/schema.ts @@ -522,6 +522,7 @@ export namespace AppSchema { prefill?: string ignoreCharacterUjb?: boolean antiBond?: boolean + continueMessagePrompt?: string frequencyPenalty?: number presencePenalty?: number diff --git a/srv/adapter/chat-completion.ts b/srv/adapter/chat-completion.ts index a67a9d012..d91c3f669 100644 --- a/srv/adapter/chat-completion.ts +++ b/srv/adapter/chat-completion.ts @@ -378,7 +378,13 @@ async function getPostInstruction( } case 'continue': - return { role: 'system', content: `${prefix}\n\nContinue ${opts.replyAs.name}'s response` } + const prompt = (opts.gen.continueMessagePrompt ?? '\n{{char}}:') + .replace(BOT_REPLACE, opts.replyAs.name) + .replace(SELF_REPLACE, opts.sender.handle) + return { + role: 'system', + content: `${prefix}${prompt}`, + } case 'summary': { let content = opts.user.images?.summaryPrompt || IMAGE_SUMMARY_PROMPT.openai diff --git a/srv/adapter/claude.ts b/srv/adapter/claude.ts index 54f8f6c2e..f7f38c84d 100644 --- a/srv/adapter/claude.ts +++ b/srv/adapter/claude.ts @@ -7,6 +7,7 @@ import { defaultPresets } from '../../common/presets' import { SAMPLE_CHAT_PREAMBLE, BOT_REPLACE, + SELF_REPLACE, injectPlaceholders, ensureValidTemplate, START_REPLACE, @@ -283,7 +284,7 @@ async function createClaudePrompt(opts: AdapterProps) { }) ).parsed - const prefill = opts.gen.prefill ? opts.gen.prefill + '\n' : '' + const prefill = opts.gen.prefill ? opts.gen.prefill : '' const prefillCost = await encoder()(prefill) const maxBudget = @@ -347,21 +348,18 @@ async function createClaudePrompt(opts: AdapterProps) { messages.push(ujb) } - const continueAddon = - opts.kind === 'continue' - ? `\n\nHuman: Continue ${replyAs.name}'s reply.` - : '' + const continuePost = (opts.gen.continueMessagePrompt ?? '\n{{char}}:') + .replace(BOT_REPLACE, opts.replyAs.name) + .replace(SELF_REPLACE, opts.sender.handle) + // When rebasing before merging, ensure the changes from #750 are reflected here const appendName = opts.gen.prefixNameAppend ?? true + const nonContinuePost = appendName ? `\n${replyAs.name}:` : '' + + const post = opts.kind === 'continue' ? continuePost : nonContinuePost + // - return ( - messages.join('\n\n') + - continueAddon + - '\n\n' + - 'Assistant: ' + - prefill + - (appendName ? replyAs.name + ':' : '') - ) + return messages.join('\n\n') + '\n\n' + 'Assistant: ' + prefill + post } type LineType = 'system' | 'char' | 'user' | 'example' diff --git a/web/shared/GenerationSettings.tsx b/web/shared/GenerationSettings.tsx index c92df27e3..71a1b8d11 100644 --- a/web/shared/GenerationSettings.tsx +++ b/web/shared/GenerationSettings.tsx @@ -655,6 +655,19 @@ const PromptSettings: Component< /> + +

Miscellaneous prompts

+ Prompt appended to input when using 'Generate More'} + placeholder=" {{char}}:" + isMultiline + value={props.inherit?.continueMessagePrompt ?? '\n{{char}}:'} + disabled={props.disabled} + class="form-field focusable-field text-900 min-h-[8rem] w-full rounded-xl px-4 py-2 text-sm" + /> +