Enterprise RAG with BM25 + Vector + Cross-Encoder Reranking
No documents uploaded yet.
Upload .md or .txt files to R2 bucket demo-autorag-docs
// Hybrid Search = BM25 + Vector Similarity
function hybridSearch(query, chunks, alpha = 0.5) {
return chunks.map(chunk => {
const bm25 = computeBM25(query, chunk); // Lexical match
const vector = computeVector(query, chunk); // Semantic match
return {
chunk,
score: alpha * bm25 + (1 - alpha) * vector
};
}).sort((a, b) => b.score - a.score);
}
// BM25 excels at: exact term matching, rare terms
// Vector excels at: semantic similarity, synonyms
// Cross-Encoder Reranking
function rerank(query, results) {
return results.map(r => {
// Cross-encoder considers full query-doc interaction
const score = crossEncoder(query, r.chunk);
// Factors: term proximity, position, coherence
return { ...r, rerankScore: score };
}).sort((a, b) => b.rerankScore - a.rerankScore);
}
// Reranking improves precision at top ranks
// Trade-off: slower but more accurate
✓ More precise retrieval
✓ Better for specific facts
✗ May lose context
✗ More chunks to search
✓ Balanced approach
✓ Good context window
✓ Recommended default
✓ Rich context
✓ Better for summaries
✗ May include noise
✗ Fewer chunks
// Citation Verification
function verifyCitation(answer, source) {
const answerWords = tokenize(answer);
const sourceWords = new Set(tokenize(source));
// Calculate overlap percentage
const matched = answerWords.filter(w => sourceWords.has(w));
const matchPercentage = matched.length / answerWords.length;
return {
verified: matchPercentage > 0.3, // 30% threshold
matchPercentage,
// Ensures answer is grounded in sources
};
}