refactor: extract repeated summarization logic into retryableSummarize function

This commit is contained in:
Bo26fhmC5M
2025-01-16 23:36:32 +09:00
parent fac11bfe67
commit 6a13b33103
2 changed files with 84 additions and 96 deletions

View File

@@ -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;

View File

@@ -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<string>, superset: Set<string>): 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