UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applicatio

403 lines (402 loc) 13.3 kB
/** * Reranker Registry * * Centralized registry for all reranker implementations with metadata * and discovery capabilities. Follows the BaseRegistry pattern. */ import { BaseRegistry } from "../../core/infrastructure/index.js"; import { logger } from "../../utils/logger.js"; import { RAGErrorCodes, RerankerError } from "../errors/RAGError.js"; /** * Default reranker metadata entries */ const DEFAULT_RERANKER_METADATA = { llm: { description: "LLM-powered semantic reranking with multi-factor scoring", defaultConfig: { topK: 3, weights: { semantic: 0.4, vector: 0.4, position: 0.2 }, }, supportedOptions: ["model", "provider", "topK", "weights"], useCases: [ "High-quality semantic reranking", "Complex query understanding", "Context-aware scoring", ], aliases: ["semantic", "ai", "model-based"], requiresModel: true, requiresExternalAPI: false, }, "cross-encoder": { description: "Cross-encoder model for query-document relevance scoring", defaultConfig: { topK: 3, model: "ms-marco-MiniLM-L-6-v2", }, supportedOptions: ["model", "topK"], useCases: [ "High-precision reranking", "Search result refinement", "Academic/research applications", ], aliases: ["cross", "encoder", "bi-encoder"], requiresModel: true, requiresExternalAPI: false, }, cohere: { description: "Cohere Rerank API for production-grade relevance scoring", defaultConfig: { topK: 3, model: "rerank-v3.5", }, supportedOptions: ["model", "topK", "apiKey"], useCases: [ "Production search systems", "Enterprise applications", "High-volume reranking", ], aliases: ["cohere-rerank", "cohere-api"], requiresModel: false, requiresExternalAPI: true, }, simple: { description: "Position and vector score-based reranking (no LLM required)", defaultConfig: { topK: 3, weights: { vector: 0.8, position: 0.2 }, }, supportedOptions: ["topK", "weights"], useCases: [ "Fast reranking", "Low-latency requirements", "When LLM is unavailable", ], aliases: ["fast", "basic", "position-based"], requiresModel: false, requiresExternalAPI: false, }, batch: { description: "Batch LLM reranking for efficient multi-document scoring", defaultConfig: { topK: 3, weights: { semantic: 0.4, vector: 0.4, position: 0.2 }, }, supportedOptions: ["model", "provider", "topK", "weights"], useCases: [ "Large result sets", "Cost-efficient LLM usage", "Batch processing pipelines", ], aliases: ["batch-llm", "efficient", "bulk"], requiresModel: true, requiresExternalAPI: false, }, }; /** * Reranker Registry * * Manages registration and discovery of all reranker implementations. * Extends BaseRegistry for consistent lifecycle management. */ export class RerankerRegistry extends BaseRegistry { static instance = null; aliasMap = new Map(); constructor() { super(); } /** * Get singleton instance */ static getInstance() { if (!RerankerRegistry.instance) { RerankerRegistry.instance = new RerankerRegistry(); } return RerankerRegistry.instance; } /** * Reset singleton (for testing) */ static resetInstance() { if (RerankerRegistry.instance) { RerankerRegistry.instance.clear(); RerankerRegistry.instance = null; } } /** * Register all built-in rerankers */ async registerAll() { // Import reranker functions const rerankerModule = await import("./reranker.js"); // Register LLM reranker this.registerReranker("llm", async () => this.createLLMRerankerInstance(rerankerModule.rerank), DEFAULT_RERANKER_METADATA.llm); // Register cross-encoder reranker this.registerReranker("cross-encoder", async () => this.createCrossEncoderInstance(rerankerModule.CrossEncoderReranker), DEFAULT_RERANKER_METADATA["cross-encoder"]); // Register Cohere reranker this.registerReranker("cohere", async () => this.createCohereInstance(rerankerModule.CohereRelevanceScorer), DEFAULT_RERANKER_METADATA.cohere); // Register simple reranker this.registerReranker("simple", async () => this.createSimpleRerankerInstance(rerankerModule.simpleRerank), DEFAULT_RERANKER_METADATA.simple); // Register batch reranker this.registerReranker("batch", async () => this.createBatchRerankerInstance(rerankerModule.batchRerank), DEFAULT_RERANKER_METADATA.batch); logger.debug(`[RerankerRegistry] Registered ${this.items.size} reranker types`); } /** * Create LLM reranker instance wrapper */ createLLMRerankerInstance(_rerankFn) { return { type: "llm", async rerank() { throw new RerankerError("LLM reranker requires model provider. Use RerankerFactory.createReranker() instead.", { rerankerType: "llm", }); }, }; } /** * Create cross-encoder instance wrapper */ createCrossEncoderInstance(CrossEncoderClass) { const encoder = new CrossEncoderClass(); return { type: "cross-encoder", async rerank(results, query, options) { const documents = results.map((r) => r.text || r.metadata?.text || ""); const scores = await encoder.rerank(query, documents); const topK = options?.topK ?? 3; return scores .map((s) => ({ result: results[s.index], score: s.score, details: { semantic: s.score, vector: results[s.index].score ?? 0, position: 1 - s.index / results.length, }, })) .sort((a, b) => b.score - a.score) .slice(0, topK); }, }; } /** * Create Cohere instance wrapper */ createCohereInstance(CohereClass) { const scorer = new CohereClass(); return { type: "cohere", async rerank(results, query, options) { const documents = results.map((r) => r.text || r.metadata?.text || ""); const scores = await scorer.score(query, documents); const topK = options?.topK ?? 3; return scores .map((s) => ({ result: results[s.index], score: s.score, details: { semantic: s.score, vector: results[s.index].score ?? 0, position: 1 - s.index / results.length, }, })) .sort((a, b) => b.score - a.score) .slice(0, topK); }, }; } /** * Create simple reranker instance wrapper */ createSimpleRerankerInstance(simpleRerankFn) { return { type: "simple", async rerank(results, _query, options) { return simpleRerankFn(results, { topK: options?.topK, vectorWeight: options?.weights?.vector, positionWeight: options?.weights?.position, }); }, }; } /** * Create batch reranker instance wrapper */ createBatchRerankerInstance(_batchRerankFn) { return { type: "batch", async rerank() { throw new RerankerError("Batch reranker requires model provider. Use RerankerFactory.createReranker() instead.", { rerankerType: "batch", }); }, }; } /** * Register a reranker with aliases */ registerReranker(type, factory, metadata) { this.register(type, factory, metadata.aliases, { metadata }); // Register aliases in local alias map for type resolution for (const alias of metadata.aliases) { this.aliasMap.set(alias.toLowerCase(), type); logger.debug(`[RerankerRegistry] Registered alias '${alias}' -> '${type}'`); } } /** * Resolve type from alias */ resolveType(nameOrAlias) { const lower = nameOrAlias.toLowerCase(); // Check if it's a direct type if (this.items.has(lower)) { return lower; } // Check aliases const resolved = this.aliasMap.get(lower); if (resolved) { return resolved; } throw new RerankerError(`Unknown reranker type: '${nameOrAlias}'. Available types: ${this.list() .map((item) => item.id) .join(", ")}`, { code: RAGErrorCodes.RERANKER_NOT_FOUND, rerankerType: nameOrAlias, details: { requestedType: nameOrAlias, availableTypes: this.list().map((item) => item.id), }, }); } /** * Get a reranker by type or alias */ async getReranker(typeOrAlias) { await this.ensureInitialized(); const type = this.resolveType(typeOrAlias); const reranker = await this.get(type); if (!reranker) { throw new RerankerError(`Reranker not found: ${type}`, { code: RAGErrorCodes.RERANKER_NOT_FOUND, rerankerType: type, details: { type }, }); } return reranker; } /** * Get list of available reranker types */ async getAvailableRerankers() { await this.ensureInitialized(); return this.list().map((item) => item.id); } /** * Get metadata for a specific reranker */ getRerankerMetadata(typeOrAlias) { const type = this.resolveType(typeOrAlias); const entry = this.list().find((item) => item.id === type); return entry?.metadata; } /** * Get all aliases for a type */ getAliasesForType(type) { const metadata = DEFAULT_RERANKER_METADATA[type]; return metadata?.aliases ?? []; } /** * Get all registered aliases */ getAllAliases() { return new Map(this.aliasMap); } /** * Check if a type or alias exists */ hasReranker(typeOrAlias) { try { this.resolveType(typeOrAlias); return true; } catch { return false; } } /** * Get rerankers by use case */ getRerankersByUseCase(useCase) { const matches = []; const useCaseLower = useCase.toLowerCase(); for (const [type, metadata] of Object.entries(DEFAULT_RERANKER_METADATA)) { const hasMatchingUseCase = metadata.useCases.some((uc) => uc.toLowerCase().includes(useCaseLower)); if (hasMatchingUseCase) { matches.push(type); } } return matches; } /** * Get default configuration for a reranker */ getDefaultConfig(typeOrAlias) { const metadata = this.getRerankerMetadata(typeOrAlias); return metadata?.defaultConfig; } /** * Get rerankers that don't require external APIs */ getLocalRerankers() { const matches = []; for (const [type, metadata] of Object.entries(DEFAULT_RERANKER_METADATA)) { if (!metadata.requiresExternalAPI) { matches.push(type); } } return matches; } /** * Get rerankers that don't require AI models */ getModelFreeRerankers() { const matches = []; for (const [type, metadata] of Object.entries(DEFAULT_RERANKER_METADATA)) { if (!metadata.requiresModel) { matches.push(type); } } return matches; } /** * Clear the registry (also clears aliases) */ clear() { super.clear(); this.aliasMap.clear(); } } /** * Global reranker registry singleton */ export const rerankerRegistry = RerankerRegistry.getInstance(); /** * Convenience function to get available rerankers */ export async function getAvailableRerankers() { return rerankerRegistry.getAvailableRerankers(); } /** * Convenience function to get reranker by type */ export async function getReranker(typeOrAlias) { return rerankerRegistry.getReranker(typeOrAlias); } /** * Convenience function to get reranker metadata */ export function getRegisteredRerankerMetadata(typeOrAlias) { return rerankerRegistry.getRerankerMetadata(typeOrAlias); }