UNPKG

arela

Version:

AI-powered CTO with multi-agent orchestration, code summarization, visual testing (web + mobile) for blazing fast development.

113 lines 3.6 kB
/** * ResultCombiner - Intelligently merges results from multiple hops * * Features: * - Deduplicates across hops * - Ranks by relevance and hop order * - Builds coherent narrative */ export class ResultCombiner { options; constructor(options = {}) { this.options = { maxResults: options.maxResults ?? 20, includeSeparators: options.includeSeparators ?? true, }; } /** * Combine results from all hops */ combine(hops) { // Step 1: Deduplicate const deduplicated = this.deduplicate(hops); // Step 2: Rank by relevance and priority const ranked = this.rank(deduplicated); // Step 3: Build narrative const narrative = this.buildNarrative(ranked); // Step 4: Limit to max results return narrative.slice(0, this.options.maxResults); } /** * Remove duplicates across hops */ deduplicate(hops) { const seen = new Set(); const unique = []; for (const hop of hops) { const filtered = []; for (const item of hop.context) { const key = this.generateKey(item); if (!seen.has(key)) { seen.add(key); filtered.push(item); } } if (filtered.length > 0) { unique.push({ ...hop, context: filtered, }); } } return unique; } /** * Rank results by relevance and hop order */ rank(hops) { // Sort hops by priority (lower ID = higher priority) const sorted = hops.sort((a, b) => { const idA = parseInt(a.subQueryId); const idB = parseInt(b.subQueryId); return idA - idB; }); // Within each hop, sort by relevance score return sorted.map((hop) => ({ ...hop, context: hop.context.sort((a, b) => { const scoreA = a.score ?? 0; const scoreB = b.score ?? 0; return scoreB - scoreA; // Higher scores first }), })); } /** * Build coherent narrative from hops */ buildNarrative(hops) { const narrative = []; for (const hop of hops) { // Add separator if enabled if (this.options.includeSeparators && hops.length > 1) { narrative.push({ content: `--- Hop ${hop.subQueryId}: ${hop.subQuery} ---`, layer: hop.context[0]?.layer || "session", score: 1.0, metadata: { type: "separator", hopId: hop.subQueryId }, }); } // Add hop results narrative.push(...hop.context); } return narrative; } /** * Generate a unique key for a context item */ generateKey(item) { // Use content + layer as key for deduplication const contentPreview = item.content.slice(0, 100); return `${item.layer}:${contentPreview}`; } /** * Calculate deduplication statistics */ calculateDeduplicationRate(before, after) { const totalBefore = before.reduce((sum, hop) => sum + hop.context.length, 0); const totalAfter = after.filter((item) => item.metadata?.type !== "separator").length; if (totalBefore === 0) return 0; return ((totalBefore - totalAfter) / totalBefore) * 100; } } //# sourceMappingURL=combiner.js.map