feat: add resummarize button to 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 } from 'lucide-svelte';
|
import { ChevronRightIcon, User, RefreshCw } 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';
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
import { getChatBranches } from "src/ts/gui/branches";
|
import { getChatBranches } from "src/ts/gui/branches";
|
||||||
import { getCurrentCharacter } from "src/ts/storage/database.svelte";
|
import { getCurrentCharacter } from "src/ts/storage/database.svelte";
|
||||||
import { message } from "@tauri-apps/plugin-dialog";
|
import { message } from "@tauri-apps/plugin-dialog";
|
||||||
|
import { summarize as hypaV3Summarize } from "src/ts/process/memory/hypav3";
|
||||||
let btn
|
let btn
|
||||||
let input = $state('')
|
let input = $state('')
|
||||||
let cardExportType = $state('realm')
|
let cardExportType = $state('realm')
|
||||||
@@ -67,6 +68,8 @@
|
|||||||
let {
|
let {
|
||||||
onclick
|
onclick
|
||||||
}:Props = $props()
|
}:Props = $props()
|
||||||
|
|
||||||
|
let hypaV3Resummarizing = $state(false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window onmessage={async (e) => {
|
<svelte:window onmessage={async (e) => {
|
||||||
@@ -325,10 +328,11 @@
|
|||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<button class="p-2 hover:text-red-500 transition-colors" onclick={async () => {
|
<button class="p-2 hover:text-red-500 transition-colors" onclick={async () => {
|
||||||
const confirmed = await alertConfirm('This action cannot be undone. Do you want to reset HypaV3 data?')
|
const confirmed = await alertConfirm('This action cannot be undone. Do you want to reset HypaV3 data?')
|
||||||
|
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].hypaV3Data = {
|
DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].hypaV3Data = {
|
||||||
summaries: []
|
summaries: []
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
<Trash2Icon size={24}/>
|
<Trash2Icon size={24}/>
|
||||||
@@ -348,7 +352,48 @@
|
|||||||
<div class="flex flex-col p-4 rounded-md border-darkborderc border bg-bgcolor">
|
<div class="flex flex-col p-4 rounded-md border-darkborderc border bg-bgcolor">
|
||||||
<!-- Summary Text -->
|
<!-- Summary Text -->
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<span class="text-sm text-textcolor2 mb-2 block">Summary #{i + 1}</span>
|
<div class="flex justify-between items-center mb-2">
|
||||||
|
<span class="text-sm text-textcolor2">Summary #{i + 1}</span>
|
||||||
|
<button
|
||||||
|
class="p-1 hover:text-blue-500 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
onclick={async () => {
|
||||||
|
hypaV3Resummarizing = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
const char = DBState.db.characters[$selectedCharID]
|
||||||
|
const chat = char.chats[DBState.db.characters[$selectedCharID].chatPage]
|
||||||
|
const firstMessage = chat.fmIndex === -1 ? char.firstMessage : char.alternateGreetings?.[chat.fmIndex ?? 0]
|
||||||
|
const toSummarize = summary.chatMemos.map(chatMemo => {
|
||||||
|
if (chatMemo == null) {
|
||||||
|
return {
|
||||||
|
role: "assistant",
|
||||||
|
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 {
|
||||||
|
hypaV3Resummarizing = false
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
disabled={hypaV3Resummarizing}
|
||||||
|
>
|
||||||
|
<RefreshCw size={16}/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<TextAreaInput
|
<TextAreaInput
|
||||||
bind:value={summary.text}
|
bind:value={summary.text}
|
||||||
className="bg-darkbg"
|
className="bg-darkbg"
|
||||||
@@ -361,14 +406,17 @@
|
|||||||
Connected Messages ({summary.chatMemos.length})
|
Connected Messages ({summary.chatMemos.length})
|
||||||
</span>
|
</span>
|
||||||
<div class="flex flex-wrap gap-1">
|
<div class="flex flex-wrap gap-1">
|
||||||
{#each summary.chatMemos as memo}
|
{#each summary.chatMemos as chatMemo}
|
||||||
<div class="text-xs px-2 py-1 bg-darkbg rounded-full text-textcolor2 hover:bg-opacity-80 cursor-help"
|
<div class="text-xs px-2 py-1 bg-darkbg rounded-full text-textcolor2 hover:bg-opacity-80 cursor-help"
|
||||||
title={(() => {
|
title={(() => {
|
||||||
const message = DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].message.find(m => m.chatId === memo);
|
const char = DBState.db.characters[$selectedCharID]
|
||||||
return message ? (message.data.length > 100 ? message.data.slice(0, 100).trim() + '...' : message.data.trim()) : 'Message not found';
|
const chat = char.chats[DBState.db.characters[$selectedCharID].chatPage]
|
||||||
|
const firstMessage = chat.fmIndex === -1 ? char.firstMessage : char.alternateGreetings?.[chat.fmIndex ?? 0]
|
||||||
|
const message = chatMemo == null ? firstMessage : chat.message.find(m => m.chatId === chatMemo)?.data
|
||||||
|
return message ? (message.length > 100 ? message.slice(0, 100).trim() + "..." : message.trim()) : "Message not found"
|
||||||
})()}
|
})()}
|
||||||
>
|
>
|
||||||
{memo}
|
{chatMemo == null ? "First message" : chatMemo}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ function cleanOrphanedSummary(chats: OpenAIChat[], data: HypaV3Data): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function summary(
|
export async function summarize(
|
||||||
stringifiedChats: string
|
stringifiedChats: string
|
||||||
): Promise<{ success: boolean; data: string }> {
|
): Promise<{ success: boolean; data: string }> {
|
||||||
const db = getDatabase();
|
const db = getDatabase();
|
||||||
@@ -446,10 +446,10 @@ export async function hypaMemoryV3(
|
|||||||
toSummarize
|
toSummarize
|
||||||
);
|
);
|
||||||
|
|
||||||
const summaryResult = await summary(stringifiedChats);
|
const summarizeResult = await summarize(stringifiedChats);
|
||||||
|
|
||||||
if (!summaryResult.success) {
|
if (!summarizeResult.success) {
|
||||||
console.log("[HypaV3] Summarization failed:", summaryResult.data);
|
console.log("[HypaV3] Summarization failed:", summarizeResult.data);
|
||||||
summarizationFailures++;
|
summarizationFailures++;
|
||||||
|
|
||||||
if (summarizationFailures >= maxSummarizationFailures) {
|
if (summarizationFailures >= maxSummarizationFailures) {
|
||||||
@@ -465,7 +465,7 @@ export async function hypaMemoryV3(
|
|||||||
}
|
}
|
||||||
|
|
||||||
data.summaries.push({
|
data.summaries.push({
|
||||||
text: summaryResult.data,
|
text: summarizeResult.data,
|
||||||
chatMemos: new Set(toSummarize.map((chat) => chat.memo)),
|
chatMemos: new Set(toSummarize.map((chat) => chat.memo)),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -687,10 +687,10 @@ export async function hypaMemoryV3(
|
|||||||
recentChats
|
recentChats
|
||||||
);
|
);
|
||||||
|
|
||||||
const summaryResult = await summary(stringifiedRecentChats);
|
const summarizeResult = await summarize(stringifiedRecentChats);
|
||||||
|
|
||||||
if (!summaryResult.success) {
|
if (!summarizeResult.success) {
|
||||||
console.log("[HypaV3] Summarization failed:", summaryResult.data);
|
console.log("[HypaV3] Summarization failed:", summarizeResult.data);
|
||||||
summarizationFailures++;
|
summarizationFailures++;
|
||||||
|
|
||||||
if (summarizationFailures >= maxSummarizationFailures) {
|
if (summarizationFailures >= maxSummarizationFailures) {
|
||||||
@@ -706,7 +706,7 @@ export async function hypaMemoryV3(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const searched = await processor.similaritySearchScoredEx(
|
const searched = await processor.similaritySearchScoredEx(
|
||||||
summaryResult.data
|
summarizeResult.data
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const [chunk, similarity] of searched) {
|
for (const [chunk, similarity] of searched) {
|
||||||
|
|||||||
Reference in New Issue
Block a user