Harden legacy extraction and recall JSON parsing

This commit is contained in:
Hao19911125
2026-04-05 15:24:01 +08:00
parent 03b535f5a4
commit ca3fc8fc2f
4 changed files with 287 additions and 8 deletions

View File

@@ -97,6 +97,44 @@ function buildRecallFallbackReason(llmResult) {
}
}
function resolveRecallSelectedIds(result) {
if (Array.isArray(result)) {
return result;
}
const visited = new Set();
const queue = [{ value: result, depth: 0 }];
while (queue.length > 0) {
const current = queue.shift();
const value = current?.value;
const depth = Number(current?.depth) || 0;
if (!value || typeof value !== "object" || visited.has(value) || depth > 1) {
continue;
}
visited.add(value);
const directCandidates = [
value.selected_ids,
value.selectedIds,
value.node_ids,
value.nodeIds,
value.ids,
];
for (const candidate of directCandidates) {
if (Array.isArray(candidate)) {
return candidate;
}
}
queue.push({ value: value.data, depth: depth + 1 });
queue.push({ value: value.result, depth: depth + 1 });
queue.push({ value: value.payload, depth: depth + 1 });
queue.push({ value: value.output, depth: depth + 1 });
}
return null;
}
function isAbortError(error) {
return error?.name === "AbortError";
}
@@ -1515,21 +1553,22 @@ async function llmRecall(
returnFailureDetails: true,
});
const result = llmResult?.ok ? llmResult.data : null;
const selectedIds = resolveRecallSelectedIds(result);
if (result?.selected_ids && Array.isArray(result.selected_ids)) {
if (Array.isArray(selectedIds)) {
// 校验 ID 有效性
const validIds = uniqueNodeIds(
result.selected_ids.filter((id) =>
selectedIds.filter((id) =>
candidates.some((c) => c.nodeId === id),
),
).slice(0, maxNodes);
if (validIds.length > 0 || result.selected_ids.length === 0) {
if (validIds.length > 0 || selectedIds.length === 0) {
return {
selectedNodeIds: validIds,
status: "llm",
reason:
validIds.length < result.selected_ids.length
validIds.length < selectedIds.length
? "LLM 返回了部分无效或超限 ID已自动裁剪"
: "LLM 精排完成",
};
@@ -1538,7 +1577,7 @@ async function llmRecall(
// LLM 失败时回退到纯评分排序
const fallbackReason = llmResult?.ok
? Array.isArray(result?.selected_ids)
? Array.isArray(selectedIds)
? "LLM 返回的候选 ID 无效,已回退到评分排序"
: "LLM 返回了无法识别的 JSON 结构,已回退到评分排序"
: buildRecallFallbackReason(llmResult);
@@ -1546,7 +1585,11 @@ async function llmRecall(
selectedNodeIds: candidates.slice(0, maxNodes).map((c) => c.nodeId),
status: "fallback",
reason: fallbackReason,
fallbackType: llmResult?.ok ? "invalid-candidate" : llmResult?.errorType || "unknown",
fallbackType: llmResult?.ok
? Array.isArray(selectedIds)
? "invalid-candidate"
: "invalid-structure"
: llmResult?.errorType || "unknown",
};
}