diff --git a/src/lang/en.ts b/src/lang/en.ts index 46e20ea7..93ef9fa4 100644 --- a/src/lang/en.ts +++ b/src/lang/en.ts @@ -415,4 +415,6 @@ export const languageEnglish = { ToggleHypaMemory: "Toggle HypaMemory", resetPromptTemplateConfirm: "Do you really want to reset prompt template?", emotionMethod: "Emotion Method", + continueResponse: "Continue Response", + showMenuChatList: "Show Menu Chat List", } \ No newline at end of file diff --git a/src/lib/ChatScreens/DefaultChatScreen.svelte b/src/lib/ChatScreens/DefaultChatScreen.svelte index 2d0f482e..6a8893f9 100644 --- a/src/lib/ChatScreens/DefaultChatScreen.svelte +++ b/src/lib/ChatScreens/DefaultChatScreen.svelte @@ -1,6 +1,6 @@ +

{language.accessibility}

@@ -32,4 +33,8 @@
+
+ +
+
\ No newline at end of file diff --git a/src/ts/process/index.ts b/src/ts/process/index.ts index 430903de..e6fb7b74 100644 --- a/src/ts/process/index.ts +++ b/src/ts/process/index.ts @@ -36,7 +36,7 @@ export interface OpenAIChatFull extends OpenAIChat{ export const doingChat = writable(false) export const abortChat = writable(false) -export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:number,signal?:AbortSignal} = {}):Promise { +export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:number,signal?:AbortSignal,continue?:boolean} = {}):Promise { const abortSignal = arg.signal ?? (new AbortController()).signal @@ -515,6 +515,14 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n formatOrder.push('postEverything') } + //continue chat model + if(arg.continue && (db.aiModel.startsWith('claude') || db.aiModel.startsWith('gpt') || db.aiModel.startsWith('openrouter') || db.aiModel.startsWith('reverse_proxy'))){ + unformated.postEverything.push({ + role: 'system', + content: '[Continue the last response]' + }) + } + function pushPrompts(cha:OpenAIChat[]){ for(const chat of cha){ @@ -670,19 +678,26 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n } else if(req.type === 'streaming'){ const reader = req.result.getReader() - const msgIndex = db.characters[selectedChar].chats[selectedChat].message.length + let msgIndex = db.characters[selectedChar].chats[selectedChat].message.length + let prefix = '' + if(arg.continue){ + msgIndex -= 1 + prefix = db.characters[selectedChar].chats[selectedChat].message[msgIndex].data + } + else{ + db.characters[selectedChar].chats[selectedChat].message.push({ + role: 'char', + data: "", + saying: currentChar.chaId, + time: Date.now() + }) + } db.characters[selectedChar].chats[selectedChat].isStreaming = true - db.characters[selectedChar].chats[selectedChat].message.push({ - role: 'char', - data: "", - saying: currentChar.chaId, - time: Date.now() - }) while(abortSignal.aborted === false){ const readed = (await reader.read()) if(readed.value){ result = readed.value - const result2 = processScriptFull(nowChatroom, reformatContent(result), 'editoutput', msgIndex) + const result2 = processScriptFull(nowChatroom, reformatContent(prefix + result), 'editoutput', msgIndex) db.characters[selectedChar].chats[selectedChat].message[msgIndex].data = result2.data emoChanged = result2.emoChanged db.characters[selectedChar].reloadKeys += 1 @@ -709,17 +724,33 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n const msgs = (req.type === 'success') ? [['char',req.result]] as const : (req.type === 'multiline') ? req.result : [] - for(const msg of msgs){ - const msgIndex = db.characters[selectedChar].chats[selectedChat].message.length - const result2 = processScriptFull(nowChatroom, reformatContent(msg[1]), 'editoutput', msgIndex) + for(let i=0;i { diff --git a/src/ts/process/request.ts b/src/ts/process/request.ts index 6c056f0b..6b7f81f8 100644 --- a/src/ts/process/request.ts +++ b/src/ts/process/request.ts @@ -23,6 +23,7 @@ interface requestDataArgument{ useStreaming?:boolean isGroupChat?:boolean useEmotion?:boolean + continue?:boolean } type requestDataResponse = { @@ -90,6 +91,7 @@ export async function requestChatDataMain(arg:requestDataArgument, model:'model' let temperature = arg.temperature ?? (db.temperature / 100) let bias = arg.bias let currentChar = arg.currentChar + arg.continue = arg.continue ?? false let biasString = arg.biasString ?? [] const aiModel = (model === 'model' || (!db.advancedBotSettings)) ? db.aiModel : db.subModel @@ -356,7 +358,7 @@ export async function requestChatDataMain(arg:requestDataArgument, model:'model' } case 'novelai': case 'novelai_kayra':{ - const proompt = stringlizeNAIChat(formated, currentChar?.name ?? '') + const proompt = stringlizeNAIChat(formated, currentChar?.name ?? '', arg.continue) let logit_bias_exp:{ sequence: number[], bias: number, ensure_sequence_finish: false, generate_once: true }[] = [] @@ -439,7 +441,7 @@ export async function requestChatDataMain(arg:requestDataArgument, model:'model' let blockingUrl = db.textgenWebUIBlockingURL.replace(/\/api.*/, "/api/v1/generate") let bodyTemplate:any const suggesting = model === "submodel" - const proompt = stringlizeChatOba(formated, currentChar.name, suggesting) + const proompt = stringlizeChatOba(formated, currentChar.name, suggesting, arg.continue) const stopStrings = getStopStrings(suggesting) console.log(proompt) console.log(stopStrings) @@ -583,7 +585,7 @@ export async function requestChatDataMain(arg:requestDataArgument, model:'model' case 'palm2':{ const body = { "prompt": { - "text": stringlizeChat(formated, currentChar?.name ?? '') + "text": stringlizeChat(formated, currentChar?.name ?? '', arg.continue) }, "safetySettings":[ { @@ -654,7 +656,7 @@ export async function requestChatDataMain(arg:requestDataArgument, model:'model' } } case "kobold":{ - const proompt = stringlizeChat(formated, currentChar?.name ?? '') + const proompt = stringlizeChat(formated, currentChar?.name ?? '', arg.continue) const url = new URL(db.koboldURL) if(url.pathname.length < 3){ url.pathname = 'api/v1/generate' @@ -704,7 +706,7 @@ export async function requestChatDataMain(arg:requestDataArgument, model:'model' }; const send_body = { - text: stringlizeAINChat(formated, currentChar?.name ?? ''), + text: stringlizeAINChat(formated, currentChar?.name ?? '', arg.continue), length: maxTokens, temperature: temperature, top_p: db.ainconfig.top_p, @@ -764,7 +766,7 @@ export async function requestChatDataMain(arg:requestDataArgument, model:'model' const response = await createDeep([{ role: 'user', - content: stringlizeChat(formated, currentChar?.name ?? '') + content: stringlizeChat(formated, currentChar?.name ?? '', arg.continue) }]) if(!response.ok){ @@ -862,7 +864,7 @@ export async function requestChatDataMain(arg:requestDataArgument, model:'model' } if(aiModel.startsWith("horde:::")){ - const proompt = stringlizeChat(formated, currentChar?.name ?? '') + const proompt = stringlizeChat(formated, currentChar?.name ?? '', arg.continue) const realModel = aiModel.split(":::")[1] diff --git a/src/ts/process/stringlize.ts b/src/ts/process/stringlize.ts index b8de559c..7c4e8d3e 100644 --- a/src/ts/process/stringlize.ts +++ b/src/ts/process/stringlize.ts @@ -7,7 +7,7 @@ export function multiChatReplacer(){ } -export function stringlizeChat(formated:OpenAIChat[], char:string = ''){ +export function stringlizeChat(formated:OpenAIChat[], char:string, continued:boolean){ let resultString:string[] = [] for(const form of formated){ if(form.role === 'system'){ @@ -20,7 +20,12 @@ export function stringlizeChat(formated:OpenAIChat[], char:string = ''){ resultString.push(form.content) } } - return resultString.join('\n\n') + `\n\n${char}:` + let res = resultString.join('\n\n') + + if(!continued){ + res += `\n\n${char}:` + } + return res } function appendWhitespace(prefix:string, seperator:string=" ") { @@ -29,7 +34,7 @@ function appendWhitespace(prefix:string, seperator:string=" ") { } return prefix } -export function stringlizeChatOba(formated:OpenAIChat[], characterName:string='', suggesting:boolean=false){ +export function stringlizeChatOba(formated:OpenAIChat[], characterName:string, suggesting:boolean, continued:boolean){ const db = get(DataBase) let resultString:string[] = [] let { header, systemPrefix, userPrefix, assistantPrefix, seperator } = db.ooba.formating; @@ -59,10 +64,12 @@ export function stringlizeChatOba(formated:OpenAIChat[], characterName:string='' } resultString.push(prefix + name + form.content) } - if (suggesting){ - resultString.push(appendWhitespace(assistantPrefix, seperator) + `${db.username}:\n` + db.autoSuggestPrefix) - } else { - resultString.push(assistantPrefix + `${characterName}:`) + if(!continued){ + if (suggesting){ + resultString.push(appendWhitespace(assistantPrefix, seperator) + `${db.username}:\n` + db.autoSuggestPrefix) + } else { + resultString.push(assistantPrefix + `${characterName}:`) + } } return resultString.join(seperator) } @@ -190,7 +197,7 @@ export function getUnstringlizerChunks(formated:OpenAIChat[], char:string, mode: return {chunks,extChunk:charNames.concat(chunks)} } -export function stringlizeAINChat(formated:OpenAIChat[], char:string = ''){ +export function stringlizeAINChat(formated:OpenAIChat[], char:string, continued: boolean){ let resultString:string[] = [] const db = get(DataBase) @@ -213,7 +220,14 @@ export function stringlizeAINChat(formated:OpenAIChat[], char:string = ''){ resultString.push(form.content) } } - return resultString.join('\n\n') + `\n\n${char} 「` + let res = resultString.join('\n\n') + if(!continued){ + res += + `\n\n${char} 「` + } + else{ + res += " 「" + } + return res } function extractAINOutputStrings(inputString:string, characters:string[]) { diff --git a/src/ts/storage/database.ts b/src/ts/storage/database.ts index 50f6b3fa..c65e9bbd 100644 --- a/src/ts/storage/database.ts +++ b/src/ts/storage/database.ts @@ -310,6 +310,164 @@ export function setDatabase(data:Database){ } +export interface Database{ + characters: (character|groupChat)[], + apiType: string + forceReplaceUrl2:string + openAIKey: string + proxyKey:string + mainPrompt: string + jailbreak: string + globalNote:string + temperature: number + askRemoval:boolean + maxContext: number + maxResponse: number + frequencyPenalty: number + PresensePenalty: number + formatingOrder: FormatingOrderItem[] + aiModel: string + jailbreakToggle:boolean + loreBookDepth: number + loreBookToken: number, + loreBook: { + name:string + data:loreBook[] + }[] + loreBookPage: number + supaMemoryPrompt: string + username: string + userIcon: string + additionalPrompt: string + descriptionPrefix: string + forceReplaceUrl: string + language: string + translator: string + plugins: RisuPlugin[] + officialplugins: { + automark?: boolean + } + currentPluginProvider: string + zoomsize:number + lastup:string + customBackground:string + textgenWebUIStreamURL:string + textgenWebUIBlockingURL:string + autoTranslate: boolean + fullScreen:boolean + playMessage:boolean + iconsize:number + theme: string + subModel:string + timeOut:number + emotionPrompt: string, + requester:string + formatversion:number + waifuWidth:number + waifuWidth2:number + botPresets:botPreset[] + botPresetsId:number + sdProvider: string + webUiUrl:string + sdSteps:number + sdCFG:number + sdConfig:sdConfig + runpodKey:string + promptPreprocess:boolean + bias: [string, number][] + swipe:boolean + instantRemove:boolean + textTheme: string + customTextTheme: { + FontColorStandard: string, + FontColorBold : string, + FontColorItalic : string, + FontColorItalicBold : string, + } + requestRetrys:number + emotionPrompt2:string + useSayNothing:boolean + didFirstSetup: boolean + requestmet: string + requestproxy: string + showUnrecommended:boolean + elevenLabKey:string + voicevoxUrl:string + useExperimental:boolean + showMemoryLimit:boolean + roundIcons:boolean + useStreaming:boolean + palmAPI:string, + supaMemoryKey:string + supaMemoryType:string + textScreenColor?:string + textBorder?:boolean + textScreenRounded?:boolean + textScreenBorder?:string + characterOrder:(string|folder)[] + hordeConfig:hordeConfig, + toggleConfirmRecommendedPreset:boolean, + novelai:{ + token:string, + model:string + } + globalscript: customscript[], + sendWithEnter:boolean + clickToEdit: boolean + koboldURL:string + advancedBotSettings:boolean + useAutoSuggestions:boolean + autoSuggestPrompt:string + autoSuggestPrefix:string + autoSuggestClean:boolean + claudeAPIKey:string, + useChatCopy:boolean, + novellistAPI:string, + useAutoTranslateInput:boolean + imageCompression:boolean + account?:{ + token:string + id:string, + data: { + refresh_token?:string, + access_token?:string + expires_in?: number + } + useSync?:boolean + }, + classicMaxWidth: boolean, + useChatSticker:boolean, + useAdditionalAssetsPreview:boolean, + usePlainFetch:boolean + hypaMemory:boolean + proxyRequestModel:string + ooba:OobaSettings + ainconfig: AINsettings + personaPrompt:string + openrouterRequestModel:string + openrouterKey:string + selectedPersona:number + personas:{ + personaPrompt:string + name:string + icon:string + }[] + assetWidth:number + animationSpeed:number + botSettingAtStart:false + NAIsettings:NAISettings + hideRealm:boolean + colorScheme:ColorScheme + colorSchemeName:string + promptTemplate?:Proompt[] + forceProxyAsOpenAI?:boolean + hypaModel:'ada'|'MiniLM' + saveTime?:number + mancerHeader:string + emotionProcesser:'submodel'|'embedding', + showMenuChatList?:boolean +} + export interface customscript{ comment: string; in:string @@ -470,162 +628,6 @@ export interface botPreset{ promptTemplate?:Proompt[] } -export interface Database{ - characters: (character|groupChat)[], - apiType: string - forceReplaceUrl2:string - openAIKey: string - proxyKey:string - mainPrompt: string - jailbreak: string - globalNote:string - temperature: number - askRemoval:boolean - maxContext: number - maxResponse: number - frequencyPenalty: number - PresensePenalty: number - formatingOrder: FormatingOrderItem[] - aiModel: string - jailbreakToggle:boolean - loreBookDepth: number - loreBookToken: number, - loreBook: { - name:string - data:loreBook[] - }[] - loreBookPage: number - supaMemoryPrompt: string - username: string - userIcon: string - additionalPrompt: string - descriptionPrefix: string - forceReplaceUrl: string - language: string - translator: string - plugins: RisuPlugin[] - officialplugins: { - automark?: boolean - } - currentPluginProvider: string - zoomsize:number - lastup:string - customBackground:string - textgenWebUIStreamURL:string - textgenWebUIBlockingURL:string - autoTranslate: boolean - fullScreen:boolean - playMessage:boolean - iconsize:number - theme: string - subModel:string - timeOut:number - emotionPrompt: string, - requester:string - formatversion:number - waifuWidth:number - waifuWidth2:number - botPresets:botPreset[] - botPresetsId:number - sdProvider: string - webUiUrl:string - sdSteps:number - sdCFG:number - sdConfig:sdConfig - runpodKey:string - promptPreprocess:boolean - bias: [string, number][] - swipe:boolean - instantRemove:boolean - textTheme: string - customTextTheme: { - FontColorStandard: string, - FontColorBold : string, - FontColorItalic : string, - FontColorItalicBold : string, - } - requestRetrys:number - emotionPrompt2:string - useSayNothing:boolean - didFirstSetup: boolean - requestmet: string - requestproxy: string - showUnrecommended:boolean - elevenLabKey:string - voicevoxUrl:string - useExperimental:boolean - showMemoryLimit:boolean - roundIcons:boolean - useStreaming:boolean - palmAPI:string, - supaMemoryKey:string - supaMemoryType:string - textScreenColor?:string - textBorder?:boolean - textScreenRounded?:boolean - textScreenBorder?:string - characterOrder:(string|folder)[] - hordeConfig:hordeConfig, - toggleConfirmRecommendedPreset:boolean, - novelai:{ - token:string, - model:string - } - globalscript: customscript[], - sendWithEnter:boolean - clickToEdit: boolean - koboldURL:string - advancedBotSettings:boolean - useAutoSuggestions:boolean - autoSuggestPrompt:string - autoSuggestPrefix:string - autoSuggestClean:boolean - claudeAPIKey:string, - useChatCopy:boolean, - novellistAPI:string, - useAutoTranslateInput:boolean - imageCompression:boolean - account?:{ - token:string - id:string, - data: { - refresh_token?:string, - access_token?:string - expires_in?: number - } - useSync?:boolean - }, - classicMaxWidth: boolean, - useChatSticker:boolean, - useAdditionalAssetsPreview:boolean, - usePlainFetch:boolean - hypaMemory:boolean - proxyRequestModel:string - ooba:OobaSettings - ainconfig: AINsettings - personaPrompt:string - openrouterRequestModel:string - openrouterKey:string - selectedPersona:number - personas:{ - personaPrompt:string - name:string - icon:string - }[] - assetWidth:number - animationSpeed:number - botSettingAtStart:false - NAIsettings:NAISettings - hideRealm:boolean - colorScheme:ColorScheme - colorSchemeName:string - promptTemplate?:Proompt[] - forceProxyAsOpenAI?:boolean - hypaModel:'ada'|'MiniLM' - saveTime?:number - mancerHeader:string - emotionProcesser:'submodel'|'embedding' -} interface hordeConfig{ apiKey:string