Spaces:
Running
Running
Devdan Schretlen
Claude Opus 5 (1M context)
Render the answer as Markdown, bound API timeouts, fix a false notice
9db5d1e Download src/rerank.py from DevSchretl/UBCHelper: direct link, hf CLI and curl.
- Browser
- Download file 2.36 kB
-
https://huggingface.co/spaces/DevSchretl/UBCHelper/resolve/main/src/rerank.py
- Command line
-
hf download hf://spaces/DevSchretl/UBCHelper/src/rerank.py
-
curl -L -o rerank.py https://huggingface.co/spaces/DevSchretl/UBCHelper/resolve/main/src/rerank.py
2.36 kB
| """ | |
| Rerank — the precision stage of the retrieval funnel. | |
| The bi-encoder (embeddings) scores query and document *separately*, so it can only | |
| compare their summaries. A cross-encoder reads the query and a document *together* and | |
| scores the pair jointly — far sharper, but far too slow to run against the whole corpus. | |
| So it only ever sees the short candidate list that the cheap recall stage (dense + BM25) | |
| already produced. | |
| Reranking runs on Cohere's hosted rerank API (config.RERANKER_MODEL). Keeping it hosted | |
| means no local torch / sentence-transformers dependency, so the service deploys on an | |
| ordinary CPU host. Excerpts longer than the model's window are truncated server-side, | |
| which is fine: the title/section header + the start of the body carry the ranking signal. | |
| """ | |
| from __future__ import annotations | |
| import time | |
| from . import config | |
| from .retrieve import Result | |
| # The Cohere client is created lazily and cached: only the hybrid_rerank mode needs it, | |
| # so dense/hybrid modes never construct it. | |
| _client = None | |
| def _get_client(): | |
| global _client | |
| if _client is None: | |
| import cohere | |
| _client = cohere.Client(config.COHERE_API_KEY, timeout=config.API_TIMEOUT) | |
| return _client | |
| def rerank(query: str, candidates: list[Result], top_k: int) -> list[Result]: | |
| """Re-score `candidates` jointly against `query`; return the top_k, best first. | |
| The returned Results carry the Cohere relevance score (0-1, higher is better), | |
| replacing whatever score the recall stage assigned. | |
| """ | |
| import cohere | |
| client = _get_client() | |
| # Trial keys are capped at 10 calls/minute; back off and retry on 429 so a batch | |
| # (e.g. the eval loop) doesn't die mid-run. | |
| for attempt in range(4): | |
| try: | |
| response = client.rerank( | |
| model=config.RERANKER_MODEL, | |
| query=query, | |
| documents=[r.recipe["text"] for r in candidates], | |
| top_n=top_k, | |
| ) | |
| break | |
| except cohere.errors.TooManyRequestsError: | |
| if attempt == 3: | |
| raise | |
| time.sleep(15 * (attempt + 1)) | |
| return [ | |
| Result( | |
| id=candidates[result.index].id, | |
| score=result.relevance_score, | |
| recipe=candidates[result.index].recipe, | |
| ) | |
| for result in response.results | |
| ] | |