feat: add important button in HypaV3 Data modal
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user