hypav2 enhancment 2

This commit is contained in:
LightningHyperBlaze45654
2024-06-12 07:11:07 -07:00
parent aff445f38f
commit 5030dd56da
3 changed files with 208 additions and 146 deletions

View File

@@ -276,7 +276,7 @@
<span class="text-textcolor mt-4">{language.type}</span> <span class="text-textcolor mt-4">{language.type}</span>
<SelectInput value={ <SelectInput value={
$DataBase.supaMemoryType === 'hypaV2' ? 'hypaV2' : $DataBase.hypav2 ? 'hypaV2' :
$DataBase.supaMemoryType !== 'none' ? 'supaMemory' : $DataBase.supaMemoryType !== 'none' ? 'supaMemory' :
$DataBase.hanuraiEnable ? 'hanuraiMemory' : 'none' $DataBase.hanuraiEnable ? 'hanuraiMemory' : 'none'
} on:change={(v) => { } on:change={(v) => {
@@ -284,15 +284,19 @@
const value = v.target.value const value = v.target.value
if (value === 'supaMemory'){ if (value === 'supaMemory'){
$DataBase.supaMemoryType = 'distilbart' $DataBase.supaMemoryType = 'distilbart'
$DataBase.hypav2 = false
$DataBase.hanuraiEnable = false $DataBase.hanuraiEnable = false
} else if (value === 'hanuraiMemory'){ } else if (value === 'hanuraiMemory'){
$DataBase.supaMemoryType = 'none' $DataBase.supaMemoryType = 'none'
$DataBase.hypav2 = false
$DataBase.hanuraiEnable = true $DataBase.hanuraiEnable = true
} else if (value === 'hypaV2') { } else if (value === 'hypaV2') {
$DataBase.supaMemoryType = 'hypaV2' $DataBase.supaMemoryType = 'hypaV2'
$DataBase.hypav2= true
$DataBase.hanuraiEnable = false $DataBase.hanuraiEnable = false
} else { } else {
$DataBase.supaMemoryType = 'none' $DataBase.supaMemoryType = 'none'
$DataBase.hypav2 = false
$DataBase.hanuraiEnable = false $DataBase.hanuraiEnable = false
} }
}}> }}>
@@ -309,26 +313,27 @@
<div class="flex"> <div class="flex">
<Check bind:check={$DataBase.hanuraiSplit} name="Text Spliting"/> <Check bind:check={$DataBase.hanuraiSplit} name="Text Spliting"/>
</div> </div>
{:else if $DataBase.supaMemoryType === 'hypaV2'} {:else if $DataBase.hypav2}
<span class="mb-2 text-textcolor2 text-sm text-wrap break-words max-w-full">{language.hypaV2Desc}</span> <span class="mb-2 text-textcolor2 text-sm text-wrap break-words max-w-full">{language.hypaV2Desc}</span>
<span class="text-textcolor mt-4">{language.SuperMemory} {language.model}</span> <span class="text-textcolor mt-4">{language.SuperMemory} {language.model}</span>
<SelectInput className="mt-2 mb-2" bind:value={$DataBase.supaMemoryType}> <SelectInput className="mt-2 mb-2" bind:value={$DataBase.supaMemoryType}>
<OptionInput value="distilbart" >distilbart-cnn-6-6 (Free/Local)</OptionInput> <OptionInput value="distilbart">distilbart-cnn-6-6 (Free/Local)</OptionInput>
<OptionInput value="instruct35" >OpenAI 3.5 Turbo Instruct</OptionInput> <OptionInput value="instruct35">OpenAI 3.5 Turbo Instruct</OptionInput>
<OptionInput value="subModel" >{language.submodel}</OptionInput> <OptionInput value="subModel">{language.submodel}</OptionInput>
</SelectInput> </SelectInput>
<span class="text-textcolor">{language.SuperMemory} Prompt</span> <span class="text-textcolor">{language.SuperMemory} Prompt</span>
<TextInput size="sm" marginBottom bind:value={$DataBase.supaMemoryPrompt} placeholder="Leave it blank to use default"/> <TextInput size="sm" marginBottom bind:value={$DataBase.supaMemoryPrompt} placeholder="Leave it blank to use default"/>
<span class="text-textcolor">{language.HypaMemory} Model</span> <span class="text-textcolor">{language.HypaMemory} Model</span>
<SelectInput className="mt-2 mb-2" bind:value={$DataBase.hypaModel}> <SelectInput className="mt-2 mb-2" bind:value={$DataBase.hypaModel}>
<OptionInput value="MiniLM" >MiniLM-L6-v2 (Free / Local)</OptionInput> <OptionInput value="MiniLM">MiniLM-L6-v2 (Free / Local)</OptionInput>
<OptionInput value="ada" >OpenAI Ada (Davinci / Curie Only)</OptionInput> <OptionInput value="nomic">Nomic (Free / Local)</OptionInput>
<OptionInput value="ada">OpenAI Ada (Davinci / Curie Only)</OptionInput>
</SelectInput> </SelectInput>
<span class="text-textcolor">{language.hypaChunkSize}</span> <span class="text-textcolor">{language.hypaChunkSize}</span>
<NumberInput size="sm" marginBottom bind:value={$DataBase.hypaChunkSize} min={100} /> <NumberInput size="sm" marginBottom bind:value={$DataBase.hypaChunkSize} min={100} />
<span class="text-textcolor">{language.hypaAllocatedTokens}</span> <span class="text-textcolor">{language.hypaAllocatedTokens}</span>
<NumberInput size="sm" marginBottom bind:value={$DataBase.hypaAllocatedTokens} min={100} /> <NumberInput size="sm" marginBottom bind:value={$DataBase.hypaAllocatedTokens} min={100} />
{:else if $DataBase.supaMemoryType !== 'none'} {:else if ($DataBase.supaMemoryType !== 'none' && $DataBase.hypav2 === false)}
<span class="mb-2 text-textcolor2 text-sm text-wrap break-words max-w-full">{language.supaDesc}</span> <span class="mb-2 text-textcolor2 text-sm text-wrap break-words max-w-full">{language.supaDesc}</span>
<span class="text-textcolor mt-4">{language.SuperMemory} {language.model}</span> <span class="text-textcolor mt-4">{language.SuperMemory} {language.model}</span>
<SelectInput className="mt-2 mb-2" bind:value={$DataBase.supaMemoryType}> <SelectInput className="mt-2 mb-2" bind:value={$DataBase.supaMemoryType}>

