feat: implement preset and parallel requests for HypaV3

This commit is contained in:
Bo26fhmC5M
2025-05-10 15:00:35 +09:00
parent d9565b4450
commit 85753a76ef
19 changed files with 2382 additions and 672 deletions

View File

@@ -3,15 +3,13 @@
import { language } from "src/lang";
import Help from "src/lib/Others/Help.svelte";
import { selectSingleFile } from "src/ts/util";
import { DBState } from 'src/ts/stores.svelte';
import { isTauri, saveAsset } from "src/ts/globalApi.svelte";
import { DBState, selectedCharID } from 'src/ts/stores.svelte';
import { isTauri, saveAsset, downloadFile } from "src/ts/globalApi.svelte";
import NumberInput from "src/lib/UI/GUI/NumberInput.svelte";
import TextInput from "src/lib/UI/GUI/TextInput.svelte";
import SelectInput from "src/lib/UI/GUI/SelectInput.svelte";
import OptionInput from "src/lib/UI/GUI/OptionInput.svelte";
import SliderInput from "src/lib/UI/GUI/SliderInput.svelte";
import Button from "src/lib/UI/GUI/Button.svelte";
import { getCharImage } from "src/ts/characters";
import Arcodion from "src/lib/UI/Arcodion.svelte";
import CheckInput from "src/lib/UI/GUI/CheckInput.svelte";
@@ -19,7 +17,9 @@
import { untrack } from "svelte";
import { tokenizePreset } from "src/ts/process/prompt";
import { getCharToken } from "src/ts/tokenizer";
import { selectedCharID } from "src/ts/stores.svelte";
import { PlusIcon, PencilIcon, TrashIcon, DownloadIcon, FolderUpIcon } from "lucide-svelte";
import { alertError, alertInput, alertConfirm, alertNormal } from "src/ts/alert";
import { createHypaV3Preset } from "src/ts/process/memory/hypav3";
$effect.pre(() => {
DBState.db.NAIImgConfig ??= {
@@ -67,25 +67,35 @@
// HypaV3
$effect(() => {
const newValue = Math.min(DBState.db.hypaV3Settings.recentMemoryRatio, 1);
const settings = DBState.db.hypaV3Presets?.[DBState.db.hypaV3PresetId]?.settings;
const currentValue = settings?.similarMemoryRatio;
if (!currentValue) return;
untrack(() => {
DBState.db.hypaV3Settings.recentMemoryRatio = newValue;
if (newValue + DBState.db.hypaV3Settings.similarMemoryRatio > 1) {
DBState.db.hypaV3Settings.similarMemoryRatio = 1 - newValue;
const newValue = Math.min(currentValue, 1);
settings.similarMemoryRatio = newValue;
if (newValue + settings.recentMemoryRatio > 1) {
settings.recentMemoryRatio = 1 - newValue;
}
})
});
$effect(() => {
const newValue = Math.min(DBState.db.hypaV3Settings.similarMemoryRatio, 1);
const settings = DBState.db.hypaV3Presets?.[DBState.db.hypaV3PresetId]?.settings;
const currentValue = settings?.recentMemoryRatio;
if (!currentValue) return;
untrack(() => {
DBState.db.hypaV3Settings.similarMemoryRatio = newValue;
const newValue = Math.min(currentValue, 1);
if (newValue + DBState.db.hypaV3Settings.recentMemoryRatio > 1) {
DBState.db.hypaV3Settings.recentMemoryRatio = 1 - newValue;
settings.recentMemoryRatio = newValue;
if (newValue + settings.similarMemoryRatio > 1) {
settings.similarMemoryRatio = 1 - newValue;
}
})
});
@@ -542,20 +552,11 @@
DBState.db.hanuraiEnable = false
DBState.db.hypaV3 = false
} else if (value === 'hypaV3') {
DBState.db.supaModelType = 'subModel'
DBState.db.memoryAlgorithmType = 'hypaMemoryV3'
DBState.db.hypav2 = false
DBState.db.supaModelType = 'none'
DBState.db.hanuraiEnable = false
DBState.db.hypav2 = false
DBState.db.hypaV3 = true
DBState.db.hypaV3Settings.memoryTokensRatio = 0.2
DBState.db.hypaV3Settings.extraSummarizationRatio = 0
DBState.db.hypaV3Settings.maxChatsPerSummary = 4
DBState.db.hypaV3Settings.recentMemoryRatio = 0.4
DBState.db.hypaV3Settings.similarMemoryRatio = 0.4
DBState.db.hypaV3Settings.enableSimilarityCorrection = false
DBState.db.hypaV3Settings.preserveOrphanedMemory = false
DBState.db.hypaV3Settings.processRegexScript = false
DBState.db.hypaV3Settings.doNotSummarizeUserMessage = false
} else {
DBState.db.supaModelType = 'none'
DBState.db.memoryAlgorithmType = 'none'
@@ -597,46 +598,191 @@
<span class="text-textcolor">{language.hypaAllocatedTokens}</span>
<NumberInput size="sm" marginBottom bind:value={DBState.db.hypaAllocatedTokens} min={100} />
{:else if DBState.db.hypaV3}
<span class="mb-2 text-textcolor2 text-sm text-wrap break-words max-w-full">{language.hypaV3Settings.descriptionLabel}</span>
<span class="text-textcolor mt-4">{language.SuperMemory} {language.model}</span>
<SelectInput className="mt-2 mb-2" bind:value={DBState.db.supaModelType}>
<OptionInput value="distilbart">distilbart-cnn-6-6 (Free/Local)</OptionInput>
<OptionInput value="subModel">{language.submodel}</OptionInput>
</SelectInput>
<span class="text-textcolor">{language.summarizationPrompt} <Help key="summarizationPrompt"/></span>
<div class="mb-2">
<TextAreaInput size="sm" placeholder={language.hypaV3Settings.supaMemoryPromptPlaceHolder} bind:value={DBState.db.supaMemoryPrompt} />
</div>
{#await getMaxMemoryRatio() then maxMemoryRatio}
<span class="text-textcolor">{language.hypaV3Settings.maxMemoryTokensRatioLabel}</span>
<NumberInput marginBottom disabled size="sm" value={maxMemoryRatio} />
{:catch error}
<span class="text-red-400">{language.hypaV3Settings.maxMemoryTokensRatioError}</span>
{/await}
<span class="text-textcolor">{language.hypaV3Settings.memoryTokensRatioLabel}</span>
<SliderInput marginBottom min={0} max={1} step={0.01} fixed={2} bind:value={DBState.db.hypaV3Settings.memoryTokensRatio} />
<span class="text-textcolor">{language.hypaV3Settings.extraSummarizationRatioLabel}</span>
<SliderInput marginBottom min={0} max={1 - DBState.db.hypaV3Settings.memoryTokensRatio} step={0.01} fixed={2} bind:value={DBState.db.hypaV3Settings.extraSummarizationRatio} />
<span class="text-textcolor">{language.hypaV3Settings.maxChatsPerSummaryLabel}</span>
<NumberInput marginBottom size="sm" min={1} bind:value={DBState.db.hypaV3Settings.maxChatsPerSummary} />
<span class="text-textcolor">{language.hypaV3Settings.recentMemoryRatioLabel}</span>
<SliderInput marginBottom min={0} max={1} step={0.01} fixed={2} bind:value={DBState.db.hypaV3Settings.recentMemoryRatio} />
<span class="text-textcolor">{language.hypaV3Settings.similarMemoryRatioLabel}</span>
<SliderInput marginBottom min={0} max={1} step={0.01} fixed={2} bind:value={DBState.db.hypaV3Settings.similarMemoryRatio} />
<span class="text-textcolor">{language.hypaV3Settings.randomMemoryRatioLabel}</span>
<NumberInput marginBottom disabled size="sm" value={parseFloat((1 - DBState.db.hypaV3Settings.recentMemoryRatio - DBState.db.hypaV3Settings.similarMemoryRatio).toFixed(2))} />
<div class="flex mb-2">
<Check name={language.hypaV3Settings.enableSimilarityCorrectionLabel} bind:check={DBState.db.hypaV3Settings.enableSimilarityCorrection} />
</div>
<div class="flex mb-2">
<Check name={language.hypaV3Settings.preserveOrphanedMemoryLabel} bind:check={DBState.db.hypaV3Settings.preserveOrphanedMemory} />
</div>
<div class="flex mb-2">
<Check name={language.hypaV3Settings.applyRegexScriptWhenRerollingLabel} bind:check={DBState.db.hypaV3Settings.processRegexScript} />
</div>
<div class="flex mb-2">
<Check name={language.hypaV3Settings.doNotSummarizeUserMessageLabel} bind:check={DBState.db.hypaV3Settings.doNotSummarizeUserMessage} />
<span class="max-w-full mb-6 text-sm text-wrap break-words text-textcolor2">{language.hypaV3Settings.descriptionLabel}</span>
<span class="text-textcolor">Preset</span>
<select class={"border border-darkborderc focus:border-borderc rounded-md shadow-sm text-textcolor bg-transparent focus:ring-borderc focus:ring-2 focus:outline-none transition-colors duration-200 text-md px-4 py-2 mb-1"}
bind:value={DBState.db.hypaV3PresetId}
>
{#each DBState.db.hypaV3Presets as preset, i}
<option class="bg-darkbg appearance-none" value={i}>{preset.name}</option>
{/each}
</select>
<div class="flex items-center mb-8">
<button class="mr-2 text-textcolor2 hover:text-green-500 cursor-pointer" onclick={() => {
const newPreset = createHypaV3Preset()
const presets = DBState.db.hypaV3Presets
presets.push(newPreset)
DBState.db.hypaV3Presets = presets
DBState.db.hypaV3PresetId = DBState.db.hypaV3Presets.length - 1
}}>
<PlusIcon size={24}/>
</button>
<button class="mr-2 text-textcolor2 hover:text-green-500 cursor-pointer" onclick={async () => {
const presets = DBState.db.hypaV3Presets
if(presets.length === 0){
alertError("There must be least one preset.")
return
}
const id = DBState.db.hypaV3PresetId
const preset = presets[id]
const newName = await alertInput(`Enter new name for ${preset.name}`)
if (!newName || newName.trim().length === 0) return
preset.name = newName
DBState.db.hypaV3Presets = presets
}}>
<PencilIcon size={24}/>
</button>
<button class="mr-2 text-textcolor2 hover:text-green-500 cursor-pointer" onclick={async (e) => {
const presets = DBState.db.hypaV3Presets
if(presets.length <= 1){
alertError("There must be least one preset.")
return
}
const id = DBState.db.hypaV3PresetId
const preset = presets[id]
const confirmed = await alertConfirm(`${language.removeConfirm}${preset.name}`)
if (!confirmed) return
DBState.db.hypaV3PresetId = 0
presets.splice(id, 1)
DBState.db.hypaV3Presets = presets
}}>
<TrashIcon size={24}/>
</button>
<div class="ml-2 mr-4 w-px h-full bg-darkborderc"></div>
<button class="mr-2 text-textcolor2 hover:text-green-500 cursor-pointer" onclick={async() => {
try {
const presets = DBState.db.hypaV3Presets
if(presets.length === 0){
alertError("There must be least one preset.")
return
}
const id = DBState.db.hypaV3PresetId
const preset = presets[id]
const bytesExport = Buffer.from(JSON.stringify({
type: 'risu',
ver: 1,
data: preset
}), 'utf-8')
await downloadFile(`hypaV3_export_${preset.name}.json`, bytesExport)
alertNormal(language.successExport)
} catch (error) {
alertError(`${error}`)
}
}}>
<DownloadIcon size={24}/>
</button>
<button class="mr-2 text-textcolor2 hover:text-green-500 cursor-pointer" onclick={async() => {
try {
const bytesImport = (await selectSingleFile(['json'])).data
if(!bytesImport) return
const objImport = JSON.parse(Buffer.from(bytesImport).toString('utf-8'))
if(objImport.type !== 'risu' || !objImport.data) return
const newPreset = createHypaV3Preset(
objImport.data.name || "Imported Preset",
objImport.data.settings || {}
);
const presets = DBState.db.hypaV3Presets
presets.push(newPreset)
DBState.db.hypaV3Presets = presets
DBState.db.hypaV3PresetId = DBState.db.hypaV3Presets.length - 1
alertNormal(language.successImport)
} catch (error) {
alertError(`${error}`)
}
}}>
<FolderUpIcon size={24}/>
</button>
</div>
{#if DBState.db.hypaV3Presets?.[DBState.db.hypaV3PresetId]?.settings}
{@const settings = DBState.db.hypaV3Presets[DBState.db.hypaV3PresetId].settings}
<span class="text-textcolor">{language.SuperMemory} {language.model}</span>
<SelectInput className="mb-4" bind:value={settings.summarizationModel}>
<OptionInput value="subModel">{language.submodel}</OptionInput>
{#if "gpu" in navigator}
<OptionInput value="Qwen3-1.7B-q4f32_1-MLC">Qwen3 1.7B (GPU)</OptionInput>
<OptionInput value="Qwen3-4B-q4f32_1-MLC">Qwen3 4B (GPU)</OptionInput>
<OptionInput value="Qwen3-8B-q4f32_1-MLC">Qwen3 8B (GPU)</OptionInput>
{/if}
</SelectInput>
<span class="text-textcolor">{language.summarizationPrompt} <Help key="summarizationPrompt"/></span>
<div class="mb-4">
<TextAreaInput size="sm" placeholder={language.hypaV3Settings.supaMemoryPromptPlaceHolder} bind:value={settings.summarizationPrompt} />
</div>
{#await getMaxMemoryRatio() then maxMemoryRatio}
<span class="text-textcolor">{language.hypaV3Settings.maxMemoryTokensRatioLabel}</span>
<NumberInput marginBottom disabled size="sm" value={maxMemoryRatio} />
{:catch error}
<span class="mb-4 text-red-400">{language.hypaV3Settings.maxMemoryTokensRatioError}</span>
{/await}
<span class="text-textcolor">{language.hypaV3Settings.memoryTokensRatioLabel}</span>
<SliderInput marginBottom min={0} max={1} step={0.01} fixed={2} bind:value={settings.memoryTokensRatio} />
<span class="text-textcolor">{language.hypaV3Settings.extraSummarizationRatioLabel}</span>
<SliderInput marginBottom min={0} max={1 - settings.memoryTokensRatio} step={0.01} fixed={2} bind:value={settings.extraSummarizationRatio} />
<span class="text-textcolor">{language.hypaV3Settings.maxChatsPerSummaryLabel}</span>
<NumberInput marginBottom size="sm" min={1} bind:value={settings.maxChatsPerSummary} />
<span class="text-textcolor">{language.hypaV3Settings.recentMemoryRatioLabel}</span>
<SliderInput marginBottom min={0} max={1} step={0.01} fixed={2} bind:value={settings.recentMemoryRatio} />
<span class="text-textcolor">{language.hypaV3Settings.similarMemoryRatioLabel}</span>
<SliderInput marginBottom min={0} max={1} step={0.01} fixed={2} bind:value={settings.similarMemoryRatio} />
<span class="text-textcolor">{language.hypaV3Settings.randomMemoryRatioLabel}</span>
<NumberInput marginBottom disabled size="sm" value={parseFloat((1 - settings.recentMemoryRatio - settings.similarMemoryRatio).toFixed(2))} />
<div class="mb-2">
<Check name={language.hypaV3Settings.preserveOrphanedMemoryLabel} bind:check={settings.preserveOrphanedMemory} />
</div>
<div class="mb-2">
<Check name={language.hypaV3Settings.applyRegexScriptWhenRerollingLabel} bind:check={settings.processRegexScript} />
</div>
<div class="mb-2">
<Check name={language.hypaV3Settings.doNotSummarizeUserMessageLabel} bind:check={settings.doNotSummarizeUserMessage} />
</div>
<Arcodion name="Advanced Settings" styled>
<div class="mb-2">
<Check name="Use Experimental Implementation" bind:check={settings.useExperimentalImpl} />
</div>
{#if settings.useExperimentalImpl}
<span class="text-textcolor">Summarization Requests Per Minute</span>
<NumberInput marginBottom size="sm" min={1} bind:value={settings.summarizationRequestsPerMinute} />
<span class="text-textcolor">Summarization Max Concurrent</span>
<NumberInput marginBottom size="sm" min={1} max={10} bind:value={settings.summarizationMaxConcurrent} />
<span class="text-textcolor">Embedding Requests Per Minute</span>
<NumberInput marginBottom size="sm" min={1} bind:value={settings.embeddingRequestsPerMinute} />
<span class="text-textcolor">Embedding Max Concurrent</span>
<NumberInput marginBottom size="sm" min={1} max={10} bind:value={settings.embeddingMaxConcurrent} />
{:else}
<div class="mb-2">
<Check name={language.hypaV3Settings.enableSimilarityCorrectionLabel} bind:check={settings.enableSimilarityCorrection} />
</div>
{/if}
</Arcodion>
{/if}
<div class="mb-8"></div>
{:else if (DBState.db.supaModelType !== 'none' && DBState.db.hypav2 === false && DBState.db.hypaV3 === false)}
<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>
@@ -663,14 +809,17 @@
<span class="text-textcolor">{language.embedding}</span>
<SelectInput className="mt-2 mb-2" bind:value={DBState.db.hypaModel}>
{#if 'gpu' in navigator}
<OptionInput value="MiniLMGPU">MiniLM L6 v2 (GPU)</OptionInput>
<OptionInput value="nomicGPU">Nomic Embed Text v1.5 (GPU)</OptionInput>
<OptionInput value="bgeSmallEnGPU">BGE Small English (GPU)</OptionInput>
<OptionInput value="bgem3GPU">BGE Medium 3 (GPU)</OptionInput>
<OptionInput value="multiMiniLMGPU">Multilingual MiniLM L12 v2 (GPU)</OptionInput>
{/if}
<OptionInput value="MiniLM">MiniLM L6 v2 (CPU)</OptionInput>
<OptionInput value="nomic">Nomic Embed Text v1.5 (CPU)</OptionInput>
<OptionInput value="bgeSmallEn">BGE Small English (CPU)</OptionInput>
<OptionInput value="bgem3">BGE Medium 3 (CPU)</OptionInput>
<OptionInput value="multiMiniLM">Multilingual MiniLM L12 v2 (CPU)</OptionInput>
<OptionInput value="openai3small">OpenAI text-embedding-3-small</OptionInput>
<OptionInput value="openai3large">OpenAI text-embedding-3-large</OptionInput>
<OptionInput value="ada">OpenAI Ada</OptionInput>