feat: add resummarize button to HypaV3 Data modal

This commit is contained in:
Bo26fhmC5M
2025-01-12 23:32:20 +09:00
parent be1713df4b
commit ab7a2aa499
2 changed files with 64 additions and 16 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 } 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>

View File

@@ -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) {