View File

@@ -4,210 +4,266 @@ import type { ChatTokenizer } from "src/ts/tokenizer";
import { get } from "svelte/store"; import { get } from "svelte/store";
import { requestChatData } from "../request"; import { requestChatData } from "../request";
import { HypaProcesser } from "./hypamemory"; import { HypaProcesser } from "./hypamemory";
import { globalFetch } from "src/ts/storage/globalApi";
import { runSummarizer } from "../transformers";
export interface HypaV2Data{ export interface HypaV2Data {
chunks: { chunks: {
text:string text: string;
targetId:string targetId: string;
}[] }[];
mainChunks: { mainChunks: {
text:string text: string;
targetId:string targetId: string;
}[] }[];
} }
async function summarize(stringlizedChat: string): Promise<{ success: boolean; data: string }> {
const db = get(DataBase);
if (db.supaMemoryType === 'distilbart') {
try {
const sum = await runSummarizer(stringlizedChat);
return { success: true, data: sum };
} catch (error) {
return {
success: false,
data: "SupaMemory: Summarizer: " + `${error}`
};
}
}
const supaPrompt = db.supaMemoryPrompt === '' ?
"[Summarize the ongoing role story, It must also remove redundancy and unnecessary text and content from the output to reduce tokens for gpt3 and other sublanguage models]\n"
: db.supaMemoryPrompt;
let result = '';
if (db.supaMemoryType !== 'subModel') {
const promptbody = stringlizedChat + '\n\n' + supaPrompt + "\n\nOutput:";
const da = await globalFetch("https://api.openai.com/v1/completions", {
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + db.supaMemoryKey
},
method: "POST",
body: {
"model": db.supaMemoryType === 'curie' ? "text-curie-001"
: db.supaMemoryType === 'instruct35' ? 'gpt-3.5-turbo-instruct'
: "text-davinci-003",
"prompt": promptbody,
"max_tokens": 600,
"temperature": 0
}
});
try {
if (!da.ok) {
return {
success: false,
data: "SupaMemory: HTTP: " + JSON.stringify(da.data)
};
}
result = (await da.data)?.choices[0]?.text?.trim();
if (!result) {
return {
success: false,
data: "SupaMemory: HTTP: " + JSON.stringify(da.data)
};
}
return { success: true, data: result };
} catch (error) {
return {
success: false,
data: "SupaMemory: HTTP: " + error
};
}
} else {
const promptbody: OpenAIChat[] = [
{
role: "user",
content: stringlizedChat
},
{
role: "system",
content: supaPrompt
}
];
const da = await requestChatData({
formated: promptbody,
bias: {},
useStreaming: false,
noMultiGen: true
}, 'submodel');
if (da.type === 'fail' || da.type === 'streaming' || da.type === 'multiline') {
return {
success: false,
data: "SupaMemory: HTTP: " + da.result
};
}
result = da.result;
}
return { success: true, data: result };
}
export async function hypaMemoryV2( export async function hypaMemoryV2(
chats:OpenAIChat[], chats: OpenAIChat[],
currentTokens:number, currentTokens: number,
maxContextTokens:number, maxContextTokens: number,
room:Chat, room: Chat,
char:character|groupChat, char: character | groupChat,
tokenizer:ChatTokenizer, tokenizer: ChatTokenizer,
arg:{asHyper?:boolean} = {} arg: { asHyper?: boolean, summaryModel?: string, summaryPrompt?: string, hypaModel?: string } = {}
): Promise<{ currentTokens: number; chats: OpenAIChat[]; error?:string; memory?:HypaV2Data;}>{ ): Promise<{ currentTokens: number; chats: OpenAIChat[]; error?: string; memory?: HypaV2Data; }> {
const db = get(DataBase) const db = get(DataBase);
const data:HypaV2Data = room.hypaV2Data ?? { const data: HypaV2Data = room.hypaV2Data ?? {
chunks:[], chunks: [],
mainChunks:[] mainChunks: []
} };
//this is for the prompt
let allocatedTokens = db.hypaAllocatedTokens let allocatedTokens = db.hypaAllocatedTokens;
let chunkSize = db.hypaChunkSize let chunkSize = db.hypaChunkSize;
currentTokens += allocatedTokens currentTokens += allocatedTokens;
currentTokens += 50 //this is for the template prompt currentTokens += 50; // this is for the template prompt
let mainPrompt = "" let mainPrompt = "";
while(data.mainChunks.length > 0){ while (data.mainChunks.length > 0) {
const chunk = data.mainChunks[0] const chunk = data.mainChunks[0];
const ind = chats.findIndex(e => e.memo === chunk.targetId) const ind = chats.findIndex(e => e.memo === chunk.targetId);
if(ind === -1){ if (ind === -1) {
data.mainChunks.shift() data.mainChunks.shift();
continue continue;
} }
const removedChats = chats.splice(0, ind) const removedChats = chats.splice(0, ind);
for(const chat of removedChats){ for (const chat of removedChats) {
currentTokens -= await tokenizer.tokenizeChat(chat) currentTokens -= await tokenizer.tokenizeChat(chat);
} }
chats = chats.slice(ind) chats = chats.slice(ind);
mainPrompt = chunk.text mainPrompt = chunk.text;
const mpToken = await tokenizer.tokenizeChat({role:'system', content:mainPrompt}) const mpToken = await tokenizer.tokenizeChat({ role: 'system', content: mainPrompt });
allocatedTokens -= mpToken allocatedTokens -= mpToken;
break break;
} }
while(currentTokens >= maxContextTokens){ while (currentTokens >= maxContextTokens) {
let idx = 0;
let idx = 0 let targetId = '';
let targetId = '' const halfData: OpenAIChat[] = [];
const halfData:OpenAIChat[] = []
let halfDataTokens = 0 let halfDataTokens = 0;
while(halfDataTokens < chunkSize){ while (halfDataTokens < chunkSize) {
const chat = chats[idx] const chat = chats[idx];
if(!chat){ if (!chat) {
break break;
} }
halfDataTokens += await tokenizer.tokenizeChat(chat) halfDataTokens += await tokenizer.tokenizeChat(chat);
halfData.push(chat) halfData.push(chat);
idx++ idx++;
targetId = chat.memo targetId = chat.memo;
} }
async function summary(stringlizedChat:string):Promise<{ const stringlizedChat = halfData.map(e => `${e.role}: ${e.content}`).join('\n');
success:boolean
data:string
}>{
const promptbody:OpenAIChat[] = [
{
role: "user",
content: stringlizedChat
},
{
role: "system",
content: "Summarize this roleplay scene in a coherent narrative format for future reference. Summarize what happened, focusing on events and interactions between them. If someone or something is new or changed, include a brief characterization of them."
}
]
const da = await requestChatData({
formated: promptbody,
bias: {},
useStreaming: false,
noMultiGen: true
}, 'model')
if(da.type === 'fail' || da.type === 'streaming' || da.type === 'multiline'){
return {
data: "Hypamemory HTTP: " + da.result,
success: false
}
}
return {
data: da.result,
success: true
}
}
const stringlizedChat = halfData.map(e => `${e.role}: ${e.content}`).join('\n') const summaryData = await summarize(stringlizedChat);
const summaryData = await summary(stringlizedChat) if (!summaryData.success) {
if(!summaryData.success){
return { return {
currentTokens: currentTokens, currentTokens: currentTokens,
chats: chats, chats: chats,
error: summaryData.data error: summaryData.data
} };
} }
const summaryDataToken = await tokenizer.tokenizeChat({role:'system', content:summaryData.data}) const summaryDataToken = await tokenizer.tokenizeChat({ role: 'system', content: summaryData.data });
mainPrompt += `\n\n${summaryData.data}` mainPrompt += `\n\n${summaryData.data}`;
currentTokens -= halfDataTokens currentTokens -= halfDataTokens;
allocatedTokens -= summaryDataToken allocatedTokens -= summaryDataToken;
data.mainChunks.unshift({ data.mainChunks.unshift({
text: mainPrompt, text: mainPrompt,
targetId: targetId targetId: targetId
}) });
if(allocatedTokens < 1500){ if (allocatedTokens < 1500) {
const summarizedMp = await summary(mainPrompt) const summarizedMp = await summarize(mainPrompt);
const mpToken = await tokenizer.tokenizeChat({role:'system', content:mainPrompt}) const mpToken = await tokenizer.tokenizeChat({ role: 'system', content: mainPrompt });
const summaryToken = await tokenizer.tokenizeChat({role:'system', content:summarizedMp.data}) const summaryToken = await tokenizer.tokenizeChat({ role: 'system', content: summarizedMp.data });
allocatedTokens -= summaryToken allocatedTokens -= summaryToken;
allocatedTokens += mpToken allocatedTokens += mpToken;
const splited = mainPrompt.split('\n\n').map(e => e.trim()).filter(e => e.length > 0) const splited = mainPrompt.split('\n\n').map(e => e.trim()).filter(e => e.length > 0);
data.chunks.push(...splited.map(e => ({ data.chunks.push(...splited.map(e => ({
text: e, text: e,
targetId: targetId targetId: targetId
}))) })));
data.mainChunks[0].text = mainPrompt data.mainChunks[0].text = mainPrompt;
} }
} }
const processer = new HypaProcesser("nomic") const processer = new HypaProcesser(db.hypaModel);
await processer.addText(data.chunks.filter(v => { await processer.addText(data.chunks.filter(v => {
return v.text.trim().length > 0 return v.text.trim().length > 0;
}).map((v) => { }).map((v) => {
return "search_document: " + v.text.trim() return "search_document: " + v.text.trim();
})) }));
let scoredResults:{[key:string]:number} = {} let scoredResults: { [key: string]: number } = {};
for(let i=0;i<3;i++){ for (let i = 0; i < 3; i++) {
const pop = chats[chats.length - i - 1] const pop = chats[chats.length - i - 1];
if(!pop){ if (!pop) {
break break;
} }
const searched = await processer.similaritySearchScored(`search_query: ${pop.content}`) const searched = await processer.similaritySearchScored(`search_query: ${pop.content}`);
for(const result of searched){ for (const result of searched) {
const score = result[1]/(i+1) const score = result[1] / (i + 1);
if(scoredResults[result[0]]){ if (scoredResults[result[0]]) {
scoredResults[result[0]] += score scoredResults[result[0]] += score;
}else{ } else {
scoredResults[result[0]] = score scoredResults[result[0]] = score;
} }
} }
} }
const scoredArray = Object.entries(scoredResults).sort((a,b) => b[1] - a[1]) const scoredArray = Object.entries(scoredResults).sort((a, b) => b[1] - a[1]);
let chunkResultPrompts = "" let chunkResultPrompts = "";
while(allocatedTokens > 0){ while (allocatedTokens > 0) {
const target = scoredArray.shift() const target = scoredArray.shift();
if(!target){ if (!target) {
break break;
} }
const tokenized = await tokenizer.tokenizeChat({ const tokenized = await tokenizer.tokenizeChat({
role: 'system', role: 'system',
content: target[0].substring(14) content: target[0].substring(14)
}) });
if(tokenized > allocatedTokens){ if (tokenized > allocatedTokens) {
break break;
} }
chunkResultPrompts += target[0].substring(14) + '\n\n' chunkResultPrompts += target[0].substring(14) + '\n\n';
allocatedTokens -= tokenized allocatedTokens -= tokenized;
} }
const fullResult = `<Past Events Summary>${mainPrompt}</Past Events Summary>\n<Past Events Details>${chunkResultPrompts}</Past Events Details>`;
const fullResult = `<Past Events Summary>${mainPrompt}</Past Events Summary>\n<Past Events Details>${chunkResultPrompts}</Past Events Details>`
chats.unshift({ chats.unshift({
role: "system", role: "system",
content: fullResult, content: fullResult,
memo: "supaMemory" memo: "supaMemory"
}) });
return { return {
currentTokens: currentTokens, currentTokens: currentTokens,
chats: chats, chats: chats,
memory: data memory: data
} };
} }

View File

@@ -568,6 +568,7 @@ export interface Database{
useAdditionalAssetsPreview:boolean, useAdditionalAssetsPreview:boolean,
usePlainFetch:boolean usePlainFetch:boolean
hypaMemory:boolean hypaMemory:boolean
hypav2:boolean
proxyRequestModel:string proxyRequestModel:string
ooba:OobaSettings ooba:OobaSettings
ainconfig: AINsettings ainconfig: AINsettings