feat: 改进召回精排反馈与上下文配置

This commit is contained in:
Youzini-afk
2026-03-24 22:15:47 +08:00
parent 1f03b0df4a
commit d4d527237e
6 changed files with 227 additions and 18 deletions

View File

@@ -84,6 +84,7 @@ const defaultSettings = {
recallEnableGraphDiffusion: true, // 是否启用图扩散 recallEnableGraphDiffusion: true, // 是否启用图扩散
recallDiffusionTopK: 100, // 图扩散阶段保留的候选上限 recallDiffusionTopK: 100, // 图扩散阶段保留的候选上限
recallLlmCandidatePool: 30, // 传给 LLM 精排的候选池大小 recallLlmCandidatePool: 30, // 传给 LLM 精排的候选池大小
recallLlmContextMessages: 4, // 传给 LLM 精排的最近非系统消息数
// 注入设置 // 注入设置
injectPosition: "atDepth", // 注入位置 injectPosition: "atDepth", // 注入位置
@@ -166,10 +167,16 @@ let isRecalling = false;
let lastInjectionContent = ""; let lastInjectionContent = "";
let lastExtractedItems = []; // 最近提取的节点(面板展示用) let lastExtractedItems = []; // 最近提取的节点(面板展示用)
let lastRecalledItems = []; // 最近召回的节点(面板展示用) let lastRecalledItems = []; // 最近召回的节点(面板展示用)
let lastRecallStatus = {
text: "待命",
meta: "尚未执行召回",
level: "idle",
};
let extractionCount = 0; // v2: 提取次数计数器(定期触发概要/遗忘/反思) let extractionCount = 0; // v2: 提取次数计数器(定期触发概要/遗忘/反思)
let serverSettingsSaveTimer = null; let serverSettingsSaveTimer = null;
let isRecoveringHistory = false; let isRecoveringHistory = false;
let lastHistoryWarningAt = 0; let lastHistoryWarningAt = 0;
let lastRecallFallbackNoticeAt = 0;
function getNodeDisplayName(node) { function getNodeDisplayName(node) {
return ( return (
@@ -279,6 +286,11 @@ function ensureCurrentGraphRuntimeState() {
function clearInjectionState() { function clearInjectionState() {
lastInjectionContent = ""; lastInjectionContent = "";
lastRecalledItems = []; lastRecalledItems = [];
lastRecallStatus = {
text: "待命",
meta: "当前无有效注入内容",
level: "idle",
};
try { try {
const context = getContext(); const context = getContext();
@@ -291,6 +303,21 @@ function clearInjectionState() {
} catch (error) { } catch (error) {
console.warn("[ST-BME] 清理旧注入失败:", error); console.warn("[ST-BME] 清理旧注入失败:", error);
} }
refreshPanelLiveState();
}
function refreshPanelLiveState() {
_panelModule?.refreshLiveState?.();
}
function setLastRecallStatus(text, meta, level = "info") {
lastRecallStatus = {
text: String(text || "待命"),
meta: String(meta || ""),
level,
};
refreshPanelLiveState();
} }
async function recordGraphMutation({ async function recordGraphMutation({
@@ -560,6 +587,12 @@ function updateModuleSettings(patch = {}) {
); );
lastInjectionContent = ""; lastInjectionContent = "";
lastRecalledItems = []; lastRecalledItems = [];
lastRecallStatus = {
text: "已停用",
meta: "插件已关闭,注入内容已清空",
level: "idle",
};
refreshPanelLiveState();
} catch (error) { } catch (error) {
console.warn("[ST-BME] 关闭插件时清理注入失败:", error); console.warn("[ST-BME] 关闭插件时清理注入失败:", error);
} }
@@ -583,6 +616,11 @@ function loadGraphFromChat() {
lastExtractedItems = []; lastExtractedItems = [];
lastRecalledItems = []; lastRecalledItems = [];
lastInjectionContent = ""; lastInjectionContent = "";
lastRecallStatus = {
text: "待命",
meta: "当前聊天尚未建立记忆图谱",
level: "idle",
};
return; return;
} }
@@ -598,6 +636,11 @@ function loadGraphFromChat() {
lastExtractedItems = []; lastExtractedItems = [];
updateLastRecalledItems(currentGraph.lastRecallResult || []); updateLastRecalledItems(currentGraph.lastRecallResult || []);
lastInjectionContent = ""; lastInjectionContent = "";
lastRecallStatus = {
text: "待命",
meta: "已加载聊天图谱,等待下一次召回",
level: "idle",
};
} }
function saveGraphToChat() { function saveGraphToChat() {
@@ -1186,22 +1229,39 @@ async function runRecall() {
// 获取最新用户消息 // 获取最新用户消息
let userMessage = ""; let userMessage = "";
const recentMessages = []; const recentMessages = [];
const recentContextMessageLimit = clampInt(
settings.recallLlmContextMessages,
4,
0,
20,
);
for (let i = chat.length - 1; i >= 0 && recentMessages.length < 4; i--) { for (
let i = chat.length - 1;
i >= 0 && (!userMessage || recentMessages.length < recentContextMessageLimit);
i--
) {
const msg = chat[i]; const msg = chat[i];
if (msg.is_system) continue; if (msg.is_system) continue;
if (msg.is_user && !userMessage) { if (msg.is_user && !userMessage) {
userMessage = msg.mes || ""; userMessage = msg.mes || "";
} }
if (recentMessages.length < recentContextMessageLimit) {
recentMessages.unshift( recentMessages.unshift(
`[${msg.is_user ? "user" : "assistant"}]: ${msg.mes || ""}`, `[${msg.is_user ? "user" : "assistant"}]: ${msg.mes || ""}`,
); );
} }
}
if (!userMessage) return; if (!userMessage) return;
console.log("[ST-BME] 开始召回"); console.log("[ST-BME] 开始召回");
setLastRecallStatus(
"召回中",
`上下文 ${recentMessages.length} 条 · 当前用户消息长度 ${userMessage.length}`,
"running",
);
const result = await retrieve({ const result = await retrieve({
graph: currentGraph, graph: currentGraph,
@@ -1235,6 +1295,12 @@ async function runRecall() {
// 格式化注入文本 // 格式化注入文本
const injectionText = formatInjection(result, getSchema()).trim(); const injectionText = formatInjection(result, getSchema()).trim();
lastInjectionContent = injectionText; lastInjectionContent = injectionText;
const retrievalMeta = result?.meta?.retrieval || {};
const llmMeta = retrievalMeta.llm || {
status: settings.recallEnableLLM ? "unknown" : "disabled",
reason: settings.recallEnableLLM ? "未提供 LLM 状态" : "LLM 精排已关闭",
candidatePool: 0,
};
if (injectionText) { if (injectionText) {
const tokens = estimateTokens(injectionText); const tokens = estimateTokens(injectionText);
@@ -1255,10 +1321,40 @@ async function runRecall() {
currentGraph.lastRecallResult = result.selectedNodeIds; currentGraph.lastRecallResult = result.selectedNodeIds;
updateLastRecalledItems(result.selectedNodeIds || []); updateLastRecalledItems(result.selectedNodeIds || []);
saveGraphToChat(); saveGraphToChat();
const llmLabel =
llmMeta.status === "llm"
? "LLM 精排完成"
: llmMeta.status === "fallback"
? "LLM 回退评分"
: llmMeta.status === "disabled"
? "仅评分排序"
: "召回完成";
setLastRecallStatus(
llmLabel,
`ctx ${recentMessages.length} · vector ${retrievalMeta.vectorHits ?? 0} · diffusion ${retrievalMeta.diffusionHits ?? 0} · llm pool ${llmMeta.candidatePool ?? 0} · recall ${result.stats.recallCount}`,
llmMeta.status === "fallback" ? "warning" : "success",
);
if (llmMeta.status === "fallback") {
const now = Date.now();
if (now - lastRecallFallbackNoticeAt > 15000) {
lastRecallFallbackNoticeAt = now;
toastr.warning(
llmMeta.reason || "LLM 精排未返回有效结果,已回退到评分排序",
"ST-BME 召回提示",
{ timeOut: 4500 },
);
}
}
} catch (e) { } catch (e) {
console.error("[ST-BME] 召回失败:", e); console.error("[ST-BME] 召回失败:", e);
const message = e?.message || String(e);
setLastRecallStatus("召回失败", message, "error");
toastr.error(`召回失败: ${message}`);
} finally { } finally {
isRecalling = false; isRecalling = false;
refreshPanelLiveState();
} }
} }
@@ -1669,6 +1765,7 @@ async function onReembedDirect() {
getSettings: () => getSettings(), getSettings: () => getSettings(),
getLastExtract: () => lastExtractedItems, getLastExtract: () => lastExtractedItems,
getLastRecall: () => lastRecalledItems, getLastRecall: () => lastRecalledItems,
getLastRecallStatus: () => lastRecallStatus,
getLastInjection: () => lastInjectionContent, getLastInjection: () => lastInjectionContent,
updateSettings: (patch) => { updateSettings: (patch) => {
const settings = updateModuleSettings(patch); const settings = updateModuleSettings(patch);

View File

@@ -126,6 +126,10 @@
<label>最近恢复</label> <label>最近恢复</label>
<div class="bme-recent-meta" id="bme-status-recovery"></div> <div class="bme-recent-meta" id="bme-status-recovery"></div>
</div> </div>
<div class="bme-config-row">
<label>最近召回</label>
<div class="bme-recent-meta" id="bme-status-last-recall"></div>
</div>
</div> </div>
<div class="bme-mobile-graph-preview" id="bme-mobile-graph-area"> <div class="bme-mobile-graph-preview" id="bme-mobile-graph-area">
@@ -748,7 +752,7 @@
<div class="bme-config-card-head"> <div class="bme-config-card-head">
<div> <div>
<div class="bme-config-card-title">LLM 精确召回</div> <div class="bme-config-card-title">LLM 精确召回</div>
<div class="bme-config-card-subtitle">控制是否启用 LLM 精排,以及传给 LLM 的候选池大小与最终保留上限。</div> <div class="bme-config-card-subtitle">控制是否启用 LLM 精排,以及传给 LLM 的上下文消息数、候选池大小与最终保留上限。</div>
</div> </div>
<div class="bme-config-guard-note">在“功能开关”中启用后生效。</div> <div class="bme-config-guard-note">在“功能开关”中启用后生效。</div>
</div> </div>
@@ -756,6 +760,10 @@
<input id="bme-setting-recall-llm" type="checkbox" /> <input id="bme-setting-recall-llm" type="checkbox" />
<span>启用 LLM 精排</span> <span>启用 LLM 精排</span>
</label> </label>
<div class="bme-config-row bme-stage-param">
<label for="bme-setting-recall-llm-context-messages">LLM 精排上下文消息数</label>
<input id="bme-setting-recall-llm-context-messages" class="bme-config-input" type="number" min="0" max="20" />
</div>
<div class="bme-config-row bme-stage-param"> <div class="bme-config-row bme-stage-param">
<label for="bme-setting-recall-llm-candidate-pool">LLM 精排候选池</label> <label for="bme-setting-recall-llm-candidate-pool">LLM 精排候选池</label>
<input id="bme-setting-recall-llm-candidate-pool" class="bme-config-input" type="number" min="1" max="100" /> <input id="bme-setting-recall-llm-candidate-pool" class="bme-config-input" type="number" min="1" max="100" />

View File

@@ -120,6 +120,7 @@ let _getGraph = null;
let _getSettings = null; let _getSettings = null;
let _getLastExtract = null; let _getLastExtract = null;
let _getLastRecall = null; let _getLastRecall = null;
let _getLastRecallStatus = null;
let _getLastInjection = null; let _getLastInjection = null;
let _updateSettings = null; let _updateSettings = null;
let _actionHandlers = {}; let _actionHandlers = {};
@@ -141,6 +142,7 @@ export async function initPanel({
getSettings, getSettings,
getLastExtract, getLastExtract,
getLastRecall, getLastRecall,
getLastRecallStatus,
getLastInjection, getLastInjection,
updateSettings, updateSettings,
actions, actions,
@@ -149,6 +151,7 @@ export async function initPanel({
_getSettings = getSettings; _getSettings = getSettings;
_getLastExtract = getLastExtract; _getLastExtract = getLastExtract;
_getLastRecall = getLastRecall; _getLastRecall = getLastRecall;
_getLastRecallStatus = getLastRecallStatus;
_getLastInjection = getLastInjection; _getLastInjection = getLastInjection;
_updateSettings = updateSettings; _updateSettings = updateSettings;
_actionHandlers = actions || {}; _actionHandlers = actions || {};
@@ -176,6 +179,7 @@ export async function initPanel({
panelEl?.querySelector(".bme-tab-btn.active")?.dataset.tab || "dashboard"; panelEl?.querySelector(".bme-tab-btn.active")?.dataset.tab || "dashboard";
_applyWorkspaceMode(); _applyWorkspaceMode();
_syncConfigSectionState(); _syncConfigSectionState();
_refreshRuntimeStatus();
} }
/** /**
@@ -204,6 +208,7 @@ export function openPanel() {
const activeTabId = const activeTabId =
panelEl?.querySelector(".bme-tab-btn.active")?.dataset.tab || currentTabId; panelEl?.querySelector(".bme-tab-btn.active")?.dataset.tab || currentTabId;
_switchTab(activeTabId); _switchTab(activeTabId);
_refreshRuntimeStatus();
_refreshGraph(); _refreshGraph();
_buildLegend(); _buildLegend();
} }
@@ -226,6 +231,27 @@ export function updatePanelTheme(themeName) {
_highlightThemeChoice(themeName); _highlightThemeChoice(themeName);
} }
export function refreshLiveState() {
if (!overlayEl?.classList.contains("active")) return;
_refreshRuntimeStatus();
switch (currentTabId) {
case "dashboard":
_refreshDashboard();
break;
case "memory":
_refreshMemoryBrowser();
break;
case "injection":
void _refreshInjectionPreview();
break;
default:
break;
}
_refreshGraph();
}
// ==================== Tab 切换 ==================== // ==================== Tab 切换 ====================
function _bindTabs() { function _bindTabs() {
@@ -309,10 +335,6 @@ function _refreshDashboard() {
_setText("bme-stat-edges", graph.edges.length); _setText("bme-stat-edges", graph.edges.length);
_setText("bme-stat-archived", archivedCount); _setText("bme-stat-archived", archivedCount);
_setText("bme-stat-frag", `${fragRate}%`); _setText("bme-stat-frag", `${fragRate}%`);
_setText(
"bme-status-meta",
`NODES: ${activeNodes.length} | EDGES: ${graph.edges.length}`,
);
const chatId = graph?.historyState?.chatId || "—"; const chatId = graph?.historyState?.chatId || "—";
const lastProcessed = graph?.historyState?.lastProcessedAssistantFloor ?? -1; const lastProcessed = graph?.historyState?.lastProcessedAssistantFloor ?? -1;
@@ -321,6 +343,7 @@ function _refreshDashboard() {
const vectorMode = graph?.vectorIndexState?.mode || "—"; const vectorMode = graph?.vectorIndexState?.mode || "—";
const vectorSource = graph?.vectorIndexState?.source || "—"; const vectorSource = graph?.vectorIndexState?.source || "—";
const recovery = graph?.historyState?.lastRecoveryResult; const recovery = graph?.historyState?.lastRecoveryResult;
const recallStatus = _getLastRecallStatus?.() || {};
_setText("bme-status-chat-id", chatId); _setText("bme-status-chat-id", chatId);
_setText( _setText(
@@ -339,6 +362,10 @@ function _refreshDashboard() {
? `${recovery.status} · from ${recovery.fromFloor ?? "—"} · ${recovery.reason || "—"}` ? `${recovery.status} · from ${recovery.fromFloor ?? "—"} · ${recovery.reason || "—"}`
: "暂无恢复记录", : "暂无恢复记录",
); );
_setText(
"bme-status-last-recall",
recallStatus.meta || "尚未执行召回",
);
_renderRecentList("bme-recent-extract", _getLastExtract?.() || []); _renderRecentList("bme-recent-extract", _getLastExtract?.() || []);
_renderRecentList("bme-recent-recall", _getLastRecall?.() || []); _renderRecentList("bme-recent-recall", _getLastRecall?.() || []);
@@ -720,6 +747,10 @@ function _refreshConfigTab() {
"bme-setting-recall-llm-candidate-pool", "bme-setting-recall-llm-candidate-pool",
settings.recallLlmCandidatePool ?? 30, settings.recallLlmCandidatePool ?? 30,
); );
_setInputValue(
"bme-setting-recall-llm-context-messages",
settings.recallLlmContextMessages ?? 4,
);
_setInputValue("bme-setting-inject-depth", settings.injectDepth ?? 9999); _setInputValue("bme-setting-inject-depth", settings.injectDepth ?? 9999);
_setInputValue("bme-setting-graph-weight", settings.graphWeight ?? 0.6); _setInputValue("bme-setting-graph-weight", settings.graphWeight ?? 0.6);
_setInputValue("bme-setting-vector-weight", settings.vectorWeight ?? 0.3); _setInputValue("bme-setting-vector-weight", settings.vectorWeight ?? 0.3);
@@ -892,6 +923,9 @@ function _bindConfigControls() {
bindNumber("bme-setting-recall-llm-candidate-pool", 30, 1, 100, (value) => bindNumber("bme-setting-recall-llm-candidate-pool", 30, 1, 100, (value) =>
_patchSettings({ recallLlmCandidatePool: value }), _patchSettings({ recallLlmCandidatePool: value }),
); );
bindNumber("bme-setting-recall-llm-context-messages", 4, 0, 20, (value) =>
_patchSettings({ recallLlmContextMessages: value }),
);
bindNumber("bme-setting-inject-depth", 9999, 0, 9999, (value) => bindNumber("bme-setting-inject-depth", 9999, 0, 9999, (value) =>
_patchSettings({ injectDepth: value }), _patchSettings({ injectDepth: value }),
); );
@@ -1186,6 +1220,15 @@ function _setText(id, text) {
if (el) el.textContent = String(text); if (el) el.textContent = String(text);
} }
function _refreshRuntimeStatus() {
const recallStatus = _getLastRecallStatus?.() || {};
const text = recallStatus.text || "待命";
const meta = recallStatus.meta || "尚未执行召回";
_setText("bme-status-text", text);
_setText("bme-status-meta", meta);
_setText("bme-panel-status", text);
}
function _patchSettings(patch = {}, options = {}) { function _patchSettings(patch = {}, options = {}) {
const settings = _updateSettings?.(patch) || _getSettings?.() || {}; const settings = _updateSettings?.(patch) || _getSettings?.() || {};
if (options.refreshGuards) _refreshGuardedConfigStates(settings); if (options.refreshGuards) _refreshGuardedConfigStates(settings);

View File

@@ -76,9 +76,27 @@ export async function retrieve({
let vectorResults = []; let vectorResults = [];
let diffusionResults = []; let diffusionResults = [];
let useLLM = false; let useLLM = false;
let llmMeta = {
enabled: enableLLMRecall,
status: enableLLMRecall ? "pending" : "disabled",
reason: enableLLMRecall ? "" : "LLM 精排已关闭",
candidatePool: 0,
selectedSeedCount: 0,
};
if (nodeCount === 0) { if (nodeCount === 0) {
return buildResult(graph, [], schema); return buildResult(graph, [], schema, {
retrieval: {
vectorHits: 0,
diffusionHits: 0,
scoredCandidates: 0,
llm: {
...llmMeta,
status: enableLLMRecall ? "skipped" : "disabled",
reason: "当前没有可参与召回的活跃节点",
},
},
});
} }
// ========== 第 1 层:向量预筛 ========== // ========== 第 1 层:向量预筛 ==========
@@ -208,7 +226,7 @@ export async function retrieve({
0, 0,
Math.min(normalizedLlmCandidatePool, scoredNodes.length), Math.min(normalizedLlmCandidatePool, scoredNodes.length),
); );
selectedNodeIds = await llmRecall( const llmResult = await llmRecall(
userMessage, userMessage,
recentMessages, recentMessages,
candidateNodes, candidateNodes,
@@ -217,10 +235,25 @@ export async function retrieve({
normalizedMaxRecallNodes, normalizedMaxRecallNodes,
options.recallPrompt, options.recallPrompt,
); );
selectedNodeIds = llmResult.selectedNodeIds;
llmMeta = {
enabled: true,
status: llmResult.status,
reason: llmResult.reason,
candidatePool: candidateNodes.length,
selectedSeedCount: llmResult.selectedNodeIds.length,
};
} else { } else {
selectedNodeIds = scoredNodes selectedNodeIds = scoredNodes
.slice(0, Math.min(normalizedTopK, scoredNodes.length)) .slice(0, Math.min(normalizedTopK, scoredNodes.length))
.map((s) => s.nodeId); .map((s) => s.nodeId);
llmMeta = {
enabled: false,
status: "disabled",
reason: "LLM 精排已关闭,直接采用评分排序",
candidatePool: 0,
selectedSeedCount: selectedNodeIds.length,
};
} }
selectedNodeIds = reconstructSceneNodeIds( selectedNodeIds = reconstructSceneNodeIds(
@@ -265,7 +298,14 @@ export async function retrieve({
selectedNodeIds = uniqueNodeIds(selectedNodeIds); selectedNodeIds = uniqueNodeIds(selectedNodeIds);
return buildResult(graph, selectedNodeIds, schema); return buildResult(graph, selectedNodeIds, schema, {
retrieval: {
vectorHits: vectorResults.length,
diffusionHits: diffusionResults.length,
scoredCandidates: scoredNodes.length,
llm: llmMeta,
},
});
} }
/** /**
@@ -374,14 +414,30 @@ async function llmRecall(
if (result?.selected_ids && Array.isArray(result.selected_ids)) { if (result?.selected_ids && Array.isArray(result.selected_ids)) {
// 校验 ID 有效性 // 校验 ID 有效性
const validIds = result.selected_ids.filter((id) => const validIds = uniqueNodeIds(
result.selected_ids.filter((id) =>
candidates.some((c) => c.nodeId === id), candidates.some((c) => c.nodeId === id),
); ),
return validIds; ).slice(0, maxNodes);
if (validIds.length > 0 || result.selected_ids.length === 0) {
return {
selectedNodeIds: validIds,
status: "llm",
reason:
validIds.length < result.selected_ids.length
? "LLM 返回了部分无效或超限 ID已自动裁剪"
: "LLM 精排完成",
};
}
} }
// LLM 失败时回退到纯评分排序 // LLM 失败时回退到纯评分排序
return candidates.slice(0, maxNodes).map((c) => c.nodeId); return {
selectedNodeIds: candidates.slice(0, maxNodes).map((c) => c.nodeId),
status: "fallback",
reason: "LLM 未返回有效 JSON 或有效候选,已回退到评分排序",
};
} }
// ==================== v2 辅助函数 ==================== // ==================== v2 辅助函数 ====================
@@ -418,7 +474,7 @@ function filterByVisibility(nodes, characterName) {
* 构建最终检索结果 * 构建最终检索结果
* 分离常驻注入Core和召回注入Recall * 分离常驻注入Core和召回注入Recall
*/ */
function buildResult(graph, selectedNodeIds, schema) { function buildResult(graph, selectedNodeIds, schema, meta = {}) {
const coreNodes = []; const coreNodes = [];
const recallNodes = []; const recallNodes = [];
const selectedSet = new Set(uniqueNodeIds(selectedNodeIds)); const selectedSet = new Set(uniqueNodeIds(selectedNodeIds));
@@ -453,6 +509,7 @@ function buildResult(graph, selectedNodeIds, schema) {
recallNodes, recallNodes,
groupedRecallNodes, groupedRecallNodes,
selectedNodeIds: [...selectedSet], selectedNodeIds: [...selectedSet],
meta,
stats: { stats: {
totalActive: activeNodes.length, totalActive: activeNodes.length,
coreCount: coreNodes.length, coreCount: coreNodes.length,

View File

@@ -32,6 +32,7 @@ assert.equal(defaultSettings.recallEnableVectorPrefilter, true);
assert.equal(defaultSettings.recallEnableGraphDiffusion, true); assert.equal(defaultSettings.recallEnableGraphDiffusion, true);
assert.equal(defaultSettings.recallDiffusionTopK, 100); assert.equal(defaultSettings.recallDiffusionTopK, 100);
assert.equal(defaultSettings.recallLlmCandidatePool, 30); assert.equal(defaultSettings.recallLlmCandidatePool, 30);
assert.equal(defaultSettings.recallLlmContextMessages, 4);
assert.equal(defaultSettings.injectDepth, 9999); assert.equal(defaultSettings.injectDepth, 9999);
console.log("default-settings tests passed"); console.log("default-settings tests passed");

View File

@@ -165,6 +165,8 @@ assert.deepEqual(state.vectorCalls, [4]);
assert.equal(state.diffusionCalls.length, 0); assert.equal(state.diffusionCalls.length, 0);
assert.equal(state.llmCandidateCount, 2); assert.equal(state.llmCandidateCount, 2);
assert.deepEqual(Array.from(llmPoolResult.selectedNodeIds), ["rule-2", "rule-1"]); assert.deepEqual(Array.from(llmPoolResult.selectedNodeIds), ["rule-2", "rule-1"]);
assert.equal(llmPoolResult.meta.retrieval.llm.status, "llm");
assert.equal(llmPoolResult.meta.retrieval.llm.candidatePool, 2);
state.vectorCalls.length = 0; state.vectorCalls.length = 0;
state.diffusionCalls.length = 0; state.diffusionCalls.length = 0;
@@ -187,5 +189,6 @@ await retrieve({
assert.deepEqual(state.vectorCalls, [3]); assert.deepEqual(state.vectorCalls, [3]);
assert.equal(state.diffusionCalls.length, 1); assert.equal(state.diffusionCalls.length, 1);
assert.equal(state.diffusionCalls[0].options.topK, 7); assert.equal(state.diffusionCalls[0].options.topK, 7);
assert.equal(noStageResult.meta.retrieval.llm.status, "disabled");
console.log("retrieval-config tests passed"); console.log("retrieval-config tests passed");