UNPKG

@n2flowjs/nbase

Version:

Neural Vector Database for efficient similarity search

144 lines (121 loc) 5.56 kB
import { expect } from 'chai'; import { SearchReranker } from '../src/search/reranking'; import { SearchResult } from '../src/types'; describe('SearchReranker', () => { let reranker: SearchReranker; let testResults: SearchResult[]; beforeEach(() => { reranker = new SearchReranker(); // Setup test results testResults = [ { id: 1, dist: 0.1, metadata: {} }, { id: 2, dist: 0.2, metadata: {} }, { id: 3, dist: 0.3, metadata: {} }, { id: 4, dist: 0.4, metadata: {} }, { id: 5, dist: 0.5, metadata: {} } ]; }); describe('rerank method', () => { it('should return empty array when input is not an array', () => { // @ts-ignore - Intentionally passing invalid input const result = reranker.rerank({}); expect(result).to.be.an('array').that.is.empty; }); it('should default to standard reranking when no method is specified', () => { const result = reranker.rerank(testResults); expect(result).to.deep.equal(testResults); }); }); describe('standard reranking', () => { it('should return all results when k is not specified', () => { const result = reranker.rerank(testResults, { method: 'standard' }); expect(result).to.have.lengthOf(testResults.length); expect(result).to.deep.equal(testResults); }); it('should limit results to k when specified', () => { const k = 3; const result = reranker.rerank(testResults, { method: 'standard', k }); expect(result).to.have.lengthOf(k); expect(result).to.deep.equal(testResults.slice(0, k)); }); }); describe('diversity reranking', () => { it('should fall back to standard when required params are missing', () => { const result = reranker.rerank(testResults, { method: 'diversity' }); expect(result).to.deep.equal(testResults); }); it('should perform MMR reranking when all required parameters are provided', () => { // Create test vectors const vectorsMap = new Map(); const vectors = [ new Float32Array([0.1, 0.2, 0.3]), new Float32Array([0.4, 0.5, 0.6]), new Float32Array([0.7, 0.8, 0.9]), new Float32Array([0.2, 0.3, 0.4]), new Float32Array([0.5, 0.6, 0.7]) ]; testResults.forEach((result, idx) => { vectorsMap.set(result.id, vectors[idx]); }); const queryVector = new Float32Array([0.3, 0.3, 0.3]); const result = reranker.rerank(testResults, { method: 'diversity', queryVector, vectorsMap, lambda: 0.5 }); // Verify we got the right number of results expect(result).to.have.lengthOf(testResults.length); // Verify first result is still the most relevant one expect(result[0].id).to.equal(1); // Verify the exact order is different from the original const originalIds = testResults.map(r => r.id); const rerankedIds = result.map(r => r.id); expect(rerankedIds).to.not.deep.equal(originalIds); }); }); describe('weighted reranking', () => { it('should fall back to standard when metadataMap is missing', () => { const result = reranker.rerank(testResults, { method: 'weighted', weights: { popularity: 0.5 } }); expect(result).to.deep.equal(testResults); }); it('should rerank based on weighted metadata attributes', () => { // Setup metadata map const metadataMap = new Map(); metadataMap.set(1, { popularity: 5, recency: 2 }); metadataMap.set(2, { popularity: 10, recency: 1 }); metadataMap.set(3, { popularity: 2, recency: 8 }); metadataMap.set(4, { popularity: 6, recency: 4 }); metadataMap.set(5, { popularity: 4, recency: 5 }); const result = reranker.rerank(testResults, { method: 'weighted', metadataMap, weights: { popularity: 0.1, recency: 0.05 } }); // Item 2 should come first due to high popularity expect(result[0].id).to.equal(2); // Verify all results are returned but in different order expect(result).to.have.lengthOf(testResults.length); const rerankedIds = result.map(r => r.id); const originalIds = testResults.map(r => r.id); expect(rerankedIds).to.not.deep.equal(originalIds); }); it('should limit results to k when specified', () => { const metadataMap = new Map(); testResults.forEach((r, i) => { metadataMap.set(r.id, { score: 10 - i }); }); const k = 2; const result = reranker.rerank(testResults, { method: 'weighted', metadataMap, weights: { score: 0.1 }, k }); expect(result).to.have.lengthOf(k); }); }); });