MCPcopy Create free account
hub / github.com/PatrickSys/codebase-context / collectHybridMatches

Method collectHybridMatches

src/core/search.ts:834–914  ·  view source on GitHub ↗
(
    queryVariants: QueryVariant[],
    candidateLimit: number,
    filters: SearchFilters | undefined,
    useSemanticSearch: boolean,
    useKeywordSearch: boolean,
    semanticWeight: number,
    keywordWeight: number
  )

Source from the content-addressed store, hash-verified

832 }
833
834 private async collectHybridMatches(
835 queryVariants: QueryVariant[],
836 candidateLimit: number,
837 filters: SearchFilters | undefined,
838 useSemanticSearch: boolean,
839 useKeywordSearch: boolean,
840 semanticWeight: number,
841 keywordWeight: number
842 ): Promise<{
843 semantic: Map<string, { chunk: CodeChunk; ranks: Array<{ rank: number; weight: number }> }>;
844 keyword: Map<string, { chunk: CodeChunk; ranks: Array<{ rank: number; weight: number }> }>;
845 }> {
846 const semanticRanks: Map<
847 string,
848 { chunk: CodeChunk; ranks: Array<{ rank: number; weight: number }> }
849 > = new Map();
850 const keywordRanks: Map<
851 string,
852 { chunk: CodeChunk; ranks: Array<{ rank: number; weight: number }> }
853 > = new Map();
854
855 // RRF uses ranks instead of scores for fusion robustness
856 if (useSemanticSearch && this.embeddingProvider && this.storageProvider) {
857 try {
858 for (const variant of queryVariants) {
859 const vectorResults = await this.semanticSearch(variant.query, candidateLimit, filters);
860
861 // Assign ranks based on retrieval order (0-indexed)
862 vectorResults.forEach((result, index) => {
863 const id = result.chunk.id;
864 const rank = index; // 0-indexed rank
865 const weight = semanticWeight * variant.weight;
866 const existing = semanticRanks.get(id);
867
868 if (existing) {
869 existing.ranks.push({ rank, weight });
870 } else {
871 semanticRanks.set(id, {
872 chunk: result.chunk,
873 ranks: [{ rank, weight }]
874 });
875 }
876 });
877 }
878 } catch (error) {
879 if (error instanceof IndexCorruptedError) {
880 throw error; // Propagate to handler for auto-heal
881 }
882 console.warn('Semantic search failed:', error);
883 }
884 }
885
886 if (useKeywordSearch && this.fuseIndex) {
887 try {
888 for (const variant of queryVariants) {
889 const keywordResults = await this.keywordSearch(variant.query, candidateLimit, filters);
890
891 // Assign ranks based on retrieval order (0-indexed)

Callers 1

searchMethod · 0.95

Calls 4

semanticSearchMethod · 0.95
keywordSearchMethod · 0.95
setMethod · 0.80
getMethod · 0.45

Tested by

no test coverage detected