Zero-darkbox query updates and tokenizer improvements

This commit is contained in:
2026-02-09 20:25:26 +08:00
parent 8131d6a15f
commit 0a28539b29
14 changed files with 1771 additions and 175 deletions

View File

@@ -44,6 +44,12 @@ import { runSummaryGeneration } from "./generate/generator.js";
// vector service
import { embed, getEngineFingerprint, testOnlineService } from "./vector/utils/embedder.js";
// tokenizer
import { preload as preloadTokenizer, injectEntities } from "./vector/utils/tokenizer.js";
// entity lexicon
import { buildEntityLexicon, buildDisplayNameMap } from "./vector/retrieval/entity-lexicon.js";
import {
getMeta,
updateMeta,
@@ -82,7 +88,7 @@ import {
// vector io
import { exportVectors, importVectors } from "./vector/storage/vector-io.js";
import { invalidateLexicalIndex } from "./vector/retrieval/lexical-index.js";
import { invalidateLexicalIndex, warmupIndex } from "./vector/retrieval/lexical-index.js";
// ═══════════════════════════════════════════════════════════════════════════
// 常量
@@ -145,6 +151,30 @@ const VECTOR_WARNING_COOLDOWN_MS = 120000; // 2分钟内不重复提醒
const EXT_PROMPT_KEY = "LittleWhiteBox_StorySummary";
const MIN_INJECTION_DEPTH = 2;
// ═══════════════════════════════════════════════════════════════════════════
// 分词器预热
// ═══════════════════════════════════════════════════════════════════════════
/** 是否已触发过预热 */
let tokenizerPreloaded = false;
function maybePreloadTokenizer() {
if (tokenizerPreloaded) return;
const vectorCfg = getVectorConfig();
if (!vectorCfg?.enabled) return;
tokenizerPreloaded = true;
preloadTokenizer()
.then((ok) => {
if (ok) tokenizerPreloaded = true;
})
.catch((e) => {
// 不置 tokenizerPreloaded允许后续重试例如用户修复路径/刷新后)
xbLog.warn(MODULE_ID, "分词器预热失败(将降级运行,可稍后重试)", e);
});
}
// role 映射
const ROLE_MAP = {
system: extension_prompt_roles.SYSTEM,
@@ -499,6 +529,27 @@ async function handleClearVectors() {
xbLog.info(MODULE_ID, "向量数据已清除");
}
// ═══════════════════════════════════════════════════════════════════════════
// 实体词典注入 + 索引预热
// ═══════════════════════════════════════════════════════════════════════════
function refreshEntityLexiconAndWarmup() {
const vectorCfg = getVectorConfig();
if (!vectorCfg?.enabled) return;
const store = getSummaryStore();
const { name1, name2 } = getContext();
const lexicon = buildEntityLexicon(store, { name1, name2 });
const displayMap = buildDisplayNameMap(store, { name1, name2 });
injectEntities(lexicon, displayMap);
// 异步预建词法索引(不阻塞)
invalidateLexicalIndex();
warmupIndex();
}
// ═══════════════════════════════════════════════════════════════════════════
// L2 自动增量向量化(总结完成后调用)
// ═══════════════════════════════════════════════════════════════════════════
@@ -997,6 +1048,9 @@ function handleFrameMessage(event) {
case "VECTOR_GENERATE":
if (data.config) saveVectorConfig(data.config);
// 向量配置变更,可能刚启用,触发预热
maybePreloadTokenizer();
refreshEntityLexiconAndWarmup();
handleGenerateVectors(data.config);
break;
@@ -1085,6 +1139,8 @@ function handleFrameMessage(event) {
case "REQUEST_VECTOR_STATS":
sendVectorStatsToFrame();
// 向量开关可能在 iframe 中被修改,检查是否需要预热
maybePreloadTokenizer();
break;
case "REQUEST_CLEAR": {
@@ -1213,7 +1269,7 @@ async function handleChatChanged() {
const newLength = Array.isArray(chat) ? chat.length : 0;
await rollbackSummaryIfNeeded();
invalidateLexicalIndex();
invalidateLexicalIndex();
initButtonsForAll();
const store = getSummaryStore();
@@ -1230,6 +1286,9 @@ async function handleChatChanged() {
sendVectorStatsToFrame();
}
// 实体词典注入 + 索引预热
refreshEntityLexiconAndWarmup();
setTimeout(() => checkVectorIntegrityAndWarn(), 2000);
}
@@ -1267,6 +1326,9 @@ async function handleMessageReceived() {
applyHideStateDebounced();
setTimeout(() => maybeAutoRunSummary("after_ai"), 1000);
// 新消息后刷新实体词典(可能有新角色)
refreshEntityLexiconAndWarmup();
}
function handleMessageSent() {
@@ -1458,4 +1520,7 @@ jQuery(() => {
if (!getSettings().storySummary?.enabled) return;
registerEvents();
initStateIntegration();
// 条件预热分词器storySummary 已启用,检查 vector 是否也启用)
maybePreloadTokenizer();
});