From 58755abd8d4fb60da36eb64563131dcb43b0933b Mon Sep 17 00:00:00 2001 From: bangonicdd <157843588+bangonicdd2@users.noreply.github.com> Date: Thu, 26 Dec 2024 22:19:00 +0900 Subject: [PATCH 1/8] fix: add missing api definition --- src/ts/plugins/plugins.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ts/plugins/plugins.ts b/src/ts/plugins/plugins.ts index 84df7272..731e8c16 100644 --- a/src/ts/plugins/plugins.ts +++ b/src/ts/plugins/plugins.ts @@ -244,7 +244,8 @@ export async function loadV2Plugin(plugins:RisuPlugin[]){ const getChar = globalThis.__pluginApis__.getChar const setChar = globalThis.__pluginApis__.setChar const addProvider = globalThis.__pluginApis__.addProvider - const addRisuEventHandler = globalThis.__pluginApis__.addRisuEventHandler + const addRisuScriptHandler = globalThis.__pluginApis__.addRisuScriptHandler + const removeRisuScriptHandler = globalThis.__pluginApis__.removeRisuScriptHandler const addRisuReplacer = globalThis.__pluginApis__.addRisuReplacer const removeRisuReplacer = globalThis.__pluginApis__.removeRisuReplacer const onUnload = globalThis.__pluginApis__.onUnload From 823541af403e97c05121d59da46adba30d23342e Mon Sep 17 00:00:00 2001 From: poroyo <132068975+poroyo@users.noreply.github.com> Date: Fri, 27 Dec 2024 04:00:19 +0900 Subject: [PATCH 2/8] Fix sayTTS missing break in gptsovits case --- src/ts/process/tts.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ts/process/tts.ts b/src/ts/process/tts.ts index df5c4097..25aefa07 100644 --- a/src/ts/process/tts.ts +++ b/src/ts/process/tts.ts @@ -309,6 +309,7 @@ export async function sayTTS(character:character,text:string) { const text = Buffer.from(textBuffer).toString('utf-8') throw new Error(text); } + break; } case 'fishspeech':{ if (character.fishSpeechConfig.model._id === ''){ From 98ddb3fc0fb0177cc3dec629b8221f1df9964902 Mon Sep 17 00:00:00 2001 From: Do-hyun Ko Date: Fri, 27 Dec 2024 04:06:03 +0900 Subject: [PATCH 3/8] Fixed example code error in plugin docs --- plugins.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins.md b/plugins.md index f29edbc6..854e28b0 100644 --- a/plugins.md +++ b/plugins.md @@ -9,7 +9,7 @@ A plugin is a js file with a header. for example: ```js //@name exampleplugin -//display-name: Example Plugin +//@display-name Example Plugin // Plugin code here ``` @@ -163,4 +163,4 @@ The plugin system has been updated to V2. The following changes have been made: - `addCharaJs` function has been removed. use `addRisuScriptHandler` instead. - `risuLog` function has been removed. use `console.log` instead. - Many security restrictions have been removed. - - `@risu-name`, `@risu-display-name`, `@risu-arg` headers has been removed. use `@name`, `@display-name`, `@arg` instead. if it's not present, it will be ran as V1 plugin. \ No newline at end of file + - `@risu-name`, `@risu-display-name`, `@risu-arg` headers has been removed. use `@name`, `@display-name`, `@arg` instead. if it's not present, it will be ran as V1 plugin. From c841538c515c2cb4f1a99556c7c5cf20a234a4d9 Mon Sep 17 00:00:00 2001 From: Do-hyun Ko Date: Fri, 27 Dec 2024 05:09:32 +0900 Subject: [PATCH 4/8] Fix semantic meaning error --- plugins.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins.md b/plugins.md index 854e28b0..92832dab 100644 --- a/plugins.md +++ b/plugins.md @@ -118,7 +118,7 @@ Adds a risu script handler to the plugin. - `type: string` - The handler type. one of `display`, `output`, `input`, `process` - `display` - The handler will be called when the data is displayed. - `output` - The handler will be called when the data is outputted by the AI model. - - `input` - The handler will be called when the data is inputted to the user. + - `input` - The handler will be called when the data is inputted by the user. - `process` - The handler will be called when creating actual request data. - `func: (content:string) => string|null|undefined|Promise` - The handler function. - `content: string` - The content to handle. From e51ec6c73966e4558d6992d2f505cbbaf0013fa0 Mon Sep 17 00:00:00 2001 From: LightningHyperBlaze45654 <73149145+LightningHyperBlaze45654@users.noreply.github.com> Date: Thu, 26 Dec 2024 23:53:05 -0800 Subject: [PATCH 5/8] bugfix(read desc) need to check if the token count is still bugged. --- src/ts/process/memory/hypav2.ts | 58 +++++++++++++++------------------ 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/src/ts/process/memory/hypav2.ts b/src/ts/process/memory/hypav2.ts index 889fcc2e..d0f929b6 100644 --- a/src/ts/process/memory/hypav2.ts +++ b/src/ts/process/memory/hypav2.ts @@ -317,15 +317,22 @@ export async function hypaMemoryV2( const data: HypaV2Data = room.hypaV2Data ?? { lastMainChunkID: 0, chunks: [], - mainChunks: [] + mainChunks: [], }; + // JSON s + data.mainChunks.forEach(mainChunk => { + if (mainChunk.chatMemos && Array.isArray(mainChunk.chatMemos)) { + mainChunk.chatMemos = new Set(mainChunk.chatMemos); + } + }); // Clean invalid HypaV2 data cleanInvalidChunks(chats, data); let allocatedTokens = db.hypaAllocatedTokens; let chunkSize = db.hypaChunkSize; - currentTokens += allocatedTokens + chats.length * 4; // ChatML token counting from official openai documentation + // Since likely the first update break the token count, will continue with this for few updates. + currentTokens = await tokenizer.tokenizeChats(chats) + allocatedTokens; let mainPrompt = ""; const lastTwoChats = chats.slice(-2); // Error handling for infinite summarization attempts @@ -345,7 +352,7 @@ export async function hypaMemoryV2( // Starting chat index of new mainChunk to be generated // Token management loop (If current token usage exceeds allowed amount) - while (currentTokens >= maxContextTokens) { + while (currentTokens > maxContextTokens) { const halfData: OpenAIChat[] = []; let halfDataTokens = 0; @@ -362,7 +369,7 @@ export async function hypaMemoryV2( // Accumulate chats to summarize while ( halfDataTokens < chunkSize && - idx < chats.length - 2 // keep the last two chats from summarizing(else, the roles will be fucked up) + (idx < chats.length - 4) // keep the last two chats from summarizing(else, the roles will be fucked up) ) { const chat = chats[idx]; const chatTokens = await tokenizer.tokenizeChat(chat); @@ -402,7 +409,7 @@ export async function hypaMemoryV2( // If no chats were added, break to avoid infinite loop if (halfData.length === 0) { - console.log("No chats to summarize in this iteration, breaking out."); + console.log("HOW DID WE GET HERE???"); break; } @@ -441,22 +448,6 @@ export async function hypaMemoryV2( "\nSummary Token Count:", summaryDataToken ); - // **Token accounting fix:** - // Previous commits, the code likely have missed removing summarized chat's tokens. - // and never actually accounted for adding the summary tokens. - // Now we: - // 1. Remove old chats' tokens (they are replaced by summary) - // 2. Add summary tokens instead - currentTokens -= halfDataTokens; // remove original chats' tokens - currentTokens += summaryDataToken; // add the summary's tokens - - console.log( - "After token adjustment:", - "\nRemoved halfDataTokens:", halfDataTokens, - "\nAdded summaryDataToken:", summaryDataToken, - "\nCurrent Tokens (after):", currentTokens - ); - // Update lastMainChunkID and create a new mainChunk data.lastMainChunkID++; const newMainChunkId = data.lastMainChunkID; @@ -490,6 +481,10 @@ export async function hypaMemoryV2( "\nUpdated mainChunks count:", data.mainChunks.length, "\nUpdated chunks count:", data.chunks.length ); + + // Update the currentTokens immediately, removing summarized portion. + currentTokens -= halfDataTokens; + console.log("Current tokens after summarization deduction:", currentTokens); } // Construct the mainPrompt from mainChunks @@ -558,23 +553,24 @@ export async function hypaMemoryV2( const fullResult = `${mainPrompt}\n${chunkResultPrompts}`; - // Filter out summarized chats - const unsummarizedChats = chats.slice(idx); - - // Insert the memory system prompt at the beginning - unsummarizedChats.unshift({ - role: "system", - content: fullResult, - memo: "supaMemory", - }); + // Filter out summarized chats and prepend the memory prompt + const unsummarizedChats: OpenAIChat[] = [ + { + role: "system", + content: fullResult, + memo: "supaMemory", + }, + ...chats.slice(idx) // Use the idx to slice out the summarized chats + ]; + // Add the last two chats back if they are not already included for (const chat of lastTwoChats) { if (!unsummarizedChats.find((c) => c.memo === chat.memo)) { unsummarizedChats.push(chat); } } - // Recalculate currentTokens + // Recalculate currentTokens based on the final chat list currentTokens = await tokenizer.tokenizeChats(unsummarizedChats); console.log( From b83cb444b952b1d20e35c52ad9a88e867ee76abe Mon Sep 17 00:00:00 2001 From: poroyo <132068975+poroyo@users.noreply.github.com> Date: Sun, 29 Dec 2024 07:28:04 +0900 Subject: [PATCH 6/8] Add functionality to update char folder images --- src/lang/en.ts | 1 + src/lang/ko.ts | 1 + src/lib/SideBars/Sidebar.svelte | 42 +++++++++++++++++++++++---- src/lib/SideBars/SidebarAvatar.svelte | 11 ++++++- src/ts/storage/database.svelte.ts | 1 + 5 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/lang/en.ts b/src/lang/en.ts index c6793efa..a0db97c8 100644 --- a/src/lang/en.ts +++ b/src/lang/en.ts @@ -490,6 +490,7 @@ export const languageEnglish = { cancel: "Cancel", renameFolder: "Rename Folder", changeFolderColor: "Change Folder Color", + changeFolderImage: "Change Folder Image", fullWordMatching: "Full Word Matching", botSettingAtStart: "Bot Menu when Launch", triggerStart: "On chat Send", diff --git a/src/lang/ko.ts b/src/lang/ko.ts index 943ea439..9d3cfa0b 100644 --- a/src/lang/ko.ts +++ b/src/lang/ko.ts @@ -441,6 +441,7 @@ export const languageKorean = { "cancel": "취소", "renameFolder": "폴더 이름 변경하기", "changeFolderColor": "폴더 색상 변경하기", + "changeFolderImage": "폴더 이미지 변경하기", "fullWordMatching": "단어 단위 매칭", "botSettingAtStart": "실행 시 봇 설정으로 시작하기", "triggerStart": "채팅 보낼 시", diff --git a/src/lib/SideBars/Sidebar.svelte b/src/lib/SideBars/Sidebar.svelte index 9d7dcbe6..6ba2c0b2 100644 --- a/src/lib/SideBars/Sidebar.svelte +++ b/src/lib/SideBars/Sidebar.svelte @@ -39,12 +39,13 @@ import { get } from "svelte/store"; import { getCharacterIndexObject } from "src/ts/util"; import { v4 } from "uuid"; - import { checkCharOrder } from "src/ts/globalApi.svelte"; + import { checkCharOrder, getFileSrc } from "src/ts/globalApi.svelte"; import { alertInput, alertSelect } from "src/ts/alert"; import SideChatList from "./SideChatList.svelte"; import { ConnectionIsHost, ConnectionOpenStore, RoomIdStore } from "src/ts/sync/multiuser"; import { sideBarSize } from "src/ts/gui/guisize"; import DevTool from "./DevTool.svelte"; + import { getModuleAssets } from 'src/ts/process/modules'; let sideBarMode = $state(0); let editMode = $state(false); let menuMode = $state(0); @@ -59,7 +60,7 @@ } type sortTypeNormal = { type:'normal',img: string, index: number, name:string } - type sortType = sortTypeNormal|{type:'folder',folder:sortTypeNormal[],id:string, name:string, color:string} + type sortType = sortTypeNormal|{type:'folder',folder:sortTypeNormal[],id:string, name:string, color:string, img?:string} let charImages: sortType[] = $state([]); let IconRounded = $state(false) let openFolders:string[] = $state([]) @@ -109,7 +110,8 @@ type: "folder", id: folder.id, name: folder.name, - color: folder.color + color: folder.color, + img: folder.img, }); } } @@ -472,10 +474,10 @@ {:else if char.type === "folder"} {#key char.color} {#key char.name} - { e.preventDefault() - const sel = parseInt(await alertSelect([language.renameFolder,language.changeFolderColor,language.cancel])) + const sel = parseInt(await alertSelect([language.renameFolder,language.changeFolderColor,language.changeFolderImage,language.cancel])) if(sel === 0){ const v = await alertInput(language.changeFolderName) const db = DBState.db @@ -501,6 +503,36 @@ db.characterOrder[ind] = oder setDatabase(db) } + else if(sel === 2) { + let assetPaths:{[key:string]:{ + path:string + }} = {} + + assetPaths["Default"] = { + path: "", + } + + const moduleAssets = getModuleAssets() + if(moduleAssets.length > 0){ + for(const asset of moduleAssets){ + const assetPath = await getFileSrc(asset[1]) + assetPaths[asset[0].toLocaleLowerCase()] = { + path: assetPath, + } + } + } + + const assetNames = Object.keys(assetPaths) + const sel = parseInt(await alertSelect(assetNames)) + const db = DBState.db + const oder = db.characterOrder[ind] + if(typeof(oder) === 'string'){ + return + } + oder.img = assetPaths[assetNames[sel]].path + db.characterOrder[ind] = oder + setDatabase(db) + } }} onClick={() => { if(char.type !== 'folder'){ diff --git a/src/lib/SideBars/SidebarAvatar.svelte b/src/lib/SideBars/SidebarAvatar.svelte index 3be150d1..48602d8a 100644 --- a/src/lib/SideBars/SidebarAvatar.svelte +++ b/src/lib/SideBars/SidebarAvatar.svelte @@ -9,6 +9,7 @@ onClick?: any; bordered?: boolean; color?: string; + backgroundimg?: string; children?: import('svelte').Snippet; oncontextmenu?: (event: MouseEvent & { currentTarget: EventTarget & HTMLDivElement; @@ -23,6 +24,7 @@ onClick = () => {}, bordered = false, color = '', + backgroundimg = '', children, oncontextmenu }: Props = $props(); @@ -55,8 +57,15 @@ style:width={size + "px"} style:height={size + "px"} style:minWidth={size + "px"} + style:background-image={backgroundimg ? `url('${backgroundimg}')` : undefined} + style:background-size={backgroundimg ? "cover" : undefined} + style:background-position={backgroundimg ? "center" : undefined} class:rounded-md={!rounded} class:rounded-full={rounded} - >{@render children?.()} + > + {#if !backgroundimg} + {@render children?.()} + {/if} + {:else} {#await src}
Date: Mon, 30 Dec 2024 07:31:40 +0900 Subject: [PATCH 7/8] Refactor char folder image upload process to use direct upload method --- src/lib/SideBars/Sidebar.svelte | 55 ++++++++++++++++--------------- src/ts/globalApi.svelte.ts | 8 +++++ src/ts/storage/database.svelte.ts | 1 + 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/lib/SideBars/Sidebar.svelte b/src/lib/SideBars/Sidebar.svelte index 6ba2c0b2..20f4b9cf 100644 --- a/src/lib/SideBars/Sidebar.svelte +++ b/src/lib/SideBars/Sidebar.svelte @@ -37,15 +37,14 @@ import SidebarAvatar from "./SidebarAvatar.svelte"; import BaseRoundedButton from "../UI/BaseRoundedButton.svelte"; import { get } from "svelte/store"; - import { getCharacterIndexObject } from "src/ts/util"; + import { getCharacterIndexObject, selectSingleFile } from "src/ts/util"; import { v4 } from "uuid"; - import { checkCharOrder, getFileSrc } from "src/ts/globalApi.svelte"; + import { checkCharOrder, getFileSrc, saveAsset } from "src/ts/globalApi.svelte"; import { alertInput, alertSelect } from "src/ts/alert"; import SideChatList from "./SideChatList.svelte"; import { ConnectionIsHost, ConnectionOpenStore, RoomIdStore } from "src/ts/sync/multiuser"; import { sideBarSize } from "src/ts/gui/guisize"; import DevTool from "./DevTool.svelte"; - import { getModuleAssets } from 'src/ts/process/modules'; let sideBarMode = $state(0); let editMode = $state(false); let menuMode = $state(0); @@ -504,34 +503,38 @@ setDatabase(db) } else if(sel === 2) { - let assetPaths:{[key:string]:{ - path:string - }} = {} - - assetPaths["Default"] = { - path: "", - } - - const moduleAssets = getModuleAssets() - if(moduleAssets.length > 0){ - for(const asset of moduleAssets){ - const assetPath = await getFileSrc(asset[1]) - assetPaths[asset[0].toLocaleLowerCase()] = { - path: assetPath, - } - } - } - - const assetNames = Object.keys(assetPaths) - const sel = parseInt(await alertSelect(assetNames)) + const sel = parseInt(await alertSelect(['Reset to Default Image', 'Select Image File'])) const db = DBState.db const oder = db.characterOrder[ind] if(typeof(oder) === 'string'){ return } - oder.img = assetPaths[assetNames[sel]].path - db.characterOrder[ind] = oder - setDatabase(db) + + switch (sel) { + case 0: + oder.imgFile = null + oder.img = '' + break; + + case 1: + const folderImage = await selectSingleFile([ + 'png', + 'jpg', + 'webp', + ]) + + if(!folderImage) { + return + } + + const folderImageData = await saveAsset(folderImage.data) + + oder.imgFile = folderImageData + oder.img = await getFileSrc(folderImageData) + db.characterOrder[ind] = oder + setDatabase(db) + break; + } } }} onClick={() => { diff --git a/src/ts/globalApi.svelte.ts b/src/ts/globalApi.svelte.ts index 6ce26b3a..e79e84e4 100644 --- a/src/ts/globalApi.svelte.ts +++ b/src/ts/globalApi.svelte.ts @@ -1081,6 +1081,14 @@ export function getUnpargeables(db: Database, uptype: 'basename' | 'pure' = 'bas addUnparge(v.icon); }); } + + if(db.characterOrder){ + db.characterOrder.forEach((item) => { + if (typeof item === 'object' && 'imgFile' in item) { + addUnparge(item.imgFile); + } + }) + } return unpargeable; } diff --git a/src/ts/storage/database.svelte.ts b/src/ts/storage/database.svelte.ts index 0d7cf347..3310d448 100644 --- a/src/ts/storage/database.svelte.ts +++ b/src/ts/storage/database.svelte.ts @@ -1203,6 +1203,7 @@ export interface folder{ data:string[] color:string id:string + imgFile?:string img?:string } From d2042116aaa6d237dfc3e4c44d8669bb894fad40 Mon Sep 17 00:00:00 2001 From: LightningHyperBlaze45654 <73149145+LightningHyperBlaze45654@users.noreply.github.com> Date: Tue, 31 Dec 2024 21:52:13 -0800 Subject: [PATCH 8/8] Fix: Token counting fix --- src/ts/process/memory/hypav2.ts | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/ts/process/memory/hypav2.ts b/src/ts/process/memory/hypav2.ts index d0f929b6..d51074f8 100644 --- a/src/ts/process/memory/hypav2.ts +++ b/src/ts/process/memory/hypav2.ts @@ -331,16 +331,15 @@ export async function hypaMemoryV2( let allocatedTokens = db.hypaAllocatedTokens; let chunkSize = db.hypaChunkSize; - // Since likely the first update break the token count, will continue with this for few updates. - currentTokens = await tokenizer.tokenizeChats(chats) + allocatedTokens; + currentTokens += allocatedTokens; // WARNING: VIRTUAL VALUE. This token is NOT real. This is a placeholder appended to calculate the maximum amount of HypaV2 memory retrieved data. let mainPrompt = ""; const lastTwoChats = chats.slice(-2); - // Error handling for infinite summarization attempts + // Error handling for failed summarization let summarizationFailures = 0; const maxSummarizationFailures = 3; // Find the index to start summarizing from - let idx = 2; // first two should not be considered + let idx = 2; // first two should not be considered([Start a new chat], Memory prompt) if (data.mainChunks.length > 0) { const lastMainChunk = data.mainChunks[data.mainChunks.length - 1]; const lastChatMemo = lastMainChunk.lastChatMemo; @@ -359,7 +358,7 @@ export async function hypaMemoryV2( const startIdx = idx; console.log( - "Starting summarization iteration:", + "[HypaV2] Starting summarization iteration:", "\nCurrent Tokens (before):", currentTokens, "\nMax Context Tokens:", maxContextTokens, "\nStartIdx:", startIdx, @@ -375,7 +374,7 @@ export async function hypaMemoryV2( const chatTokens = await tokenizer.tokenizeChat(chat); console.log( - "Evaluating chat for summarization:", + "[HypaV2] Evaluating chat for summarization:", "\nIndex:", idx, "\nRole:", chat.role, "\nContent:", chat.content, @@ -399,7 +398,7 @@ export async function hypaMemoryV2( const endIdx = idx - 1; console.log( - "Summarization batch chosen with this:", + "[HypaV2] Summarization batch chosen with this:", "\nStartIdx:", startIdx, "\nEndIdx:", endIdx, "\nNumber of chats in halfData:", halfData.length, @@ -443,7 +442,7 @@ export async function hypaMemoryV2( }); console.log( - "Summarization success:", + "[HypaV2] Summarization success:", "\nSummary Data:", summaryData.data, "\nSummary Token Count:", summaryDataToken ); @@ -476,15 +475,14 @@ export async function hypaMemoryV2( ); console.log( - "Chunks added:", + "[HypaV2] Chunks added:", splitted, "\nUpdated mainChunks count:", data.mainChunks.length, "\nUpdated chunks count:", data.chunks.length ); - // Update the currentTokens immediately, removing summarized portion. currentTokens -= halfDataTokens; - console.log("Current tokens after summarization deduction:", currentTokens); + console.log("[HypaV2] tokens after summarization deduction:", currentTokens); } // Construct the mainPrompt from mainChunks @@ -552,6 +550,11 @@ export async function hypaMemoryV2( } const fullResult = `${mainPrompt}\n${chunkResultPrompts}`; + const fullResultTokens = await tokenizer.tokenizeChat({ + role: "system", + content: fullResult, + }); + currentTokens += fullResultTokens; // Filter out summarized chats and prepend the memory prompt const unsummarizedChats: OpenAIChat[] = [ @@ -563,18 +566,17 @@ export async function hypaMemoryV2( ...chats.slice(idx) // Use the idx to slice out the summarized chats ]; - // Add the last two chats back if they are not already included + // Remove this later, as this is already done by the index for (const chat of lastTwoChats) { if (!unsummarizedChats.find((c) => c.memo === chat.memo)) { unsummarizedChats.push(chat); } } - // Recalculate currentTokens based on the final chat list - currentTokens = await tokenizer.tokenizeChats(unsummarizedChats); + currentTokens -= allocatedTokens; // Virtually added memory tokens got removed. Bad way, but had no choice. console.log( - "Model being used: ", + "[HypaV2] Model being used: ", db.hypaModel, db.supaModelType, "\nCurrent session tokens: ",