Improve L0 extraction flow and recall robustness
This commit is contained in:
@@ -526,6 +526,52 @@ async function handleClearVectors() {
|
||||
xbLog.info(MODULE_ID, "向量数据已清除");
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// L0 自动补提取(每收到新消息后检查并补提取缺失楼层)
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
async function maybeAutoExtractL0() {
|
||||
const vectorCfg = getVectorConfig();
|
||||
if (!vectorCfg?.enabled) return;
|
||||
if (anchorGenerating || vectorGenerating) return;
|
||||
|
||||
const { chatId, chat } = getContext();
|
||||
if (!chatId || !chat?.length) return;
|
||||
|
||||
const stats = await getAnchorStats();
|
||||
if (stats.pending <= 0) return;
|
||||
|
||||
anchorGenerating = true;
|
||||
|
||||
try {
|
||||
await incrementalExtractAtoms(chatId, chat, null, { maxFloors: 20 });
|
||||
|
||||
// 为新提取的 L0 楼层构建 L1 chunks
|
||||
await buildIncrementalChunks({ vectorConfig: vectorCfg });
|
||||
|
||||
invalidateLexicalIndex();
|
||||
|
||||
await sendAnchorStatsToFrame();
|
||||
await sendVectorStatsToFrame();
|
||||
|
||||
xbLog.info(MODULE_ID, "自动 L0 补提取完成");
|
||||
} catch (e) {
|
||||
xbLog.error(MODULE_ID, "自动 L0 补提取失败", e);
|
||||
} finally {
|
||||
anchorGenerating = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// Embedding 连接预热
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
function warmupEmbeddingConnection() {
|
||||
const vectorCfg = getVectorConfig();
|
||||
if (!vectorCfg?.enabled) return;
|
||||
embed(['.'], vectorCfg, { timeout: 5000 }).catch(() => {});
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// 实体词典注入 + 索引预热
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
@@ -1284,6 +1330,9 @@ async function handleChatChanged() {
|
||||
// 实体词典注入 + 索引预热
|
||||
refreshEntityLexiconAndWarmup();
|
||||
|
||||
// Embedding 连接预热(保持 TCP keep-alive,减少首次召回超时)
|
||||
warmupEmbeddingConnection();
|
||||
|
||||
setTimeout(() => checkVectorIntegrityAndWarn(), 2000);
|
||||
}
|
||||
|
||||
@@ -1316,7 +1365,10 @@ async function handleMessageReceived() {
|
||||
// 向量全量生成中时跳过 L1 sync(避免竞争写入)
|
||||
if (vectorGenerating) return;
|
||||
|
||||
await syncOnMessageReceived(chatId, lastFloor, message, vectorConfig);
|
||||
await syncOnMessageReceived(chatId, lastFloor, message, vectorConfig, () => {
|
||||
sendAnchorStatsToFrame();
|
||||
sendVectorStatsToFrame();
|
||||
});
|
||||
await maybeAutoBuildChunks();
|
||||
|
||||
applyHideStateDebounced();
|
||||
@@ -1324,6 +1376,9 @@ async function handleMessageReceived() {
|
||||
|
||||
// 新消息后刷新实体词典(可能有新角色)
|
||||
refreshEntityLexiconAndWarmup();
|
||||
|
||||
// 自动补提取缺失的 L0(延迟执行,避免与当前楼提取竞争)
|
||||
setTimeout(() => maybeAutoExtractL0(), 2000);
|
||||
}
|
||||
|
||||
function handleMessageSent() {
|
||||
|
||||
Reference in New Issue
Block a user