+
-
HypaV3 Data
+
HypaV3 Data
{
let confirmed = await alertConfirm(
"This action cannot be undone. Do you want to reset HypaV3 data?"
@@ -53,9 +281,10 @@
>
+
{
alertStore.set({
type: "none",
@@ -67,167 +296,199 @@
-
- {#each DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].hypaV3Data.summaries as summary, i}
+
+
+
+ {#each modalState.summaries as summary, i}
-
-
-
-
Summary #{i + 1}
-
-
-
{
- summary.isImportant = !summary.isImportant;
- }}
- >
-
-
-
-
{
- hypaV3IsResummarizing = true;
+
+
+
Summary #{i + 1}
+
+
+ await toggleTranslate(summary)}
+ >
+
+
- 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,
- };
- }
+
+ {
+ summary.isImportant = !summary.isImportant;
+ }}
+ >
+
+
- 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 summarize(stringifiedChats);
-
- if (summarizeResult.success) {
- summary.text = summarizeResult.data;
- }
- } finally {
- hypaV3IsResummarizing = false;
- }
- }}
- disabled={hypaV3IsResummarizing}
- >
-
-
-
+
+
await toggleReroll(summary)}
+ disabled={!isRerollable(summary)}
+ >
+
+
-
-
-
-
-
- Connected Messages ({summary.chatMemos.length})
-
-
-
-
- {#each summary.chatMemos as chatMemo}
+
+
+
+
+ {#if summary.state.translation}
+
+
Translation
+
+ {summary.state.translation}
+
+
+ {/if}
+
+
+ {#if summary.state.rerolledText}
+
+
+
Rerolled Summary
+
+
+ await toggleTranslateRerolled(summary)}
+ >
+
+
+
+
+ {
- hypaV3ExpandedChatMemo =
- hypaV3ExpandedChatMemo.summaryChatMemos ===
- summary.chatMemos &&
- hypaV3ExpandedChatMemo.summaryChatMemo === chatMemo
- ? { summaryChatMemos: [], summaryChatMemo: "" }
- : {
- summaryChatMemos: summary.chatMemos,
- summaryChatMemo: chatMemo,
- };
+ summary.state.rerolledText = null;
+ summary.state.rerolledTranslation = null;
}}
>
- {chatMemo == null ? "First Message" : chatMemo}
+
- {/each}
-
-
- {#if hypaV3ExpandedChatMemo.summaryChatMemos === summary.chatMemos && hypaV3ExpandedChatMemo.summaryChatMemo !== ""}
-
-
+ {
+ summary.text = summary.state.rerolledText!;
+ summary.state.rerolledText = null;
+ summary.state.rerolledTranslation = null;
+ }}
>
- {(() => {
- 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 targetMessage =
- hypaV3ExpandedChatMemo.summaryChatMemo == null
- ? { role: "char", data: firstMessage }
- : chat.message.find(
- (m) =>
- m.chatId ===
- hypaV3ExpandedChatMemo.summaryChatMemo
- );
+
+
+
+
+
- if (targetMessage) {
- const displayRole =
- targetMessage.role === "char"
- ? char.name
- : targetMessage.role;
- return `${displayRole}:\n${targetMessage.data}`;
- }
-
- return "Message not found";
- })()}
+
+ {#if summary.state.rerolledTranslation}
+
+
Rerolled Translation
+
+ {summary.state.rerolledTranslation}
{/if}
+ {/if}
+
+
+
+
+
+ Connected Messages ({summary.chatMemos.length})
+
+
+ await toggleTranslateExpandedMessage()}
+ >
+
+
+
+
+
+
+ {#each summary.chatMemos as chatMemo}
+ toggleExpandMessage(summary, chatMemo)}
+ >
+ {chatMemo == null ? "First Message" : chatMemo}
+
+ {/each}
+
+
+
+ {#if modalState.expandedMessage?.summaryChatMemos === summary.chatMemos}
+ {@const messageData = getMessageData()}
+
+ {#if messageData}
+
+
+ {messageData.role}:
+
+
+
+ {messageData.data}
+
+ {:else}
+
Message not found
+ {/if}
+
+
+ {#if modalState.expandedMessage.translation}
+
+
Translation
+
+ {modalState.expandedMessage.translation}
+
+
+ {/if}
+
+ {/if}
{/each}
- {#if DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].hypaV3Data.summaries.length === 0}
+
+ {#if modalState.summaries.length === 0}
No summaries yet
{/if}
From 3e234dcb157fc7f049a38b064066325f3af4a8fe Mon Sep 17 00:00:00 2001
From: Bo26fhmC5M <88071760+Bo26fhmC5M@users.noreply.github.com>
Date: Wed, 15 Jan 2025 13:45:34 +0900
Subject: [PATCH 02/11] feat: add dual-action translation (cached/regenerate)
in HypaV3 modal Implements shift+click (desktop) and double tap (mobile) for
regenerating translations while maintaining regular click/tap for cached
translations.
---
src/lib/Others/HypaV3Modal.svelte | 106 ++++++++++++++++++++++++++----
src/ts/process/memory/hypav3.ts | 4 +-
2 files changed, 96 insertions(+), 14 deletions(-)
diff --git a/src/lib/Others/HypaV3Modal.svelte b/src/lib/Others/HypaV3Modal.svelte
index 4aebdf7d..89faa2df 100644
--- a/src/lib/Others/HypaV3Modal.svelte
+++ b/src/lib/Others/HypaV3Modal.svelte
@@ -61,7 +61,10 @@
expandedMessage: null,
});
- async function toggleTranslate(summary: ExtendedSummary): Promise
{
+ async function toggleTranslate(
+ summary: ExtendedSummary,
+ regenerate?: boolean
+ ): Promise {
if (summary.state.isTranslating) return;
if (summary.state.translation) {
@@ -72,7 +75,7 @@
summary.state.isTranslating = true;
summary.state.translation = "Loading...";
- const result = await translate(summary.text);
+ const result = await translate(summary.text, regenerate);
summary.state.translation = result;
summary.state.isTranslating = false;
@@ -144,7 +147,8 @@
}
async function toggleTranslateRerolled(
- summary: ExtendedSummary
+ summary: ExtendedSummary,
+ regenerate?: boolean
): Promise {
if (summary.state.isRerolledTranslating) return;
@@ -158,13 +162,15 @@
summary.state.isRerolledTranslating = true;
summary.state.rerolledTranslation = "Loading...";
- const result = await translate(summary.state.rerolledText);
+ const result = await translate(summary.state.rerolledText, regenerate);
summary.state.rerolledTranslation = result;
summary.state.isRerolledTranslating = false;
}
- async function toggleTranslateExpandedMessage(): Promise {
+ async function toggleTranslateExpandedMessage(
+ regenerate?: boolean
+ ): Promise {
if (!modalState.expandedMessage || modalState.expandedMessage.isTranslating)
return;
@@ -180,7 +186,7 @@
modalState.expandedMessage.isTranslating = true;
modalState.expandedMessage.translation = "Loading...";
- const result = await translate(messageData.data);
+ const result = await translate(messageData.data, regenerate);
modalState.expandedMessage.translation = result;
modalState.expandedMessage.isTranslating = false;
@@ -235,13 +241,78 @@
};
}
- async function translate(text) {
+ async function translate(
+ text: string,
+ regenerate?: boolean
+ ): Promise {
try {
- return await translateHTML(text, false, "", -1);
+ return await translateHTML(text, false, "", -1, regenerate);
} catch (error) {
return `Translation failed: ${error}`;
}
}
+
+ type DualActionParams = {
+ onMainAction?: () => void;
+ onAlternativeAction?: () => void;
+ };
+
+ function handleDualAction(node: HTMLElement, params: DualActionParams = {}) {
+ const state = {
+ lastTap: 0,
+ tapTimeout: null as any,
+ };
+
+ const DOUBLE_TAP_DELAY = 300;
+
+ function handleInteraction(event: Event) {
+ if ("ontouchend" in window) {
+ // Mobile environment
+ const currentTime = new Date().getTime();
+ const tapLength = currentTime - state.lastTap;
+
+ if (tapLength < DOUBLE_TAP_DELAY && tapLength > 0) {
+ // Double tap detected
+ event.preventDefault();
+ clearTimeout(state.tapTimeout); // Cancel the first tap timeout
+ params.onAlternativeAction?.();
+ state.lastTap = 0; // Reset state
+ } else {
+ // First tap
+ state.lastTap = currentTime;
+
+ // Delayed single tap execution
+ state.tapTimeout = setTimeout(() => {
+ if (state.lastTap === currentTime) {
+ // If no double tap occurred
+ params.onMainAction?.();
+ }
+ }, DOUBLE_TAP_DELAY);
+ }
+ } else {
+ // Desktop environment
+ if ((event as MouseEvent).shiftKey) {
+ params.onAlternativeAction?.();
+ } else {
+ params.onMainAction?.();
+ }
+ }
+ }
+
+ node.addEventListener("click", handleInteraction);
+ node.addEventListener("touchend", handleInteraction);
+
+ return {
+ destroy() {
+ node.removeEventListener("click", handleInteraction);
+ node.removeEventListener("touchend", handleInteraction);
+ clearTimeout(state.tapTimeout); // Cleanup timeout
+ },
+ update(newParams: DualActionParams) {
+ params = newParams;
+ },
+ };
+ }
@@ -310,7 +381,10 @@
await toggleTranslate(summary)}
+ use:handleDualAction={{
+ onMainAction: () => toggleTranslate(summary, false),
+ onAlternativeAction: () => toggleTranslate(summary, true),
+ }}
>
@@ -367,8 +441,12 @@
- await toggleTranslateRerolled(summary)}
+ use:handleDualAction={{
+ onMainAction: () =>
+ toggleTranslateRerolled(summary, false),
+ onAlternativeAction: () =>
+ toggleTranslateRerolled(summary, true),
+ }}
>
@@ -427,7 +505,11 @@
await toggleTranslateExpandedMessage()}
+ use:handleDualAction={{
+ onMainAction: () => toggleTranslateExpandedMessage(false),
+ onAlternativeAction: () =>
+ toggleTranslateExpandedMessage(true),
+ }}
>
diff --git a/src/ts/process/memory/hypav3.ts b/src/ts/process/memory/hypav3.ts
index 4786c1bf..25d7d83f 100644
--- a/src/ts/process/memory/hypav3.ts
+++ b/src/ts/process/memory/hypav3.ts
@@ -854,7 +854,7 @@ class HypaProcesserEx extends HypaProcesser {
summaryChunkVectors: SummaryChunkVector[] = [];
// Calculate dot product similarity between two vectors
- similarity(a: VectorArray, b: VectorArray) {
+ similarity(a: VectorArray, b: VectorArray): number {
let dot = 0;
for (let i = 0; i < a.length; i++) {
@@ -864,7 +864,7 @@ class HypaProcesserEx extends HypaProcesser {
return dot;
}
- async addSummaryChunks(chunks: SummaryChunk[]) {
+ async addSummaryChunks(chunks: SummaryChunk[]): Promise
{
// Maintain the superclass's caching structure by adding texts
const texts = chunks.map((chunk) => chunk.text);
From d59cc1a29cd35f11e6e7ec4e21cd23296bbcc878 Mon Sep 17 00:00:00 2001
From: Bo26fhmC5M <88071760+Bo26fhmC5M@users.noreply.github.com>
Date: Wed, 15 Jan 2025 19:56:07 +0900
Subject: [PATCH 03/11] refactor: update UI management to index-based approach
---
src/lib/Others/HypaV3Modal.svelte | 312 ++++++++++++++----------------
1 file changed, 148 insertions(+), 164 deletions(-)
diff --git a/src/lib/Others/HypaV3Modal.svelte b/src/lib/Others/HypaV3Modal.svelte
index 89faa2df..582236c9 100644
--- a/src/lib/Others/HypaV3Modal.svelte
+++ b/src/lib/Others/HypaV3Modal.svelte
@@ -10,78 +10,94 @@
import TextAreaInput from "../UI/GUI/TextAreaInput.svelte";
import { alertConfirm } from "../../ts/alert";
import { DBState, alertStore, selectedCharID } from "src/ts/stores.svelte";
- import {
- type SerializableHypaV3Data,
- summarize,
- } from "src/ts/process/memory/hypav3";
+ import { summarize } from "src/ts/process/memory/hypav3";
import { translateHTML } from "src/ts/translator/translator";
- import PersonaSettings from "../Setting/Pages/PersonaSettings.svelte";
- type Summary = SerializableHypaV3Data["summaries"][number];
-
- interface ExtendedSummary extends Summary {
- state: {
- isTranslating: boolean;
- translation?: string | null;
- isRerolling: boolean;
- rerolledText?: string | null;
- isRerolledTranslating: boolean;
- rerolledTranslation?: string | null;
- };
+ interface SummaryUI {
+ isTranslating: boolean;
+ translation: string | null;
+ isRerolling: boolean;
+ rerolledText: string | null;
+ isRerolledTranslating: boolean;
+ rerolledTranslation: string | null;
}
- interface HypaV3ModalState {
- summaries: ExtendedSummary[];
- expandedMessage: {
- summaryChatMemos: string[];
- selectedChatMemo: string;
- isTranslating: boolean;
- translation?: string | null;
- } | null;
+ interface ExpandedMessageUI {
+ summaryIndex: number;
+ selectedChatMemo: string;
+ isTranslating: boolean;
+ translation?: string | null;
}
- // Initialize modal state
- let modalState = $state({
- summaries: DBState.db.characters[$selectedCharID].chats[
+ const hypaV3DataState = $state(
+ DBState.db.characters[$selectedCharID].chats[
DBState.db.characters[$selectedCharID].chatPage
- ].hypaV3Data.summaries.map((s) => {
- const summary = s as ExtendedSummary;
+ ].hypaV3Data
+ );
+ const summaryUIStates = $state(
+ hypaV3DataState.summaries.map(() => ({
+ isTranslating: false,
+ translation: null,
+ isRerolling: false,
+ rerolledText: null,
+ isRerolledTranslating: false,
+ rerolledTranslation: null,
+ }))
+ );
+ let expandedMessageUIState = $state(null);
- summary.state = {
- isTranslating: false,
- translation: null,
- isRerolling: false,
- rerolledText: null,
- isRerolledTranslating: false,
- rerolledTranslation: null,
- };
-
- return summary;
- }),
- expandedMessage: null,
+ $effect(() => {
+ // Detects changes in all nested properties including summaries
+ hypaV3DataState.summaries;
+ expandedMessageUIState = null;
});
+ function getMessageFromChatMemo(
+ chatMemo: string | null
+ ): { role: string; data: string } | null {
+ 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 targetMessage =
+ chatMemo == null
+ ? { role: "char", data: firstMessage }
+ : chat.message.find((m) => m.chatId === chatMemo);
+
+ return targetMessage;
+ }
+
async function toggleTranslate(
- summary: ExtendedSummary,
+ summaryIndex: number,
regenerate?: boolean
): Promise {
- if (summary.state.isTranslating) return;
+ const summaryUIState = summaryUIStates[summaryIndex];
- if (summary.state.translation) {
- summary.state.translation = null;
+ if (summaryUIState.isTranslating) return;
+
+ if (summaryUIState.translation) {
+ summaryUIState.translation = null;
return;
}
- summary.state.isTranslating = true;
- summary.state.translation = "Loading...";
+ summaryUIState.isTranslating = true;
+ summaryUIState.translation = "Loading...";
- const result = await translate(summary.text, regenerate);
+ const result = await translate(
+ hypaV3DataState.summaries[summaryIndex].text,
+ regenerate
+ );
- summary.state.translation = result;
- summary.state.isTranslating = false;
+ summaryUIState.translation = result;
+ summaryUIState.isTranslating = false;
}
- function isRerollable(summary: ExtendedSummary): boolean {
+ function isRerollable(summaryIndex: number): boolean {
+ const summary = hypaV3DataState.summaries[summaryIndex];
+
for (const chatMemo of summary.chatMemos) {
if (typeof chatMemo === "string") {
const char = DBState.db.characters[$selectedCharID];
@@ -93,154 +109,121 @@
}
}
}
-
return true;
}
- async function toggleReroll(summary: ExtendedSummary): Promise {
- if (summary.state.isRerolling) return;
- if (!isRerollable(summary)) return;
+ async function toggleReroll(summaryIndex: number): Promise {
+ const summaryUIState = summaryUIStates[summaryIndex];
- summary.state.isRerolling = true;
- summary.state.rerolledText = "Loading...";
+ if (summaryUIState.isRerolling) return;
+ if (!isRerollable(summaryIndex)) return;
+
+ summaryUIState.isRerolling = true;
+ summaryUIState.rerolledText = "Loading...";
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 summary = hypaV3DataState.summaries[summaryIndex];
const toSummarize = summary.chatMemos.map((chatMemo) => {
- if (chatMemo == null) {
- return {
- role: "assistant",
- data: firstMessage,
- };
- }
+ const message = getMessageFromChatMemo(chatMemo);
- const msg = chat.message.find((m) => m.chatId === chatMemo);
-
- return msg
- ? {
- role: msg.role === "char" ? "assistant" : msg.role,
- data: msg.data,
- }
- : null;
+ return {
+ ...message,
+ role: message.role === "char" ? "assistant" : message.role,
+ };
});
const stringifiedChats = toSummarize
.map((m) => `${m.role}: ${m.data}`)
.join("\n");
-
const summarizeResult = await summarize(stringifiedChats);
if (summarizeResult.success) {
- summary.state.rerolledText = summarizeResult.data;
+ summaryUIState.rerolledText = summarizeResult.data;
}
} catch (error) {
- summary.state.rerolledText = "Reroll failed";
+ summaryUIState.rerolledText = "Reroll failed";
} finally {
- summary.state.isRerolling = false;
+ summaryUIState.isRerolling = false;
}
}
async function toggleTranslateRerolled(
- summary: ExtendedSummary,
+ summaryIndex: number,
regenerate?: boolean
): Promise {
- if (summary.state.isRerolledTranslating) return;
+ const summaryUIState = summaryUIStates[summaryIndex];
- if (summary.state.rerolledTranslation) {
- summary.state.rerolledTranslation = null;
+ if (summaryUIState.isRerolledTranslating) return;
+
+ if (summaryUIState.rerolledTranslation) {
+ summaryUIState.rerolledTranslation = null;
return;
}
- if (!summary.state.rerolledText) return;
+ if (!summaryUIState.rerolledText) return;
- summary.state.isRerolledTranslating = true;
- summary.state.rerolledTranslation = "Loading...";
+ summaryUIState.isRerolledTranslating = true;
+ summaryUIState.rerolledTranslation = "Loading...";
- const result = await translate(summary.state.rerolledText, regenerate);
+ const result = await translate(summaryUIState.rerolledText, regenerate);
- summary.state.rerolledTranslation = result;
- summary.state.isRerolledTranslating = false;
+ summaryUIState.rerolledTranslation = result;
+ summaryUIState.isRerolledTranslating = false;
}
async function toggleTranslateExpandedMessage(
regenerate?: boolean
): Promise {
- if (!modalState.expandedMessage || modalState.expandedMessage.isTranslating)
- return;
+ if (!expandedMessageUIState || expandedMessageUIState.isTranslating) return;
- if (modalState.expandedMessage.translation) {
- modalState.expandedMessage.translation = null;
+ if (expandedMessageUIState.translation) {
+ expandedMessageUIState.translation = null;
return;
}
- const messageData = getMessageData();
+ const message = getMessageFromChatMemo(
+ expandedMessageUIState.selectedChatMemo
+ );
- if (!messageData) return;
+ if (!message) return;
- modalState.expandedMessage.isTranslating = true;
- modalState.expandedMessage.translation = "Loading...";
+ expandedMessageUIState.isTranslating = true;
+ expandedMessageUIState.translation = "Loading...";
- const result = await translate(messageData.data, regenerate);
+ const result = await translate(message.data, regenerate);
- modalState.expandedMessage.translation = result;
- modalState.expandedMessage.isTranslating = false;
+ expandedMessageUIState.translation = result;
+ expandedMessageUIState.isTranslating = false;
}
function isMessageExpanded(
- summary: ExtendedSummary,
+ summaryIndex: number,
chatMemo: string | null
): boolean {
+ if (!expandedMessageUIState) return false;
+
+ const summary = hypaV3DataState.summaries[summaryIndex];
+
return (
- modalState.expandedMessage?.summaryChatMemos === summary.chatMemos &&
- modalState.expandedMessage?.selectedChatMemo === chatMemo
+ expandedMessageUIState.summaryIndex === summaryIndex &&
+ expandedMessageUIState.selectedChatMemo === chatMemo
);
}
function toggleExpandMessage(
- summary: ExtendedSummary,
+ summaryIndex: number,
chatMemo: string | null
): void {
- modalState.expandedMessage = isMessageExpanded(summary, chatMemo)
+ expandedMessageUIState = isMessageExpanded(summaryIndex, chatMemo)
? null
: {
- summaryChatMemos: summary.chatMemos,
+ summaryIndex,
selectedChatMemo: chatMemo,
isTranslating: false,
translation: null,
};
}
- function getMessageData(): { role: string; data: string } | null {
- 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 targetMessage =
- modalState.expandedMessage?.selectedChatMemo == null
- ? { role: "char", data: firstMessage }
- : chat.message.find(
- (m) => m.chatId === modalState.expandedMessage!.selectedChatMemo
- );
-
- if (!targetMessage) {
- return null;
- }
-
- return {
- ...targetMessage,
- role: targetMessage.role === "char" ? char.name : targetMessage.role,
- };
- }
-
async function translate(
text: string,
regenerate?: boolean
@@ -318,7 +301,7 @@
- {#each modalState.summaries as summary, i}
+ {#each hypaV3DataState.summaries as summary, i}
@@ -382,8 +365,8 @@
toggleTranslate(summary, false),
- onAlternativeAction: () => toggleTranslate(summary, true),
+ onMainAction: () => toggleTranslate(i, false),
+ onAlternativeAction: () => toggleTranslate(i, true),
}}
>
@@ -404,8 +387,8 @@
await toggleReroll(summary)}
- disabled={!isRerollable(summary)}
+ onclick={async () => await toggleReroll(i)}
+ disabled={!isRerollable(i)}
>
@@ -419,7 +402,7 @@
/>
- {#if summary.state.translation}
+ {#if summaryUIStates[i].translation}
Translation
- {summary.state.translation}
+ {summaryUIStates[i].translation}
{/if}
- {#if summary.state.rerolledText}
+ {#if summaryUIStates[i].rerolledText}
Rerolled Summary
@@ -442,10 +425,9 @@
- toggleTranslateRerolled(summary, false),
+ onMainAction: () => toggleTranslateRerolled(i, false),
onAlternativeAction: () =>
- toggleTranslateRerolled(summary, true),
+ toggleTranslateRerolled(i, true),
}}
>
@@ -455,8 +437,8 @@
{
- summary.state.rerolledText = null;
- summary.state.rerolledTranslation = null;
+ summaryUIStates[i].rerolledText = null;
+ summaryUIStates[i].rerolledTranslation = null;
}}
>
@@ -466,9 +448,9 @@
{
- summary.text = summary.state.rerolledText!;
- summary.state.rerolledText = null;
- summary.state.rerolledTranslation = null;
+ summary.text = summaryUIStates[i].rerolledText!;
+ summaryUIStates[i].rerolledText = null;
+ summaryUIStates[i].rerolledTranslation = null;
}}
>
@@ -476,12 +458,12 @@
- {#if summary.state.rerolledTranslation}
+ {#if summaryUIStates[i].rerolledTranslation}
Rerolled Translation
- {summary.state.rerolledTranslation}
+ {summaryUIStates[i].rerolledTranslation}
{/if}
@@ -520,12 +502,12 @@
{#each summary.chatMemos as chatMemo}
toggleExpandMessage(summary, chatMemo)}
+ onclick={() => toggleExpandMessage(i, chatMemo)}
>
{chatMemo == null ? "First Message" : chatMemo}
@@ -533,26 +515,28 @@
- {#if modalState.expandedMessage?.summaryChatMemos === summary.chatMemos}
- {@const messageData = getMessageData()}
+ {#if expandedMessageUIState?.summaryIndex === i}
+ {@const message = getMessageFromChatMemo(
+ expandedMessageUIState.selectedChatMemo
+ )}
- {#if messageData}
+ {#if message}
- {messageData.role}:
+ {message.role}'s Message
- {messageData.data}
+ {message.data}
{:else}
Message not found
{/if}
- {#if modalState.expandedMessage.translation}
+ {#if expandedMessageUIState.translation}
Translation
- {modalState.expandedMessage.translation}
+ {expandedMessageUIState.translation}
{/if}
@@ -570,7 +554,7 @@
{/each}
- {#if modalState.summaries.length === 0}
+ {#if hypaV3DataState.summaries.length === 0}
No summaries yet
{/if}
From c57c2561901622b3344453cb9d4588409271a127 Mon Sep 17 00:00:00 2001
From: Bo26fhmC5M <88071760+Bo26fhmC5M@users.noreply.github.com>
Date: Thu, 16 Jan 2025 01:23:02 +0900
Subject: [PATCH 04/11] fix: reactive declarations
---
src/lib/Others/HypaV3Modal.svelte | 383 ++++++++++++++++--------------
1 file changed, 200 insertions(+), 183 deletions(-)
diff --git a/src/lib/Others/HypaV3Modal.svelte b/src/lib/Others/HypaV3Modal.svelte
index 582236c9..099e669c 100644
--- a/src/lib/Others/HypaV3Modal.svelte
+++ b/src/lib/Others/HypaV3Modal.svelte
@@ -29,13 +29,16 @@
translation?: string | null;
}
- const hypaV3DataState = $state(
+ const hypaV3DataState = $derived(
DBState.db.characters[$selectedCharID].chats[
DBState.db.characters[$selectedCharID].chatPage
].hypaV3Data
);
- const summaryUIStates = $state(
- hypaV3DataState.summaries.map(() => ({
+
+ let summaryUIStates = $state(
+ DBState.db.characters[$selectedCharID].chats[
+ DBState.db.characters[$selectedCharID].chatPage
+ ].hypaV3Data.summaries.map(() => ({
isTranslating: false,
translation: null,
isRerolling: false,
@@ -47,8 +50,18 @@
let expandedMessageUIState = $state(null);
$effect(() => {
- // Detects changes in all nested properties including summaries
hypaV3DataState.summaries;
+ hypaV3DataState.summaries.length;
+
+ summaryUIStates = hypaV3DataState.summaries.map(() => ({
+ isTranslating: false,
+ translation: null,
+ isRerolling: false,
+ rerolledText: null,
+ isRerolledTranslating: false,
+ rerolledTranslation: null,
+ }));
+
expandedMessageUIState = null;
});
@@ -354,204 +367,208 @@
{#each hypaV3DataState.summaries as summary, i}
-
-
-
-
Summary #{i + 1}
-
-
- toggleTranslate(i, false),
- onAlternativeAction: () => toggleTranslate(i, true),
- }}
- >
-
-
-
-
- {
- summary.isImportant = !summary.isImportant;
- }}
- >
-
-
-
-
- await toggleReroll(i)}
- disabled={!isRerollable(i)}
- >
-
-
-
-
-
-
-
-
-
- {#if summaryUIStates[i].translation}
-
-
Translation
-
- {summaryUIStates[i].translation}
-
-
- {/if}
-
-
- {#if summaryUIStates[i].rerolledText}
-
-
-
Rerolled Summary
-
-
- toggleTranslateRerolled(i, false),
- onAlternativeAction: () =>
- toggleTranslateRerolled(i, true),
- }}
- >
-
-
-
-
- {
- summaryUIStates[i].rerolledText = null;
- summaryUIStates[i].rerolledTranslation = null;
- }}
- >
-
-
-
-
- {
- summary.text = summaryUIStates[i].rerolledText!;
- summaryUIStates[i].rerolledText = null;
- summaryUIStates[i].rerolledTranslation = null;
- }}
- >
-
-
-
-
-
-
-
- {#if summaryUIStates[i].rerolledTranslation}
-
-
Rerolled Translation
-
- {summaryUIStates[i].rerolledTranslation}
-
-
- {/if}
-
- {/if}
-
-
-
+ {#if summaryUIStates[i]}
+
+
-
- Connected Messages ({summary.chatMemos.length})
-
-
- toggleTranslateExpandedMessage(false),
- onAlternativeAction: () =>
- toggleTranslateExpandedMessage(true),
- }}
- >
-
-
-
-
-
-
- {#each summary.chatMemos as chatMemo}
+
Summary #{i + 1}
+
+
toggleExpandMessage(i, chatMemo)}
+ class="p-2 text-zinc-400 hover:text-zinc-200 transition-colors"
+ use:handleDualAction={{
+ onMainAction: () => toggleTranslate(i, false),
+ onAlternativeAction: () => toggleTranslate(i, true),
+ }}
>
- {chatMemo == null ? "First Message" : chatMemo}
+
- {/each}
+
+
+ {
+ summary.isImportant = !summary.isImportant;
+ }}
+ >
+
+
+
+
+ await toggleReroll(i)}
+ disabled={!isRerollable(i)}
+ >
+
+
+
-
- {#if expandedMessageUIState?.summaryIndex === i}
- {@const message = getMessageFromChatMemo(
- expandedMessageUIState.selectedChatMemo
- )}
-
- {#if message}
-
-
- {message.role}'s Message
-
-
-
- {message.data}
-
- {:else}
-
Message not found
- {/if}
+
+
-
- {#if expandedMessageUIState.translation}
+
+ {#if summaryUIStates[i].translation}
+
+
Translation
+
+ {summaryUIStates[i].translation}
+
+
+ {/if}
+
+
+ {#if summaryUIStates[i].rerolledText}
+
+
+
Rerolled Summary
+
+
+ toggleTranslateRerolled(i, false),
+ onAlternativeAction: () =>
+ toggleTranslateRerolled(i, true),
+ }}
+ >
+
+
+
+
+ {
+ summaryUIStates[i].rerolledText = null;
+ summaryUIStates[i].rerolledTranslation = null;
+ }}
+ >
+
+
+
+
+ {
+ summary.text = summaryUIStates[i].rerolledText!;
+ summaryUIStates[i].translation = null;
+ summaryUIStates[i].rerolledText = null;
+ summaryUIStates[i].rerolledTranslation = null;
+ }}
+ >
+
+
+
+
+
+
+
+ {#if summaryUIStates[i].rerolledTranslation}
Translation Rerolled Translation
- {expandedMessageUIState.translation}
+ {summaryUIStates[i].rerolledTranslation}
{/if}
{/if}
+
+
+
+
+
+ Connected Messages ({summary.chatMemos.length})
+
+
+ toggleTranslateExpandedMessage(false),
+ onAlternativeAction: () =>
+ toggleTranslateExpandedMessage(true),
+ }}
+ >
+
+
+
+
+
+
+ {#each summary.chatMemos as chatMemo}
+ toggleExpandMessage(i, chatMemo)}
+ >
+ {chatMemo == null ? "First Message" : chatMemo}
+
+ {/each}
+
+
+
+ {#if expandedMessageUIState?.summaryIndex === i}
+ {@const message = getMessageFromChatMemo(
+ expandedMessageUIState.selectedChatMemo
+ )}
+
+ {#if message}
+
+
+ {message.role}'s Message
+
+
+
+ {message.data}
+
+ {:else}
+
Message not found
+ {/if}
+
+
+ {#if expandedMessageUIState.translation}
+
+
Translation
+
+ {expandedMessageUIState.translation}
+
+
+ {/if}
+
+ {/if}
+
-
+ {/if}
{/each}
{#if hypaV3DataState.summaries.length === 0}
From 682f536c5a39aa53eaef76a7277e131fc0b105d9 Mon Sep 17 00:00:00 2001
From: Bo26fhmC5M <88071760+Bo26fhmC5M@users.noreply.github.com>
Date: Thu, 16 Jan 2025 01:36:29 +0900
Subject: [PATCH 05/11] refactor: extract double confirmation logic into
reusable function
---
src/lib/Others/HypaV3Modal.svelte | 44 ++++++++++++++++++++-----------
1 file changed, 28 insertions(+), 16 deletions(-)
diff --git a/src/lib/Others/HypaV3Modal.svelte b/src/lib/Others/HypaV3Modal.svelte
index 099e669c..690b8e61 100644
--- a/src/lib/Others/HypaV3Modal.svelte
+++ b/src/lib/Others/HypaV3Modal.svelte
@@ -8,7 +8,7 @@
CheckIcon,
} from "lucide-svelte";
import TextAreaInput from "../UI/GUI/TextAreaInput.svelte";
- import { alertConfirm } from "../../ts/alert";
+ import { alertConfirm, showHypaV3Alert } from "../../ts/alert";
import { DBState, alertStore, selectedCharID } from "src/ts/stores.svelte";
import { summarize } from "src/ts/process/memory/hypav3";
import { translateHTML } from "src/ts/translator/translator";
@@ -65,6 +65,21 @@
expandedMessageUIState = null;
});
+ async function confirmTwice(
+ firstMessage: string,
+ secondMessage: string
+ ): Promise
{
+ let confirmed = await alertConfirm(firstMessage);
+
+ if (confirmed) {
+ confirmed = await alertConfirm(secondMessage);
+
+ if (confirmed) {
+ return true;
+ }
+ }
+ }
+
function getMessageFromChatMemo(
chatMemo: string | null
): { role: string; data: string } | null {
@@ -327,22 +342,19 @@
{
- let confirmed = await alertConfirm(
- "This action cannot be undone. Do you want to reset HypaV3 data?"
- );
-
- if (confirmed) {
- confirmed = await alertConfirm(
+ if (
+ await confirmTwice(
+ "This action cannot be undone. Do you want to reset HypaV3 data?",
"This action is irreversible. Do you really, really want to reset HypaV3 data?"
- );
-
- if (confirmed) {
- DBState.db.characters[$selectedCharID].chats[
- DBState.db.characters[$selectedCharID].chatPage
- ].hypaV3Data = {
- summaries: [],
- };
- }
+ )
+ ) {
+ DBState.db.characters[$selectedCharID].chats[
+ DBState.db.characters[$selectedCharID].chatPage
+ ].hypaV3Data = {
+ summaries: [],
+ };
+ } else {
+ showHypaV3Alert();
}
}}
>
From 6ffaa1257e9ba5d1dc2d8093af757c746b4c4d49 Mon Sep 17 00:00:00 2001
From: Bo26fhmC5M <88071760+Bo26fhmC5M@users.noreply.github.com>
Date: Thu, 16 Jan 2025 22:12:32 +0900
Subject: [PATCH 06/11] feat: improve ratio sliders interaction in HypaV3
settings
---
src/lib/Others/HypaV3Modal.svelte | 34 +++---------
src/lib/Setting/Pages/OtherBotSettings.svelte | 53 ++++++++++++++-----
2 files changed, 47 insertions(+), 40 deletions(-)
diff --git a/src/lib/Others/HypaV3Modal.svelte b/src/lib/Others/HypaV3Modal.svelte
index 690b8e61..8f2e1f11 100644
--- a/src/lib/Others/HypaV3Modal.svelte
+++ b/src/lib/Others/HypaV3Modal.svelte
@@ -35,24 +35,10 @@
].hypaV3Data
);
- let summaryUIStates = $state(
- DBState.db.characters[$selectedCharID].chats[
- DBState.db.characters[$selectedCharID].chatPage
- ].hypaV3Data.summaries.map(() => ({
- isTranslating: false,
- translation: null,
- isRerolling: false,
- rerolledText: null,
- isRerolledTranslating: false,
- rerolledTranslation: null,
- }))
- );
+ let summaryUIStates = $state([]);
let expandedMessageUIState = $state(null);
- $effect(() => {
- hypaV3DataState.summaries;
- hypaV3DataState.summaries.length;
-
+ $effect.pre(() => {
summaryUIStates = hypaV3DataState.summaries.map(() => ({
isTranslating: false,
translation: null,
@@ -65,19 +51,13 @@
expandedMessageUIState = null;
});
- async function confirmTwice(
+ async function alertConfirmTwice(
firstMessage: string,
secondMessage: string
): Promise {
- let confirmed = await alertConfirm(firstMessage);
-
- if (confirmed) {
- confirmed = await alertConfirm(secondMessage);
-
- if (confirmed) {
- return true;
- }
- }
+ return (
+ (await alertConfirm(firstMessage)) && (await alertConfirm(secondMessage))
+ );
}
function getMessageFromChatMemo(
@@ -343,7 +323,7 @@
class="p-2 text-zinc-400 hover:text-zinc-200 hover:text-rose-300 transition-colors"
onclick={async () => {
if (
- await confirmTwice(
+ await alertConfirmTwice(
"This action cannot be undone. Do you want to reset HypaV3 data?",
"This action is irreversible. Do you really, really want to reset HypaV3 data?"
)
diff --git a/src/lib/Setting/Pages/OtherBotSettings.svelte b/src/lib/Setting/Pages/OtherBotSettings.svelte
index 086e234a..8259f29b 100644
--- a/src/lib/Setting/Pages/OtherBotSettings.svelte
+++ b/src/lib/Setting/Pages/OtherBotSettings.svelte
@@ -15,8 +15,9 @@
import { getCharImage } from "src/ts/characters";
import Arcodion from "src/lib/UI/Arcodion.svelte";
import CheckInput from "src/lib/UI/GUI/CheckInput.svelte";
- import TextAreaInput from "src/lib/UI/GUI/TextAreaInput.svelte";
- import { hypaMemoryV3 } from "src/ts/process/memory/hypav3";
+ import TextAreaInput from "src/lib/UI/GUI/TextAreaInput.svelte";
+ import { untrack } from "svelte";
+
$effect.pre(() => {
DBState.db.NAIImgConfig ??= {
width: 512,
@@ -40,6 +41,32 @@
});
let submenu = $state(DBState.db.useLegacyGUI ? -1 : 0)
+
+ // HypaV3
+ $effect(() => {
+ const newValue = Math.min(DBState.db.hypaV3Settings.recentMemoryRatio, 1);
+
+ untrack(() => {
+ DBState.db.hypaV3Settings.recentMemoryRatio = newValue;
+
+ if (newValue + DBState.db.hypaV3Settings.similarMemoryRatio > 1) {
+ DBState.db.hypaV3Settings.similarMemoryRatio = 1 - newValue;
+ }
+ })
+ })
+
+ $effect(() => {
+ const newValue = Math.min(DBState.db.hypaV3Settings.similarMemoryRatio, 1);
+
+ untrack(() => {
+ DBState.db.hypaV3Settings.similarMemoryRatio = newValue;
+
+ if (newValue + DBState.db.hypaV3Settings.recentMemoryRatio > 1) {
+ DBState.db.hypaV3Settings.recentMemoryRatio = 1 - newValue;
+ }
+ })
+ });
+ // End HypaV3
{language.otherBots}
@@ -467,31 +494,31 @@
OpenAI 3.5 Turbo Instruct
{language.submodel}
- {#if DBState.db.supaModelType === 'instruct35'}
+ {#if DBState.db.supaModelType === "instruct35"}
OpenAI API Key
-
+
{/if}
{language.summarizationPrompt}
-
+
Memory Tokens Ratio
-
+
Extra Summarization Ratio
-
+
Max Chats Per Summary
-
+
Recent Memory Ratio
-
+
Similar Memory Ratio
-
+
Random Memory Ratio
-
+
-
+
-
+
{:else if (DBState.db.supaModelType !== 'none' && DBState.db.hypav2 === false && DBState.db.hypaV3 === false)}
{language.supaDesc}
From fac11bfe67077975de684a212cebcdb564c57f17 Mon Sep 17 00:00:00 2001
From: Bo26fhmC5M <88071760+Bo26fhmC5M@users.noreply.github.com>
Date: Thu, 16 Jan 2025 22:40:08 +0900
Subject: [PATCH 07/11] fix: improve HypaV3 logging
---
src/ts/process/memory/hypav3.ts | 137 +++++++++++++++++---------------
1 file changed, 71 insertions(+), 66 deletions(-)
diff --git a/src/ts/process/memory/hypav3.ts b/src/ts/process/memory/hypav3.ts
index 25d7d83f..7495c74f 100644
--- a/src/ts/process/memory/hypav3.ts
+++ b/src/ts/process/memory/hypav3.ts
@@ -87,7 +87,7 @@ function cleanOrphanedSummary(chats: OpenAIChat[], data: HypaV3Data): void {
const removedCount = originalLength - data.summaries.length;
if (removedCount > 0) {
- console.log(`[HypaV3] Cleaned ${removedCount} orphaned summaries`);
+ console.log(`[HypaV3] Cleaned ${removedCount} orphaned summaries.`);
}
}
@@ -103,7 +103,7 @@ export async function summarize(
} catch (error) {
return {
success: false,
- data: "[HypaV3] " + error,
+ data: error,
};
}
}
@@ -116,7 +116,7 @@ export async function summarize(
switch (db.supaModelType) {
case "instruct35": {
console.log(
- "[HypaV3] Using openAI gpt-3.5-turbo-instruct for summarization"
+ "[HypaV3] Using openAI gpt-3.5-turbo-instruct for summarization."
);
const requestPrompt = `${stringifiedChats}\n\n${summarizePrompt}\n\nOutput:`;
@@ -165,7 +165,7 @@ export async function summarize(
}
case "subModel": {
- console.log(`[HypaV3] Using ax model ${db.subModel} for summarization`);
+ console.log(`[HypaV3] Using ax model ${db.subModel} for summarization.`);
const requestMessages: OpenAIChat[] = parseChatML(
summarizePrompt.replaceAll("{{slot}}", stringifiedChats)
@@ -190,14 +190,17 @@ export async function summarize(
"memory"
);
- if (
- response.type === "fail" ||
- response.type === "streaming" ||
- response.type === "multiline"
- ) {
+ if (response.type === "streaming" || response.type === "multiline") {
return {
success: false,
- data: "Unexpected response type",
+ data: "unexpected response type",
+ };
+ }
+
+ if (response.type === "fail") {
+ return {
+ success: false,
+ data: response.result,
};
}
@@ -207,7 +210,7 @@ export async function summarize(
default: {
return {
success: false,
- data: `Unsupported model ${db.supaModelType} for summarization`,
+ data: `unsupported model ${db.supaModelType} for summarization`,
};
}
}
@@ -298,10 +301,10 @@ export async function hypaMemoryV3(
if (shouldReserveEmptyMemoryTokens) {
currentTokens += emptyMemoryTokens;
- console.log("[HypaV3] Reserved empty memory tokens:", emptyMemoryTokens);
+ console.log("[HypaV3] Reserved empty memory tokens: ", emptyMemoryTokens);
} else {
currentTokens += memoryTokens;
- console.log("[HypaV3] Reserved max memory tokens:", memoryTokens);
+ console.log("[HypaV3] Reserved max memory tokens: ", memoryTokens);
}
// If summarization is needed
@@ -336,17 +339,17 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] Evaluating summarization batch:",
- "\nCurrent Tokens:",
+ "\nCurrent Tokens: ",
currentTokens,
- "\nMax Context Tokens:",
+ "\nMax Context Tokens: ",
maxContextTokens,
- "\nStart Index:",
+ "\nStart Index: ",
startIdx,
- "\nEnd Index:",
+ "\nEnd Index: ",
endIdx,
- "\nChat Count:",
+ "\nChat Count: ",
endIdx - startIdx,
- "\nMax Chats Per Summary:",
+ "\nMax Chats Per Summary: ",
db.hypaV3Settings.maxChatsPerSummary
);
@@ -356,13 +359,13 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] Evaluating chat:",
- "\nIndex:",
+ "\nIndex: ",
i,
- "\nRole:",
+ "\nRole: ",
chat.role,
"\nContent:\n",
chat.content,
- "\nTokens:",
+ "\nTokens: ",
chatTokens
);
@@ -387,7 +390,7 @@ export async function hypaMemoryV3(
currentTokens - toSummarizeTokens < targetTokens
) {
console.log(
- `[HypaV3] Stopping summarization: would reduce below target tokens (${currentTokens} - ${toSummarizeTokens} < ${targetTokens})`
+ `[HypaV3] Stopping summarization: currentTokens(${currentTokens}) - toSummarizeTokens(${toSummarizeTokens}) < targetTokens(${targetTokens})`
);
break;
}
@@ -401,23 +404,23 @@ export async function hypaMemoryV3(
while (summarizationFailures < maxSummarizationFailures) {
console.log(
"[HypaV3] Attempting summarization:",
- "\nAttempt:",
+ "\nAttempt: ",
summarizationFailures + 1,
- "\nTarget:",
+ "\nTarget: ",
toSummarize
);
const summarizeResult = await summarize(stringifiedChats);
if (!summarizeResult.success) {
- console.log("[HypaV3] Summarization failed:", summarizeResult.data);
+ console.log("[HypaV3] Summarization failed: ", summarizeResult.data);
summarizationFailures++;
if (summarizationFailures >= maxSummarizationFailures) {
return {
currentTokens,
chats,
- error: "[HypaV3] Summarization failed after maximum retries",
+ error: `[HypaV3] Summarization failed after maximum retries: ${summarizeResult.data}`,
memory: toSerializableHypaV3Data(data),
};
}
@@ -442,11 +445,11 @@ export async function hypaMemoryV3(
`[HypaV3] ${
summarizationMode ? "Completed" : "Skipped"
} summarization phase:`,
- "\nCurrent Tokens:",
+ "\nCurrent Tokens: ",
currentTokens,
- "\nMax Context Tokens:",
+ "\nMax Context Tokens: ",
maxContextTokens,
- "\nAvailable Memory Tokens:",
+ "\nAvailable Memory Tokens: ",
availableMemoryTokens
);
@@ -480,11 +483,11 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] After important memory selection:",
- "\nSummary Count:",
+ "\nSummary Count: ",
selectedImportantSummaries.length,
- "\nSummaries:",
+ "\nSummaries: ",
selectedImportantSummaries,
- "\nAvailable Memory Tokens:",
+ "\nAvailable Memory Tokens: ",
availableMemoryTokens
);
@@ -525,13 +528,13 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] After recent memory selection:",
- "\nSummary Count:",
+ "\nSummary Count: ",
selectedRecentSummaries.length,
- "\nSummaries:",
+ "\nSummaries: ",
selectedRecentSummaries,
- "\nReserved Recent Memory Tokens:",
+ "\nReserved Recent Memory Tokens: ",
reservedRecentMemoryTokens,
- "\nConsumed Recent Memory Tokens:",
+ "\nConsumed Recent Memory Tokens: ",
consumedRecentMemoryTokens
);
}
@@ -553,7 +556,7 @@ export async function hypaMemoryV3(
reservedSimilarMemoryTokens += unusedRecentTokens;
console.log(
"[HypaV3] Additional available token space for similar memory:",
- "\nFrom recent:",
+ "\nFrom recent: ",
unusedRecentTokens
);
}
@@ -617,23 +620,23 @@ export async function hypaMemoryV3(
while (summarizationFailures < maxSummarizationFailures) {
console.log(
"[HypaV3] Attempting summarization:",
- "\nAttempt:",
+ "\nAttempt: ",
summarizationFailures + 1,
- "\nTarget:",
+ "\nTarget: ",
recentChats
);
const summarizeResult = await summarize(stringifiedRecentChats);
if (!summarizeResult.success) {
- console.log("[HypaV3] Summarization failed:", summarizeResult.data);
+ console.log("[HypaV3] Summarization failed: ", summarizeResult.data);
summarizationFailures++;
if (summarizationFailures >= maxSummarizationFailures) {
return {
currentTokens,
chats,
- error: "[HypaV3] Summarization failed after maximum retries",
+ error: `[HypaV3] Summarization failed after maximum retries: ${summarizeResult.data}`,
memory: toSerializableHypaV3Data(data),
};
}
@@ -654,7 +657,7 @@ export async function hypaMemoryV3(
);
}
- console.log("[HypaV3] Similarity corrected");
+ console.log("[HypaV3] Similarity corrected.");
break;
}
@@ -675,11 +678,13 @@ export async function hypaMemoryV3(
/*
console.log(
"[HypaV3] Trying to add similar summary:",
- "\nSummary Tokens:",
+ "\nSummary Tokens: ",
summaryTokens,
- "\nReserved Tokens:",
+ "\nConsumed Similar Memory Tokens: ",
+ consumedSimilarMemoryTokens,
+ "\nReserved Tokens: ",
reservedSimilarMemoryTokens,
- "\nWould exceed:",
+ "\nWould exceed: ",
summaryTokens + consumedSimilarMemoryTokens > reservedSimilarMemoryTokens
);
*/
@@ -689,7 +694,7 @@ export async function hypaMemoryV3(
reservedSimilarMemoryTokens
) {
console.log(
- `[HypaV3] Stopping similar memory selection: would exceed reserved tokens (${consumedSimilarMemoryTokens} + ${summaryTokens} > ${reservedSimilarMemoryTokens})`
+ `[HypaV3] Stopping similar memory selection: consumedSimilarMemoryTokens(${consumedSimilarMemoryTokens}) + summaryTokens(${summaryTokens}) > reservedSimilarMemoryTokens(${reservedSimilarMemoryTokens})`
);
break;
}
@@ -702,13 +707,13 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] After similar memory selection:",
- "\nSummary Count:",
+ "\nSummary Count: ",
selectedSimilarSummaries.length,
- "\nSummaries:",
+ "\nSummaries: ",
selectedSimilarSummaries,
- "\nReserved Similar Memory Tokens:",
+ "\nReserved Similar Memory Tokens: ",
reservedSimilarMemoryTokens,
- "\nConsumed Similar Memory Tokens:",
+ "\nConsumed Similar Memory Tokens: ",
consumedSimilarMemoryTokens
);
}
@@ -731,11 +736,11 @@ export async function hypaMemoryV3(
reservedRandomMemoryTokens += unusedRecentTokens + unusedSimilarTokens;
console.log(
"[HypaV3] Additional available token space for random memory:",
- "\nFrom recent:",
+ "\nFrom recent: ",
unusedRecentTokens,
- "\nFrom similar:",
+ "\nFrom similar: ",
unusedSimilarTokens,
- "\nTotal added:",
+ "\nTotal added: ",
unusedRecentTokens + unusedSimilarTokens
);
@@ -766,13 +771,13 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] After random memory selection:",
- "\nSummary Count:",
+ "\nSummary Count: ",
selectedRandomSummaries.length,
- "\nSummaries:",
+ "\nSummaries: ",
selectedRandomSummaries,
- "\nReserved Random Memory Tokens:",
+ "\nReserved Random Memory Tokens: ",
reservedRandomMemoryTokens,
- "\nConsumed Random Memory Tokens:",
+ "\nConsumed Random Memory Tokens: ",
consumedRandomMemoryTokens
);
}
@@ -802,19 +807,19 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] Final memory selection:",
- "\nSummary Count:",
+ "\nSummary Count: ",
selectedSummaries.length,
- "\nSummaries:",
+ "\nSummaries: ",
selectedSummaries,
- "\nReal Memory Tokens:",
+ "\nReal Memory Tokens: ",
realMemoryTokens,
- "\nAvailable Memory Tokens:",
+ "\nAvailable Memory Tokens: ",
availableMemoryTokens
);
if (currentTokens > maxContextTokens) {
throw new Error(
- `[HypaV3] Unexpected input token count:\nCurrent Tokens:${currentTokens}\nMax Context Tokens:${maxContextTokens}`
+ `[HypaV3] Unexpected error: input token count (${currentTokens}) exceeds max context size (${maxContextTokens})`
);
}
@@ -829,11 +834,11 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] Exiting function:",
- "\nCurrent Tokens:",
+ "\nCurrent Tokens: ",
currentTokens,
- "\nAll chats, including memory prompt:",
+ "\nAll chats, including memory prompt: ",
newChats,
- "\nMemory Data:",
+ "\nMemory Data: ",
data
);
From 6a13b33103f9c6eac073e4ef5f25b5665bce9da2 Mon Sep 17 00:00:00 2001
From: Bo26fhmC5M <88071760+Bo26fhmC5M@users.noreply.github.com>
Date: Thu, 16 Jan 2025 23:36:32 +0900
Subject: [PATCH 08/11] refactor: extract repeated summarization logic into
retryableSummarize function
---
src/lib/Others/HypaV3Modal.svelte | 14 +--
src/ts/process/memory/hypav3.ts | 166 ++++++++++++++----------------
2 files changed, 84 insertions(+), 96 deletions(-)
diff --git a/src/lib/Others/HypaV3Modal.svelte b/src/lib/Others/HypaV3Modal.svelte
index 8f2e1f11..0970e4e9 100644
--- a/src/lib/Others/HypaV3Modal.svelte
+++ b/src/lib/Others/HypaV3Modal.svelte
@@ -11,6 +11,7 @@
import { alertConfirm, showHypaV3Alert } from "../../ts/alert";
import { DBState, alertStore, selectedCharID } from "src/ts/stores.svelte";
import { summarize } from "src/ts/process/memory/hypav3";
+ import { type OpenAIChat } from "src/ts/process/index.svelte";
import { translateHTML } from "src/ts/translator/translator";
interface SummaryUI {
@@ -131,19 +132,18 @@
try {
const summary = hypaV3DataState.summaries[summaryIndex];
- const toSummarize = summary.chatMemos.map((chatMemo) => {
+ const toSummarize: OpenAIChat[] = summary.chatMemos.map((chatMemo) => {
const message = getMessageFromChatMemo(chatMemo);
return {
- ...message,
- role: message.role === "char" ? "assistant" : message.role,
+ role: (message.role === "char"
+ ? "assistant"
+ : message.role) as OpenAIChat["role"],
+ content: message.data,
};
});
- const stringifiedChats = toSummarize
- .map((m) => `${m.role}: ${m.data}`)
- .join("\n");
- const summarizeResult = await summarize(stringifiedChats);
+ const summarizeResult = await summarize(toSummarize);
if (summarizeResult.success) {
summaryUIState.rerolledText = summarizeResult.data;
diff --git a/src/ts/process/memory/hypav3.ts b/src/ts/process/memory/hypav3.ts
index 7495c74f..c2fabf58 100644
--- a/src/ts/process/memory/hypav3.ts
+++ b/src/ts/process/memory/hypav3.ts
@@ -39,6 +39,10 @@ interface SummaryChunk {
summary: Summary;
}
+const minChatsForSimilarity = 3;
+const maxSummarizationFailures = 3;
+const summarySeparator = "\n\n";
+
// Helper function to check if one Set is a subset of another
function isSubset(subset: Set, superset: Set): boolean {
for (const elem of subset) {
@@ -92,9 +96,12 @@ function cleanOrphanedSummary(chats: OpenAIChat[], data: HypaV3Data): void {
}
export async function summarize(
- stringifiedChats: string
+ oaiChats: OpenAIChat[]
): Promise<{ success: boolean; data: string }> {
const db = getDatabase();
+ const stringifiedChats = oaiChats
+ .map((chat) => `${chat.role}: ${chat.content}`)
+ .join("\n");
if (db.supaModelType === "distilbart") {
try {
@@ -216,6 +223,37 @@ export async function summarize(
}
}
+async function retryableSummarize(
+ oaiChats: OpenAIChat[]
+): Promise<{ success: boolean; data: string }> {
+ let summarizationFailures = 0;
+
+ while (summarizationFailures < maxSummarizationFailures) {
+ console.log(
+ "[HypaV3] Attempting summarization:",
+ "\nAttempt: ",
+ summarizationFailures + 1,
+ "\nTarget: ",
+ oaiChats
+ );
+
+ const summarizeResult = await summarize(oaiChats);
+
+ if (!summarizeResult.success) {
+ console.log("[HypaV3] Summarization failed: ", summarizeResult.data);
+ summarizationFailures++;
+
+ if (summarizationFailures >= maxSummarizationFailures) {
+ return summarizeResult;
+ }
+
+ continue;
+ }
+
+ return summarizeResult;
+ }
+}
+
export async function hypaMemoryV3(
chats: OpenAIChat[],
currentTokens: number,
@@ -229,9 +267,6 @@ export async function hypaMemoryV3(
error?: string;
memory?: SerializableHypaV3Data;
}> {
- const minChatsForSimilarity = 3;
- const maxSummarizationFailures = 3;
- const summarySeparator = "\n\n";
const db = getDatabase();
// Validate settings
@@ -396,47 +431,23 @@ export async function hypaMemoryV3(
}
// Attempt summarization
- let summarizationFailures = 0;
- const stringifiedChats = toSummarize
- .map((chat) => `${chat.role}: ${chat.content}`)
- .join("\n");
+ const summarizeResult = await retryableSummarize(toSummarize);
- while (summarizationFailures < maxSummarizationFailures) {
- console.log(
- "[HypaV3] Attempting summarization:",
- "\nAttempt: ",
- summarizationFailures + 1,
- "\nTarget: ",
- toSummarize
- );
-
- const summarizeResult = await summarize(stringifiedChats);
-
- if (!summarizeResult.success) {
- console.log("[HypaV3] Summarization failed: ", summarizeResult.data);
- summarizationFailures++;
-
- if (summarizationFailures >= maxSummarizationFailures) {
- return {
- currentTokens,
- chats,
- error: `[HypaV3] Summarization failed after maximum retries: ${summarizeResult.data}`,
- memory: toSerializableHypaV3Data(data),
- };
- }
-
- continue;
- }
-
- data.summaries.push({
- text: summarizeResult.data,
- chatMemos: new Set(toSummarize.map((chat) => chat.memo)),
- isImportant: false,
- });
-
- break;
+ if (!summarizeResult.success) {
+ return {
+ currentTokens,
+ chats,
+ error: `[HypaV3] Summarization failed after maximum retries: ${summarizeResult.data}`,
+ memory: toSerializableHypaV3Data(data),
+ };
}
+ data.summaries.push({
+ text: summarizeResult.data,
+ chatMemos: new Set(toSummarize.map((chat) => chat.memo)),
+ isImportant: false,
+ });
+
currentTokens -= toSummarizeTokens;
startIdx = endIdx;
}
@@ -611,56 +622,33 @@ export async function hypaMemoryV3(
// (2) Summarized recent chat search
if (db.hypaV3Settings.enableSimilarityCorrection) {
- let summarizationFailures = 0;
+ // Attempt summarization
const recentChats = chats.slice(-minChatsForSimilarity);
- const stringifiedRecentChats = recentChats
- .map((chat) => `${chat.role}: ${chat.content}`)
- .join("\n");
+ const summarizeResult = await retryableSummarize(recentChats);
- while (summarizationFailures < maxSummarizationFailures) {
- console.log(
- "[HypaV3] Attempting summarization:",
- "\nAttempt: ",
- summarizationFailures + 1,
- "\nTarget: ",
- recentChats
- );
-
- const summarizeResult = await summarize(stringifiedRecentChats);
-
- if (!summarizeResult.success) {
- console.log("[HypaV3] Summarization failed: ", summarizeResult.data);
- summarizationFailures++;
-
- if (summarizationFailures >= maxSummarizationFailures) {
- return {
- currentTokens,
- chats,
- error: `[HypaV3] Summarization failed after maximum retries: ${summarizeResult.data}`,
- memory: toSerializableHypaV3Data(data),
- };
- }
-
- continue;
- }
-
- const searched = await processor.similaritySearchScoredEx(
- summarizeResult.data
- );
-
- for (const [chunk, similarity] of searched) {
- const summary = chunk.summary;
-
- scoredSummaries.set(
- summary,
- (scoredSummaries.get(summary) || 0) + similarity
- );
- }
-
- console.log("[HypaV3] Similarity corrected.");
-
- break;
+ if (!summarizeResult.success) {
+ return {
+ currentTokens,
+ chats,
+ error: `[HypaV3] Summarization failed after maximum retries: ${summarizeResult.data}`,
+ memory: toSerializableHypaV3Data(data),
+ };
}
+
+ const searched = await processor.similaritySearchScoredEx(
+ summarizeResult.data
+ );
+
+ for (const [chunk, similarity] of searched) {
+ const summary = chunk.summary;
+
+ scoredSummaries.set(
+ summary,
+ (scoredSummaries.get(summary) || 0) + similarity
+ );
+ }
+
+ console.log("[HypaV3] Similarity corrected.");
}
// Sort in descending order
From 3c62317f3a129a0396c12f8a1d771714e32a71cd Mon Sep 17 00:00:00 2001
From: Bo26fhmC5M <88071760+Bo26fhmC5M@users.noreply.github.com>
Date: Fri, 17 Jan 2025 00:17:12 +0900
Subject: [PATCH 09/11] feat: add lastSelectedSummaries property to store
selected memory indices
---
src/lib/Others/HypaV3Modal.svelte | 1 +
src/lib/SideBars/CharConfig.svelte | 1 +
src/ts/process/memory/hypav3.ts | 108 ++++++++++++++++-------------
3 files changed, 61 insertions(+), 49 deletions(-)
diff --git a/src/lib/Others/HypaV3Modal.svelte b/src/lib/Others/HypaV3Modal.svelte
index 0970e4e9..77cc034e 100644
--- a/src/lib/Others/HypaV3Modal.svelte
+++ b/src/lib/Others/HypaV3Modal.svelte
@@ -332,6 +332,7 @@
DBState.db.characters[$selectedCharID].chatPage
].hypaV3Data = {
summaries: [],
+ lastSelectedSummaries: [],
};
} else {
showHypaV3Alert();
diff --git a/src/lib/SideBars/CharConfig.svelte b/src/lib/SideBars/CharConfig.svelte
index fccb78db..93a4c98a 100644
--- a/src/lib/SideBars/CharConfig.svelte
+++ b/src/lib/SideBars/CharConfig.svelte
@@ -1113,6 +1113,7 @@
onclick={() => {
DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].hypaV3Data ??= {
summaries: [],
+ lastSelectedSummaries: [],
}
showHypaV3Alert()
}}
diff --git a/src/ts/process/memory/hypav3.ts b/src/ts/process/memory/hypav3.ts
index c2fabf58..91bef8d6 100644
--- a/src/ts/process/memory/hypav3.ts
+++ b/src/ts/process/memory/hypav3.ts
@@ -24,6 +24,7 @@ interface Summary {
interface HypaV3Data {
summaries: Summary[];
+ lastSelectedSummaries?: number[];
}
export interface SerializableHypaV3Data {
@@ -32,6 +33,7 @@ export interface SerializableHypaV3Data {
chatMemos: string[];
isImportant: boolean;
}[];
+ lastSelectedSummaries?: number[];
}
interface SummaryChunk {
@@ -55,6 +57,7 @@ function isSubset(subset: Set, superset: Set): boolean {
function toSerializableHypaV3Data(data: HypaV3Data): SerializableHypaV3Data {
return {
+ ...data,
summaries: data.summaries.map((summary) => ({
...summary,
chatMemos: [...summary.chatMemos],
@@ -64,6 +67,7 @@ function toSerializableHypaV3Data(data: HypaV3Data): SerializableHypaV3Data {
function toHypaV3Data(serialData: SerializableHypaV3Data): HypaV3Data {
return {
+ ...serialData,
summaries: serialData.summaries.map((summary) => ({
...summary,
// Convert null back to undefined (JSON serialization converts undefined to null)
@@ -231,16 +235,16 @@ async function retryableSummarize(
while (summarizationFailures < maxSummarizationFailures) {
console.log(
"[HypaV3] Attempting summarization:",
- "\nAttempt: ",
+ "\nAttempt:",
summarizationFailures + 1,
- "\nTarget: ",
+ "\nTarget:",
oaiChats
);
const summarizeResult = await summarize(oaiChats);
if (!summarizeResult.success) {
- console.log("[HypaV3] Summarization failed: ", summarizeResult.data);
+ console.log("[HypaV3] Summarization failed:", summarizeResult.data);
summarizationFailures++;
if (summarizationFailures >= maxSummarizationFailures) {
@@ -288,6 +292,7 @@ export async function hypaMemoryV3(
// Load existing hypa data if available
let data: HypaV3Data = {
summaries: [],
+ lastSelectedSummaries: [],
};
if (room.hypaV3Data) {
@@ -336,10 +341,10 @@ export async function hypaMemoryV3(
if (shouldReserveEmptyMemoryTokens) {
currentTokens += emptyMemoryTokens;
- console.log("[HypaV3] Reserved empty memory tokens: ", emptyMemoryTokens);
+ console.log("[HypaV3] Reserved empty memory tokens:", emptyMemoryTokens);
} else {
currentTokens += memoryTokens;
- console.log("[HypaV3] Reserved max memory tokens: ", memoryTokens);
+ console.log("[HypaV3] Reserved max memory tokens:", memoryTokens);
}
// If summarization is needed
@@ -374,17 +379,17 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] Evaluating summarization batch:",
- "\nCurrent Tokens: ",
+ "\nCurrent Tokens:",
currentTokens,
- "\nMax Context Tokens: ",
+ "\nMax Context Tokens:",
maxContextTokens,
- "\nStart Index: ",
+ "\nStart Index:",
startIdx,
- "\nEnd Index: ",
+ "\nEnd Index:",
endIdx,
- "\nChat Count: ",
+ "\nChat Count:",
endIdx - startIdx,
- "\nMax Chats Per Summary: ",
+ "\nMax Chats Per Summary:",
db.hypaV3Settings.maxChatsPerSummary
);
@@ -394,13 +399,13 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] Evaluating chat:",
- "\nIndex: ",
+ "\nIndex:",
i,
- "\nRole: ",
+ "\nRole:",
chat.role,
- "\nContent:\n",
- chat.content,
- "\nTokens: ",
+ "\nContent:",
+ "\n" + chat.content,
+ "\nTokens:",
chatTokens
);
@@ -456,11 +461,11 @@ export async function hypaMemoryV3(
`[HypaV3] ${
summarizationMode ? "Completed" : "Skipped"
} summarization phase:`,
- "\nCurrent Tokens: ",
+ "\nCurrent Tokens:",
currentTokens,
- "\nMax Context Tokens: ",
+ "\nMax Context Tokens:",
maxContextTokens,
- "\nAvailable Memory Tokens: ",
+ "\nAvailable Memory Tokens:",
availableMemoryTokens
);
@@ -494,11 +499,11 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] After important memory selection:",
- "\nSummary Count: ",
+ "\nSummary Count:",
selectedImportantSummaries.length,
- "\nSummaries: ",
+ "\nSummaries:",
selectedImportantSummaries,
- "\nAvailable Memory Tokens: ",
+ "\nAvailable Memory Tokens:",
availableMemoryTokens
);
@@ -539,13 +544,13 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] After recent memory selection:",
- "\nSummary Count: ",
+ "\nSummary Count:",
selectedRecentSummaries.length,
- "\nSummaries: ",
+ "\nSummaries:",
selectedRecentSummaries,
- "\nReserved Recent Memory Tokens: ",
+ "\nReserved Tokens:",
reservedRecentMemoryTokens,
- "\nConsumed Recent Memory Tokens: ",
+ "\nConsumed Tokens:",
consumedRecentMemoryTokens
);
}
@@ -567,7 +572,7 @@ export async function hypaMemoryV3(
reservedSimilarMemoryTokens += unusedRecentTokens;
console.log(
"[HypaV3] Additional available token space for similar memory:",
- "\nFrom recent: ",
+ "\nFrom recent:",
unusedRecentTokens
);
}
@@ -666,13 +671,13 @@ export async function hypaMemoryV3(
/*
console.log(
"[HypaV3] Trying to add similar summary:",
- "\nSummary Tokens: ",
+ "\nSummary Tokens:",
summaryTokens,
- "\nConsumed Similar Memory Tokens: ",
+ "\nConsumed Similar Memory Tokens:",
consumedSimilarMemoryTokens,
- "\nReserved Tokens: ",
+ "\nReserved Tokens:",
reservedSimilarMemoryTokens,
- "\nWould exceed: ",
+ "\nWould exceed:",
summaryTokens + consumedSimilarMemoryTokens > reservedSimilarMemoryTokens
);
*/
@@ -695,13 +700,13 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] After similar memory selection:",
- "\nSummary Count: ",
+ "\nSummary Count:",
selectedSimilarSummaries.length,
- "\nSummaries: ",
+ "\nSummaries:",
selectedSimilarSummaries,
- "\nReserved Similar Memory Tokens: ",
+ "\nReserved Tokens:",
reservedSimilarMemoryTokens,
- "\nConsumed Similar Memory Tokens: ",
+ "\nConsumed Tokens:",
consumedSimilarMemoryTokens
);
}
@@ -724,11 +729,11 @@ export async function hypaMemoryV3(
reservedRandomMemoryTokens += unusedRecentTokens + unusedSimilarTokens;
console.log(
"[HypaV3] Additional available token space for random memory:",
- "\nFrom recent: ",
+ "\nFrom recent:",
unusedRecentTokens,
- "\nFrom similar: ",
+ "\nFrom similar:",
unusedSimilarTokens,
- "\nTotal added: ",
+ "\nTotal added:",
unusedRecentTokens + unusedSimilarTokens
);
@@ -759,13 +764,13 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] After random memory selection:",
- "\nSummary Count: ",
+ "\nSummary Count:",
selectedRandomSummaries.length,
- "\nSummaries: ",
+ "\nSummaries:",
selectedRandomSummaries,
- "\nReserved Random Memory Tokens: ",
+ "\nReserved Tokens:",
reservedRandomMemoryTokens,
- "\nConsumed Random Memory Tokens: ",
+ "\nConsumed Tokens:",
consumedRandomMemoryTokens
);
}
@@ -795,13 +800,13 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] Final memory selection:",
- "\nSummary Count: ",
+ "\nSummary Count:",
selectedSummaries.length,
- "\nSummaries: ",
+ "\nSummaries:",
selectedSummaries,
- "\nReal Memory Tokens: ",
+ "\nReal Memory Tokens:",
realMemoryTokens,
- "\nAvailable Memory Tokens: ",
+ "\nAvailable Memory Tokens:",
availableMemoryTokens
);
@@ -811,6 +816,11 @@ export async function hypaMemoryV3(
);
}
+ // Save last selected summaries
+ data.lastSelectedSummaries = selectedSummaries.map((selectedSummary) =>
+ data.summaries.findIndex((summary) => summary === selectedSummary)
+ );
+
const newChats: OpenAIChat[] = [
{
role: "system",
@@ -822,11 +832,11 @@ export async function hypaMemoryV3(
console.log(
"[HypaV3] Exiting function:",
- "\nCurrent Tokens: ",
+ "\nCurrent Tokens:",
currentTokens,
- "\nAll chats, including memory prompt: ",
+ "\nAll chats, including memory prompt:",
newChats,
- "\nMemory Data: ",
+ "\nMemory Data:",
data
);
From 171b267891c9255236e43a32243815f9cfa6a3a8 Mon Sep 17 00:00:00 2001
From: Bo26fhmC5M <88071760+Bo26fhmC5M@users.noreply.github.com>
Date: Fri, 17 Jan 2025 02:22:46 +0900
Subject: [PATCH 10/11] feat: display next message to be summarized in HypaV3
modal
---
src/lib/Others/HypaV3Modal.svelte | 61 +++++++++++++++++++++++++++----
1 file changed, 53 insertions(+), 8 deletions(-)
diff --git a/src/lib/Others/HypaV3Modal.svelte b/src/lib/Others/HypaV3Modal.svelte
index 77cc034e..717f6fd5 100644
--- a/src/lib/Others/HypaV3Modal.svelte
+++ b/src/lib/Others/HypaV3Modal.svelte
@@ -12,6 +12,7 @@
import { DBState, alertStore, selectedCharID } from "src/ts/stores.svelte";
import { summarize } from "src/ts/process/memory/hypav3";
import { type OpenAIChat } from "src/ts/process/index.svelte";
+ import { type Message } from "src/ts/storage/database.svelte";
import { translateHTML } from "src/ts/translator/translator";
interface SummaryUI {
@@ -61,9 +62,7 @@
);
}
- function getMessageFromChatMemo(
- chatMemo: string | null
- ): { role: string; data: string } | null {
+ function getMessageFromChatMemo(chatMemo: string | null): Message | null {
const char = DBState.db.characters[$selectedCharID];
const chat = char.chats[DBState.db.characters[$selectedCharID].chatPage];
const firstMessage =
@@ -71,10 +70,11 @@
? char.firstMessage
: char.alternateGreetings?.[chat.fmIndex ?? 0];
- const targetMessage =
+ const targetMessage = (
chatMemo == null
? { role: "char", data: firstMessage }
- : chat.message.find((m) => m.chatId === chatMemo);
+ : chat.message.find((m) => m.chatId === chatMemo)
+ ) as Message;
return targetMessage;
}
@@ -232,6 +232,36 @@
};
}
+ function getNextMessageToSummarize(): Message {
+ 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];
+
+ if (hypaV3DataState.summaries.length > 0) {
+ const lastSummary = hypaV3DataState.summaries.at(-1);
+ const lastMessageIndex = chat.message.findIndex(
+ (msg) => msg.chatId === lastSummary.chatMemos.at(-1)
+ );
+
+ if (lastMessageIndex !== -1) {
+ const nextMessage = chat.message[lastMessageIndex + 1];
+
+ if (nextMessage) {
+ return nextMessage;
+ }
+ }
+ }
+
+ if (firstMessage?.trim() === "") {
+ return chat.message[0];
+ }
+
+ return { role: "char", chatId: "first message", data: firstMessage };
+ }
+
async function translate(
text: string,
regenerate?: boolean
@@ -311,7 +341,7 @@
@@ -359,6 +389,10 @@
+ {#if hypaV3DataState.summaries.length === 0}
+
No summaries yet
+ {/if}
+
{#each hypaV3DataState.summaries as summary, i}
{#if summaryUIStates[i]}
No summaries yet
+ {#if true}
+
+ {@const nextMessage = getNextMessageToSummarize()}
+
+
+ HypaV3 will summarize {nextMessage.chatId}
+
+
+ {nextMessage.data}
+
+
{/if}
From b43eec49d11d650544ad19091bd2cec60518b4a0 Mon Sep 17 00:00:00 2001
From: Bo26fhmC5M <88071760+Bo26fhmC5M@users.noreply.github.com>
Date: Fri, 17 Jan 2025 09:03:23 +0900
Subject: [PATCH 11/11] fix: handle empty message edge cases in
getNextMessageToSummarize
---
src/lib/Others/HypaV3Modal.svelte | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/src/lib/Others/HypaV3Modal.svelte b/src/lib/Others/HypaV3Modal.svelte
index 717f6fd5..3ac09afd 100644
--- a/src/lib/Others/HypaV3Modal.svelte
+++ b/src/lib/Others/HypaV3Modal.svelte
@@ -232,7 +232,7 @@
};
}
- function getNextMessageToSummarize(): Message {
+ function getNextMessageToSummarize(): Message | null {
const char = DBState.db.characters[$selectedCharID];
const chat = char.chats[DBState.db.characters[$selectedCharID].chatPage];
const firstMessage =
@@ -256,7 +256,11 @@
}
if (firstMessage?.trim() === "") {
- return chat.message[0];
+ if (chat.message.length > 0) {
+ return chat.message[0];
+ }
+
+ return null;
}
return { role: "char", chatId: "first message", data: firstMessage };
@@ -601,16 +605,18 @@
{#if true}
{@const nextMessage = getNextMessageToSummarize()}
-
-
- HypaV3 will summarize {nextMessage.chatId}
-
-
- {nextMessage.data}
+ {#if nextMessage}
+
+
+ HypaV3 will summarize [{nextMessage.chatId}]
+
+
+ {nextMessage.data}
+
-
+ {/if}
{/if}