Spaces:
Sleeping
Sleeping
File size: 2,629 Bytes
bb04c5f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | # searcher/reranker.py
import yaml
from sentence_transformers import CrossEncoder
class Reranker:
"""
Cross-encoder reranking for precision improvement on top-k candidates.
Why rerank after fusion?
- Bi-encoders (used in DenseRetriever) embed query and doc INDEPENDENTLY
β fast but they can't model their interaction
- Cross-encoders process (query, document) TOGETHER β much more accurate
but too slow to run over the whole corpus
- Solution: use bi-encoder to shortlist ~20 candidates, then cross-encoder
to precisely rank them β speed of FAISS + accuracy of cross-encoder
Model: ms-marco-MiniLM-L-6-v2 (fast, strong on passage relevance)
"""
def __init__(self, config_path="config.yaml"):
with open(config_path) as f:
config = yaml.safe_load(f)
model_name = config.get("reranker_model", "cross-encoder/ms-marco-MiniLM-L-6-v2")
self.enabled = config.get("reranking_enabled", True)
if self.enabled:
print(f"Loading reranker model '{model_name}'...")
self.model = CrossEncoder(model_name)
print("Reranker loaded.")
def rerank(self, query: str, candidates: list[dict], top_k: int = 5) -> list[dict]:
"""
Rerank candidates using cross-encoder relevance scores.
Args:
query β original (not expanded) user query
candidates β list of chunk dicts from FusionRanker
top_k β number of final results to return
Returns:
list[dict] β reranked results, each with rerank_score added
"""
if not self.enabled or not candidates:
return candidates[:top_k]
pairs = [(query, c["chunk_text"]) for c in candidates]
scores = self.model.predict(pairs)
for i, score in enumerate(scores):
candidates[i]["rerank_score"] = float(score)
reranked = sorted(candidates, key=lambda x: x["rerank_score"], reverse=True)
return reranked[:top_k]
if __name__ == "__main__":
reranker = Reranker()
candidates = [
{"chunk_id": 1, "chunk_text": "Q3 budget shows 15% revenue increase", "filepath": "/a.pdf", "chunk_index": 0, "rrf_score": 0.03},
{"chunk_id": 2, "chunk_text": "The weather today is sunny and warm", "filepath": "/b.txt", "chunk_index": 0, "rrf_score": 0.02},
]
results = reranker.rerank("quarterly revenue", candidates, top_k=2)
for r in results:
print(f"[rerank {r['rerank_score']:.4f}] {r['chunk_text']}") |