feat: add important button in HypaV3 Data modal

This commit is contained in:
Bo26fhmC5M
2025-01-13 23:30:18 +09:00
parent a7c3141cc0
commit f3c6278d21
2 changed files with 97 additions and 44 deletions

View File

@@ -5,7 +5,7 @@
import { getCharImage } from '../../ts/characters'; import { getCharImage } from '../../ts/characters';
import { ParseMarkdown } from '../../ts/parser.svelte'; import { ParseMarkdown } from '../../ts/parser.svelte';
import BarIcon from '../SideBars/BarIcon.svelte'; import BarIcon from '../SideBars/BarIcon.svelte';
import { ChevronRightIcon, User, RefreshCw } from 'lucide-svelte'; import { ChevronRightIcon, User, RefreshCw, StarIcon } from 'lucide-svelte';
import { hubURL, isCharacterHasAssets } from 'src/ts/characterCards'; import { hubURL, isCharacterHasAssets } from 'src/ts/characterCards';
import TextInput from '../UI/GUI/TextInput.svelte'; import TextInput from '../UI/GUI/TextInput.svelte';
import { openURL } from 'src/ts/globalApi.svelte'; import { openURL } from 'src/ts/globalApi.svelte';
@@ -364,46 +364,57 @@
<div class="mb-4"> <div class="mb-4">
<div class="flex justify-between items-center mb-2"> <div class="flex justify-between items-center mb-2">
<span class="text-sm text-textcolor2">Summary #{i + 1}</span> <span class="text-sm text-textcolor2">Summary #{i + 1}</span>
<!-- Resummarize Button --> <div class="flex items-center gap-4">
<button <!-- Important Button -->
class="p-1 hover:text-blue-500 transition-colors disabled:opacity-50 disabled:cursor-not-allowed" <button
onclick={async () => { class="p-1 hover:text-yellow-500 transition-colors {summary.isImportant ? "text-yellow-500" : "text-textcolor2"}"
hypaV3IsResummarizing = true onclick={() => {
summary.isImportant = !summary.isImportant
}}
>
<StarIcon size={16}/>
</button>
<!-- Resummarize Button -->
<button
class="p-1 hover:text-blue-500 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
onclick={async () => {
hypaV3IsResummarizing = true
try { try {
const char = DBState.db.characters[$selectedCharID] const char = DBState.db.characters[$selectedCharID]
const chat = char.chats[DBState.db.characters[$selectedCharID].chatPage] const chat = char.chats[DBState.db.characters[$selectedCharID].chatPage]
const firstMessage = chat.fmIndex === -1 ? char.firstMessage : char.alternateGreetings?.[chat.fmIndex ?? 0] const firstMessage = chat.fmIndex === -1 ? char.firstMessage : char.alternateGreetings?.[chat.fmIndex ?? 0]
const toSummarize = summary.chatMemos.map(chatMemo => { const toSummarize = summary.chatMemos.map(chatMemo => {
if (chatMemo == null) { if (chatMemo == null) {
return { return {
role: "assistant", role: "assistant",
data: firstMessage data: firstMessage
}
} }
const msg = chat.message.find(m => m.chatId === chatMemo)
return msg ? {
role: msg.role === "char" ? "assistant" : msg.role,
data: msg.data
} : null
})
const stringifiedChats = toSummarize
.map((m) => `${m.role}: ${m.data}`)
.join("\n")
const summarizeResult = await hypaV3Summarize(stringifiedChats)
if (summarizeResult.success) {
summary.text = summarizeResult.data
} }
} finally {
const msg = chat.message.find(m => m.chatId === chatMemo) hypaV3IsResummarizing = false
return msg ? {
role: msg.role === "char" ? "assistant" : msg.role,
data: msg.data
} : null
})
const stringifiedChats = toSummarize
.map((m) => `${m.role}: ${m.data}`)
.join("\n")
const summarizeResult = await hypaV3Summarize(stringifiedChats)
if (summarizeResult.success) {
summary.text = summarizeResult.data
} }
} finally { }}
hypaV3IsResummarizing = false disabled={hypaV3IsResummarizing}
} >
}} <RefreshCw size={16}/>
disabled={hypaV3IsResummarizing} </button>
> </div>
<RefreshCw size={16}/>
</button>
</div> </div>
<!-- Editable Summary --> <!-- Editable Summary -->
<TextAreaInput <TextAreaInput

View File

