fix(reranker): score HuggingFace reranker with sigmoid, not min-max (#5715)

This commit is contained in:
Muhammad Furqan
2026-06-25 16:18:02 +05:30
committed by GitHub
parent 890473f891
commit af70668308
2 changed files with 72 additions and 3 deletions
+21 -3
View File
@@ -59,6 +59,26 @@ class HuggingFaceReranker(BaseReranker):
self.model.to(self.device)
self.model.eval()
@staticmethod
def _normalize_scores(scores: List[float]) -> List[float]:
"""Map raw cross-encoder logits into the [0, 1] range via a sigmoid.
Cross-encoder rerankers (e.g. ``BAAI/bge-reranker-*``) emit unbounded
logits; the documented way to obtain an interpretable [0, 1] relevance
score is a per-document sigmoid (``1 / (1 + e^-x)``), which preserves the
ranking order.
This replaces the previous min-max scaling, which produced *set-relative*
scores: the lowest-ranked document was always forced to 0.0, and a single
document (or any set of tied scores) collapsed to 0.0 — wrongly reporting
a result as completely irrelevant. Sigmoid scores each document on its own
merit, so those cases are handled naturally.
"""
if not scores:
return []
arr = np.asarray(scores, dtype=float)
return (1.0 / (1.0 + np.exp(-arr))).tolist()
def rerank(self, query: str, documents: List[Dict[str, Any]], top_k: int = None) -> List[Dict[str, Any]]:
"""
Rerank documents using HuggingFace cross-encoder model.
@@ -118,9 +138,7 @@ class HuggingFaceReranker(BaseReranker):
# Normalize scores if requested
if self.config.normalize:
scores = np.array(scores)
scores = (scores - scores.min()) / (scores.max() - scores.min() + 1e-8)
scores = scores.tolist()
scores = self._normalize_scores(scores)
# Combine documents with scores
doc_score_pairs = list(zip(documents, scores))