From dc1799f7fc77f606c87b78756eb7a5025011c499 Mon Sep 17 00:00:00 2001 From: kwaroran Date: Thu, 3 Aug 2023 12:34:07 +0900 Subject: [PATCH] [feat] prompt template --- src/lang/en.ts | 7 +- src/lib/Setting/Pages/BotSettings.svelte | 12 +- src/lib/Setting/Pages/PromptSettings.svelte | 45 +++++ src/lib/Setting/Settings.svelte | 17 +- src/lib/UI/ProomptItem.svelte | 65 +++++++ src/ts/process/index.ts | 199 ++++++++++++++++---- src/ts/process/proompt.ts | 19 ++ src/ts/storage/database.ts | 2 + 8 files changed, 328 insertions(+), 38 deletions(-) create mode 100644 src/lib/Setting/Pages/PromptSettings.svelte create mode 100644 src/lib/UI/ProomptItem.svelte create mode 100644 src/ts/process/proompt.ts diff --git a/src/lang/en.ts b/src/lang/en.ts index d5326aab..bec8852b 100644 --- a/src/lang/en.ts +++ b/src/lang/en.ts @@ -10,7 +10,8 @@ export const languageEnglish = { 'authorNote': "Author's Note", 'lastChat': "Last Chat", "description": "Character Description", - 'personaPrompt':'Persona Prompt' + 'personaPrompt':'Persona Prompt', + 'plain': "Plain Prompt", }, errors:{ toomuchtoken: 'Error: The minimum required token is greater than the Max Context Size.', @@ -400,4 +401,8 @@ export const languageEnglish = { hideRealm: "Hide RisuRealm", popularityLevel: "{} Popularity", colorScheme: "Color Scheme", + rangeStart: "Range Start", + rangeEnd: "Range End", + untilChatEnd: "Until Chat End", + usePromptTemplate: "Use Prompt Template", } \ No newline at end of file diff --git a/src/lib/Setting/Pages/BotSettings.svelte b/src/lib/Setting/Pages/BotSettings.svelte index f437b066..b0134ef6 100644 --- a/src/lib/Setting/Pages/BotSettings.svelte +++ b/src/lib/Setting/Pages/BotSettings.svelte @@ -417,7 +417,17 @@
- +
+ {#if $DataBase.promptTemplate} + { + $DataBase.promptTemplate = undefined + }}/> + {:else} + { + $DataBase.promptTemplate = [] + }}/> + {/if} +
{/if} diff --git a/src/lib/Setting/Pages/PromptSettings.svelte b/src/lib/Setting/Pages/PromptSettings.svelte new file mode 100644 index 00000000..01259045 --- /dev/null +++ b/src/lib/Setting/Pages/PromptSettings.svelte @@ -0,0 +1,45 @@ + + +

{language.prompt}

+
+ {#if $DataBase.promptTemplate.length === 0} +
No Format
+ {/if} + {#key sorted} + {#each $DataBase.promptTemplate as proompt, i} + { + let templates = $DataBase.promptTemplate + templates.splice(i, 1) + $DataBase.promptTemplate = templates + }} /> + {/each} + {/key} +
+ + \ No newline at end of file diff --git a/src/lib/Setting/Settings.svelte b/src/lib/Setting/Settings.svelte index 0e63555e..13e666d9 100644 --- a/src/lib/Setting/Settings.svelte +++ b/src/lib/Setting/Settings.svelte @@ -17,6 +17,8 @@ import LanguageSettings from "./Pages/LanguageSettings.svelte"; import AccessibilitySettings from "./Pages/AccessibilitySettings.svelte"; import PersonaSettings from "./Pages/PersonaSettings.svelte"; + import PromptSettings from "./Pages/PromptSettings.svelte"; + import { DataBase } from "src/ts/storage/database"; let selected = -1 let openPresetList = false let openLoreList = false @@ -30,12 +32,23 @@ {#if window.innerWidth >= 700 || selected === -1}
- + {#if $DataBase.promptTemplate} + + {/if}
+ { + if(proompt.type === 'plain' || proompt.type === 'jailbreak'){ + proompt.text = "" + proompt.role = "bot" + } + if(proompt.type === 'chat'){ + proompt.rangeStart = 0 + proompt.rangeEnd = 'end' + } + }} > + {language.formating.plain} + {language.formating.jailbreak} + {language.Chat} + {language.formating.personaPrompt} + {language.formating.description} + {language.formating.authorNote} + {language.formating.lorebook} + + + {#if proompt.type === 'plain' || proompt.type === 'jailbreak'} + {language.prompt} + + {language.role} + + {language.user} + {language.character} + {language.systemPrompt} + + {/if} + {#if proompt.type === 'chat'} + {language.rangeStart} + + {language.rangeEnd} + {#if proompt.rangeEnd === 'end'} + { + if(proompt.type === 'chat'){ + proompt.rangeEnd = 0 + } + }} /> + {:else} + + { + if(proompt.type === 'chat'){ + proompt.rangeEnd = 'end' + } + }} /> + {/if} + {/if} + \ No newline at end of file diff --git a/src/ts/process/index.ts b/src/ts/process/index.ts index 332c8629..0c7311c9 100644 --- a/src/ts/process/index.ts +++ b/src/ts/process/index.ts @@ -1,7 +1,7 @@ import { get, writable } from "svelte/store"; import { DataBase, setDatabase, type character } from "../storage/database"; import { CharEmotion, selectedCharID } from "../stores"; -import { ChatTokenizer, tokenizeNum } from "../tokenizer"; +import { ChatTokenizer, tokenize, tokenizeNum } from "../tokenizer"; import { language } from "../../lang"; import { alertError } from "../alert"; import { loadLoreBookPrompt } from "./lorebook"; @@ -169,7 +169,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n 'personaPrompt':([] as OpenAIChat[]) } - if(!currentChar.utilityBot){ + if((!currentChar.utilityBot) && (!db.promptTemplate)){ const mainp = currentChar.systemPrompt?.replaceAll('{{original}}', db.mainPrompt) || db.mainPrompt @@ -255,10 +255,84 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n //await tokenize currernt let currentTokens = db.maxResponse - for(const key in unformated){ - const chats = unformated[key] as OpenAIChat[] - for(const chat of chats){ - currentTokens += await tokenizer.tokenizeChat(chat) + + if(db.promptTemplate){ + const template = db.promptTemplate + + async function tokenizeChatArray(chats:OpenAIChat[]){ + for(const chat of chats){ + const tokens = await tokenizer.tokenizeChat(chat) + currentTokens += tokens + } + } + + + for(const card of template){ + switch(card.type){ + case 'persona':{ + await tokenizeChatArray(unformated.personaPrompt) + break + } + case 'description':{ + await tokenizeChatArray(unformated.description) + break + } + case 'authornote':{ + await tokenizeChatArray(unformated.authorNote) + break + } + case 'lorebook':{ + await tokenizeChatArray(unformated.lorebook) + break + } + case 'plain': + case 'jailbreak':{ + if((!db.jailbreakToggle) && (card.type === 'jailbreak')){ + continue + } + + const convertRole = { + "system": "system", + "user": "user", + "bot": "assistant" + } as const + + let content = card.text + + if(card.type2 === 'globalNote'){ + content = (risuChatParser(currentChar.replaceGlobalNote?.replaceAll('{{original}}', content) || content, {chara:currentChar})) + } + else if(card.type2 === 'main'){ + content = (risuChatParser(content, {chara: currentChar})) + } + else{ + content = risuChatParser(content, {chara: currentChar}) + } + + const prompt:OpenAIChat ={ + role: convertRole[card.role], + content: content + } + + await tokenizeChatArray([prompt]) + break + } + case 'chat':{ + const start = card.rangeStart + const end = (card.rangeEnd === 'end') ? unformated.chats.length : card.rangeEnd + const chats = unformated.chats.slice(start, end) + await tokenizeChatArray(chats) + break + } + } + } + } + else{ + for(const key in unformated){ + const chats = unformated[key] as OpenAIChat[] + for(const chat of chats){ + currentTokens += await tokenizer.tokenizeChat(chat) + } } } @@ -407,42 +481,97 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n let formated:OpenAIChat[] = [] const formatOrder = cloneDeep(db.formatingOrder) formatOrder.push('postEverything') - let sysPrompts:string[] = [] - for(let i=0;i 0){ - const prompt = sysPrompts.join('\n') - if(prompt.replace(/\n/g,'').length > 3){ - formated.push({ - role: 'system', - content: prompt - }) + + function pushPrompts(cha:OpenAIChat[]){ + for(const chat of cha){ + if(!chat.content){ + continue + } + if(chat.role === 'system'){ + const endf = formated.at(-1) + if(endf && endf.role === 'system' && endf.memo === chat.memo && endf.name === chat.name){ + formated[formated.length - 1].content += '\n\n' + chat.content + } + else{ + formated.push(chat) + } + formated.at(-1).content += '' + } + else{ + formated.push(chat) } - sysPrompts = [] - formated = formated.concat(cha) - } - else{ - formated = formated.concat(cha) } } - if(sysPrompts.length > 0){ - const prompt = sysPrompts.join('\n') + if(db.promptTemplate){ + const template = db.promptTemplate - if(prompt.replace(/\n/g,'').length > 3){ - formated.push({ - role: 'system', - content: prompt - }) + for(const card of template){ + switch(card.type){ + case 'persona':{ + pushPrompts(unformated.personaPrompt) + break + } + case 'description':{ + pushPrompts(unformated.description) + break + } + case 'authornote':{ + pushPrompts(unformated.authorNote) + break + } + case 'lorebook':{ + pushPrompts(unformated.lorebook) + break + } + case 'plain': + case 'jailbreak':{ + if((!db.jailbreakToggle) && (card.type === 'jailbreak')){ + continue + } + + const convertRole = { + "system": "system", + "user": "user", + "bot": "assistant" + } as const + + let content = card.text + + if(card.type2 === 'globalNote'){ + content = (risuChatParser(currentChar.replaceGlobalNote?.replaceAll('{{original}}', content) || content, {chara:currentChar})) + } + else if(card.type2 === 'main'){ + content = (risuChatParser(content, {chara: currentChar})) + } + else{ + content = risuChatParser(content, {chara: currentChar}) + } + + const prompt:OpenAIChat ={ + role: convertRole[card.role], + content: content + } + + pushPrompts([prompt]) + break + } + case 'chat':{ + const start = card.rangeStart + const end = (card.rangeEnd === 'end') ? unformated.chats.length : card.rangeEnd + const chats = unformated.chats.slice(start, end) + pushPrompts(chats) + break + } + } + } + } + else{ + for(let i=0;i