@@ -19,6 +19,7 @@ import type { ChatTokenizer } from "src/ts/tokenizer";
interface Summary { interface Summary {
text: string; text: string;
chatMemos: Set<string>; chatMemos: Set<string>;
isImportant: boolean;
} }
interface HypaV3Data { interface HypaV3Data {
@@ -29,6 +30,7 @@ export interface SerializableHypaV3Data {
summaries: { summaries: {
text: string; text: string;
chatMemos: string[]; chatMemos: string[];
isImportant: boolean;
}[]; }[];
} }
@@ -50,7 +52,7 @@ function isSubset(subset: Set<string>, superset: Set<string>): boolean {
function toSerializableHypaV3Data(data: HypaV3Data): SerializableHypaV3Data { function toSerializableHypaV3Data(data: HypaV3Data): SerializableHypaV3Data {
return { return {
summaries: data.summaries.map((summary) => ({ summaries: data.summaries.map((summary) => ({
text: summary.text, ...summary,
chatMemos: [...summary.chatMemos], chatMemos: [...summary.chatMemos],
})), })),
}; };
@@ -59,9 +61,11 @@ function toSerializableHypaV3Data(data: HypaV3Data): SerializableHypaV3Data {
function toHypaV3Data(serialData: SerializableHypaV3Data): HypaV3Data { function toHypaV3Data(serialData: SerializableHypaV3Data): HypaV3Data {
return { return {
summaries: serialData.summaries.map((summary) => ({ summaries: serialData.summaries.map((summary) => ({
text: summary.text, ...summary,
// Convert null back to undefined (JSON serialization converts undefined to null) // Convert null back to undefined (JSON serialization converts undefined to null)
chatMemos: new Set(summary.chatMemos.map(memo => memo === null ? undefined : memo)), chatMemos: new Set(
summary.chatMemos.map((memo) => (memo === null ? undefined : memo))
),
})), })),
}; };
} }
@@ -288,7 +292,7 @@ export async function hypaMemoryV3(
const shouldReserveEmptyMemoryTokens = const shouldReserveEmptyMemoryTokens =
data.summaries.length === 0 && data.summaries.length === 0 &&
currentTokens + emptyMemoryTokens <= maxContextTokens; currentTokens + emptyMemoryTokens <= maxContextTokens;
const availableMemoryTokens = shouldReserveEmptyMemoryTokens let availableMemoryTokens = shouldReserveEmptyMemoryTokens
? 0 ? 0
: memoryTokens - emptyMemoryTokens; : memoryTokens - emptyMemoryTokens;
@@ -424,6 +428,7 @@ export async function hypaMemoryV3(
data.summaries.push({ data.summaries.push({
text: summarizeResult.data, text: summarizeResult.data,
chatMemos: new Set(toSummarize.map((chat) => chat.memo)), chatMemos: new Set(toSummarize.map((chat) => chat.memo)),
isImportant: false,
}); });
break; break;
@@ -451,6 +456,38 @@ export async function hypaMemoryV3(
db.hypaV3Settings.recentMemoryRatio - db.hypaV3Settings.recentMemoryRatio -
db.hypaV3Settings.similarMemoryRatio; db.hypaV3Settings.similarMemoryRatio;
// Select important summaries
const selectedImportantSummaries: Summary[] = [];
for (const summary of data.summaries) {
if (summary.isImportant) {
const summaryTokens = await tokenizer.tokenizeChat({
role: "system",
content: summary.text + summarySeparator,
});
if (summaryTokens > availableMemoryTokens) {
break;
}
selectedImportantSummaries.push(summary);
availableMemoryTokens -= summaryTokens;
}
}
selectedSummaries.push(...selectedImportantSummaries);
console.log(
"[HypaV3] After important memory selection:",
"\nSummary Count:",
selectedImportantSummaries.length,
"\nSummaries:",
selectedImportantSummaries,
"\nAvailable Memory Tokens:",
availableMemoryTokens
);
// Select recent summaries // Select recent summaries
const reservedRecentMemoryTokens = Math.floor( const reservedRecentMemoryTokens = Math.floor(
availableMemoryTokens * db.hypaV3Settings.recentMemoryRatio availableMemoryTokens * db.hypaV3Settings.recentMemoryRatio
@@ -460,9 +497,14 @@ export async function hypaMemoryV3(
if (db.hypaV3Settings.recentMemoryRatio > 0) { if (db.hypaV3Settings.recentMemoryRatio > 0) {
const selectedRecentSummaries: Summary[] = []; const selectedRecentSummaries: Summary[] = [];
// Target only summaries that haven't been selected yet
const unusedSummaries = data.summaries.filter(
(e) => !selectedSummaries.includes(e)
);
// Add one by one from the end // Add one by one from the end
for (let i = data.summaries.length - 1; i >= 0; i--) { for (let i = unusedSummaries.length - 1; i >= 0; i--) {
const summary = data.summaries[i]; const summary = unusedSummaries[i];
const summaryTokens = await tokenizer.tokenizeChat({ const summaryTokens = await tokenizer.tokenizeChat({
role: "system", role: "system",
content: summary.text + summarySeparator, content: summary.text + summarySeparator,