Improve L0 extraction flow and recall robustness

This commit is contained in:
2026-02-10 12:43:43 +08:00
parent 3af76a9651
commit 1fe0647462
5 changed files with 370 additions and 120 deletions

View File

@@ -334,7 +334,7 @@ export async function syncOnMessageSwiped(chatId, lastFloor) {
/**
* 新消息后同步:删除 + 重建最后楼层
*/
export async function syncOnMessageReceived(chatId, lastFloor, message, vectorConfig) {
export async function syncOnMessageReceived(chatId, lastFloor, message, vectorConfig, onL0Complete) {
if (!chatId || lastFloor < 0 || !message) return;
if (!vectorConfig?.enabled) return;
@@ -368,11 +368,10 @@ export async function syncOnMessageReceived(chatId, lastFloor, message, vectorCo
const userMessage = (userFloor >= 0 && chat[userFloor]?.is_user) ? chat[userFloor] : null;
try {
await extractAndStoreAtomsForRound(lastFloor, message, userMessage);
await extractAndStoreAtomsForRound(lastFloor, message, userMessage, onL0Complete);
} catch (e) {
xbLog.warn(MODULE_ID, `Atom 提取失败: floor ${lastFloor}`, e);
}
}
}

View File

@@ -112,7 +112,8 @@ function buildL0InputText(userMessage, aiMessage) {
return parts.join('\n\n---\n\n').trim();
}
export async function incrementalExtractAtoms(chatId, chat, onProgress) {
export async function incrementalExtractAtoms(chatId, chat, onProgress, options = {}) {
const { maxFloors = Infinity } = options;
if (!chatId || !chat?.length) return { built: 0 };
const vectorCfg = getVectorConfig();
@@ -144,6 +145,11 @@ export async function incrementalExtractAtoms(chatId, chat, onProgress) {
pendingPairs.push({ userMsg, aiMsg: msg, aiFloor: i });
}
// 限制单次提取楼层数(自动触发时使用)
if (pendingPairs.length > maxFloors) {
pendingPairs.length = maxFloors;
}
if (!pendingPairs.length) {
onProgress?.('已全部提取', 0, 0);
return { built: 0 };
@@ -323,14 +329,14 @@ export async function clearAllAtomsAndVectors(chatId) {
let extractionQueue = [];
let isProcessing = false;
export async function extractAndStoreAtomsForRound(aiFloor, aiMessage, userMessage) {
export async function extractAndStoreAtomsForRound(aiFloor, aiMessage, userMessage, onComplete) {
const { chatId } = getContext();
if (!chatId) return;
const vectorCfg = getVectorConfig();
if (!vectorCfg?.enabled) return;
extractionQueue.push({ aiFloor, aiMessage, userMessage, chatId });
extractionQueue.push({ aiFloor, aiMessage, userMessage, chatId, onComplete });
processQueue();
}
@@ -339,13 +345,14 @@ async function processQueue() {
isProcessing = true;
while (extractionQueue.length > 0) {
const { aiFloor, aiMessage, userMessage, chatId } = extractionQueue.shift();
const { aiFloor, aiMessage, userMessage, chatId, onComplete } = extractionQueue.shift();
try {
const atoms = await extractAtomsForRound(userMessage, aiMessage, aiFloor, { timeout: 12000 });
if (!atoms?.length) {
xbLog.info(MODULE_ID, `floor ${aiFloor}: 无有效 atoms`);
onComplete?.({ floor: aiFloor, atomCount: 0 });
continue;
}
@@ -356,8 +363,10 @@ async function processQueue() {
await vectorizeAtomsSimple(chatId, atoms);
xbLog.info(MODULE_ID, `floor ${aiFloor}: ${atoms.length} atoms 已存储`);
onComplete?.({ floor: aiFloor, atomCount: atoms.length });
} catch (e) {
xbLog.error(MODULE_ID, `floor ${aiFloor} 处理失败`, e);
onComplete?.({ floor: aiFloor, atomCount: 0, error: e });
}
}