diff --git a/modules/story-summary/generate/prompt.js b/modules/story-summary/generate/prompt.js index 162d650..3364b33 100644 --- a/modules/story-summary/generate/prompt.js +++ b/modules/story-summary/generate/prompt.js @@ -1112,26 +1112,32 @@ async function buildVectorPrompt(store, recallResult, causalById, focusCharacter if (distantL0.length && total.used < total.max) { const distantBudget = { used: 0, max: Math.min(SUMMARIZED_EVIDENCE_MAX, total.max - total.used) }; - // 按楼层排序(时间顺序)后分组 - distantL0.sort((a, b) => a.floor - b.floor); + // 先按分数挑组(高分优先),再按时间输出(楼层升序) const distantFloorMap = groupL0ByFloor(distantL0); - - // 按楼层顺序遍历(Map 保持插入顺序,distantL0 已按 floor 排序) + const distantRanked = []; for (const [floor, l0s] of distantFloorMap) { const group = buildEvidenceGroup(floor, l0s, l1ByFloor); + const bestScore = Math.max(...l0s.map(l0 => (l0.rerankScore ?? l0.similarity ?? 0))); + distantRanked.push({ group, bestScore }); + } + distantRanked.sort((a, b) => (b.bestScore - a.bestScore) || (a.group.floor - b.group.floor)); - // 原子组预算检查 + const acceptedDistantGroups = []; + for (const item of distantRanked) { + const group = item.group; if (distantBudget.used + group.totalTokens > distantBudget.max) continue; + distantBudget.used += group.totalTokens; + acceptedDistantGroups.push(group); + for (const l0 of group.l0Atoms) usedL0Ids.add(l0.id); + injectionStats.distantEvidence.units++; + } + acceptedDistantGroups.sort((a, b) => a.floor - b.floor); + for (const group of acceptedDistantGroups) { const groupLines = formatEvidenceGroup(group); for (const line of groupLines) { assembled.distantEvidence.lines.push(line); } - distantBudget.used += group.totalTokens; - for (const l0 of l0s) { - usedL0Ids.add(l0.id); - } - injectionStats.distantEvidence.units++; } assembled.distantEvidence.tokens = distantBudget.used; @@ -1154,24 +1160,32 @@ async function buildVectorPrompt(store, recallResult, causalById, focusCharacter if (recentL0.length) { const recentBudget = { used: 0, max: UNSUMMARIZED_EVIDENCE_MAX }; - // 按楼层排序后分组 - recentL0.sort((a, b) => a.floor - b.floor); + // 先按分数挑组(高分优先),再按时间输出(楼层升序) const recentFloorMap = groupL0ByFloor(recentL0); - + const recentRanked = []; for (const [floor, l0s] of recentFloorMap) { const group = buildEvidenceGroup(floor, l0s, l1ByFloor); + const bestScore = Math.max(...l0s.map(l0 => (l0.rerankScore ?? l0.similarity ?? 0))); + recentRanked.push({ group, bestScore }); + } + recentRanked.sort((a, b) => (b.bestScore - a.bestScore) || (a.group.floor - b.group.floor)); + const acceptedRecentGroups = []; + for (const item of recentRanked) { + const group = item.group; if (recentBudget.used + group.totalTokens > recentBudget.max) continue; + recentBudget.used += group.totalTokens; + acceptedRecentGroups.push(group); + for (const l0 of group.l0Atoms) usedL0Ids.add(l0.id); + injectionStats.recentEvidence.units++; + } + acceptedRecentGroups.sort((a, b) => a.floor - b.floor); + for (const group of acceptedRecentGroups) { const groupLines = formatEvidenceGroup(group); for (const line of groupLines) { assembled.recentEvidence.lines.push(line); } - recentBudget.used += group.totalTokens; - for (const l0 of l0s) { - usedL0Ids.add(l0.id); - } - injectionStats.recentEvidence.units++; } assembled.recentEvidence.tokens = recentBudget.used;