refactor: extract extraction and recall helper controllers

This commit is contained in:
Youzini-afk
2026-03-29 16:39:22 +08:00
parent d9f04d4388
commit 81d06870db
3 changed files with 418 additions and 283 deletions

222
recall-controller.js Normal file
View File

@@ -0,0 +1,222 @@
// ST-BME: 召回输入解析与注入控制器(纯函数)
export function buildRecallRecentMessagesController(
chat,
limit,
syntheticUserMessage = "",
runtime,
) {
if (!Array.isArray(chat) || limit <= 0) return [];
const recentMessages = [];
for (
let index = chat.length - 1;
index >= 0 && recentMessages.length < limit;
index--
) {
const message = chat[index];
if (message?.is_system) continue;
recentMessages.unshift(runtime.formatRecallContextLine(message));
}
const normalizedSynthetic = runtime.normalizeRecallInputText(
syntheticUserMessage,
);
if (!normalizedSynthetic) return recentMessages;
const syntheticLine = `[user]: ${normalizedSynthetic}`;
if (recentMessages[recentMessages.length - 1] !== syntheticLine) {
recentMessages.push(syntheticLine);
while (recentMessages.length > limit) {
recentMessages.shift();
}
}
return recentMessages;
}
export function getRecallUserMessageSourceLabelController(source) {
switch (source) {
case "send-intent":
return "发送意图";
case "chat-tail-user":
return "当前用户楼层";
case "message-sent":
return "已发送用户楼层";
case "chat-last-user":
return "历史最后用户楼层";
default:
return "未知";
}
}
export function resolveRecallInputController(
chat,
recentContextMessageLimit,
override = null,
runtime,
) {
const overrideText = runtime.normalizeRecallInputText(
override?.userMessage || "",
);
if (overrideText) {
return {
userMessage: overrideText,
source: String(override?.source || "override"),
sourceLabel: String(override?.sourceLabel || "发送前拦截"),
recentMessages: runtime.buildRecallRecentMessages(
chat,
recentContextMessageLimit,
override?.includeSyntheticUserMessage === false ? "" : overrideText,
),
};
}
const latestUserMessage = runtime.getLatestUserChatMessage(chat);
const latestUserText = runtime.normalizeRecallInputText(
latestUserMessage?.mes || "",
);
const lastNonSystemMessage = runtime.getLastNonSystemChatMessage(chat);
const tailUserText = lastNonSystemMessage?.is_user
? runtime.normalizeRecallInputText(lastNonSystemMessage?.mes || "")
: "";
const pendingIntentText = runtime.isFreshRecallInputRecord(
runtime.pendingRecallSendIntent,
)
? runtime.pendingRecallSendIntent.text
: "";
const sentUserText = runtime.isFreshRecallInputRecord(
runtime.lastRecallSentUserMessage,
)
? runtime.lastRecallSentUserMessage.text
: "";
let userMessage = "";
let source = "";
let syntheticUserMessage = "";
if (pendingIntentText) {
userMessage = pendingIntentText;
source = "send-intent";
syntheticUserMessage = pendingIntentText;
} else if (tailUserText) {
userMessage = tailUserText;
source = "chat-tail-user";
} else if (sentUserText) {
userMessage = sentUserText;
source = "message-sent";
if (!latestUserText || latestUserText !== sentUserText) {
syntheticUserMessage = sentUserText;
}
} else if (latestUserText) {
userMessage = latestUserText;
source = "chat-last-user";
}
return {
userMessage,
source,
sourceLabel: runtime.getRecallUserMessageSourceLabel(source),
recentMessages: runtime.buildRecallRecentMessages(
chat,
recentContextMessageLimit,
syntheticUserMessage,
),
};
}
export function applyRecallInjectionController(
settings,
recallInput,
recentMessages,
result,
runtime,
) {
const injectionText = runtime
.formatInjection(result, runtime.getSchema())
.trim();
runtime.setLastInjectionContent(injectionText);
const retrievalMeta = result?.meta?.retrieval || {};
const llmMeta = retrievalMeta.llm || {
status: settings.recallEnableLLM ? "unknown" : "disabled",
reason: settings.recallEnableLLM ? "未提供 LLM 状态" : "LLM 精排已关闭",
candidatePool: 0,
};
if (injectionText) {
const tokens = runtime.estimateTokens(injectionText);
runtime.console.log(
`[ST-BME] 注入 ${tokens} 估算 tokens, Core=${result.stats.coreCount}, Recall=${result.stats.recallCount}`,
);
}
const injectionTransport = runtime.applyModuleInjectionPrompt(
injectionText,
settings,
);
runtime.recordInjectionSnapshot("recall", {
taskType: "recall",
source: recallInput.source,
sourceLabel: recallInput.sourceLabel,
hookName: recallInput.hookName,
recentMessages,
selectedNodeIds: result.selectedNodeIds || [],
retrievalMeta,
llmMeta,
stats: result.stats || {},
injectionText,
transport: injectionTransport,
});
runtime.setCurrentGraphLastRecallResult(result.selectedNodeIds);
runtime.updateLastRecalledItems(result.selectedNodeIds || []);
runtime.saveGraphToChat({ reason: "recall-result-updated" });
const llmLabel =
llmMeta.status === "llm"
? "LLM 精排完成"
: llmMeta.status === "fallback"
? "LLM 回退评分"
: llmMeta.status === "disabled"
? "仅评分排序"
: "召回完成";
const hookLabel = runtime.getRecallHookLabel(recallInput.hookName);
runtime.setLastRecallStatus(
llmLabel,
[
hookLabel,
recallInput.sourceLabel,
`ctx ${recentMessages.length}`,
`vector ${retrievalMeta.vectorHits ?? 0}`,
retrievalMeta.vectorMergedHits ? `merged ${retrievalMeta.vectorMergedHits}` : "",
`diffusion ${retrievalMeta.diffusionHits ?? 0}`,
retrievalMeta.candidatePoolAfterDpp
? `dpp ${retrievalMeta.candidatePoolAfterDpp}`
: "",
`llm pool ${llmMeta.candidatePool ?? 0}`,
`recall ${result.stats.recallCount}`,
]
.filter(Boolean)
.join(" · "),
llmMeta.status === "fallback" ? "warning" : "success",
{
syncRuntime: true,
toastKind: "",
},
);
if (llmMeta.status === "fallback") {
const now = Date.now();
if (now - runtime.getLastRecallFallbackNoticeAt() > 15000) {
runtime.setLastRecallFallbackNoticeAt(now);
runtime.toastr.warning(
llmMeta.reason || "LLM 精排未成功,已改用评分排序并继续注入记忆",
"ST-BME 召回提示",
{ timeOut: 4500 },
);
}
}
return { injectionText, retrievalMeta, llmMeta };
}