Spaces:
Running on Zero
Running on Zero
sync: from ael backend/space/
Browse files
rerank.py
CHANGED
|
@@ -105,6 +105,18 @@ DROP_BELOW = float(os.environ.get("AEL_RERANK_DROP", "0.35"))
|
|
| 105 |
# one, not a target: a short page is fine, an empty one is not.
|
| 106 |
MIN_RESULTS = 1
|
| 107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
# How many results the model is allowed to judge. A 421M cross-encoder on a
|
| 109 |
# shared CPU does not score eight documents inside an 800ms budget, and the
|
| 110 |
# first version's answer to that was to throw the whole set away — which is why
|
|
@@ -370,8 +382,24 @@ def rerank(query, results, budget_ms=800):
|
|
| 370 |
# Highest score first. Unscored results keep their relative position at the
|
| 371 |
# end rather than being dropped: we have no opinion about them.
|
| 372 |
scored.sort(key=lambda t: (t[0] is None, -(t[0] if t[0] is not None else 0.0), t[1]))
|
| 373 |
-
|
| 374 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 375 |
|
| 376 |
out["scores"] = [
|
| 377 |
{"title": str(r.get("title") or "")[:80], "score": p}
|
|
|
|
| 105 |
# one, not a target: a short page is fine, an empty one is not.
|
| 106 |
MIN_RESULTS = 1
|
| 107 |
|
| 108 |
+
# …but one result is not a page you can research with. When the threshold would
|
| 109 |
+
# leave fewer than this, the *highest-scoring* results are kept instead of the
|
| 110 |
+
# original set: the floor must not resurrect the junk, so it tops the list back
|
| 111 |
+
# up from the model's own ranking rather than falling back to engine order.
|
| 112 |
+
#
|
| 113 |
+
# This is not the "floor of 3" the module's own docstring warns about. That one
|
| 114 |
+
# fell back to the whole original set, so a set of eight with two worth showing
|
| 115 |
+
# served all eight. Topping up from the ranking cannot do that: the results that
|
| 116 |
+
# come back are still the ones the model rated highest, just including a couple
|
| 117 |
+
# more of them.
|
| 118 |
+
MIN_KEEP = int(os.environ.get("AEL_RERANK_MIN_KEEP", "2"))
|
| 119 |
+
|
| 120 |
# How many results the model is allowed to judge. A 421M cross-encoder on a
|
| 121 |
# shared CPU does not score eight documents inside an 800ms budget, and the
|
| 122 |
# first version's answer to that was to throw the whole set away — which is why
|
|
|
|
| 382 |
# Highest score first. Unscored results keep their relative position at the
|
| 383 |
# end rather than being dropped: we have no opinion about them.
|
| 384 |
scored.sort(key=lambda t: (t[0] is None, -(t[0] if t[0] is not None else 0.0), t[1]))
|
| 385 |
+
|
| 386 |
+
judged_rows = [row for row in scored if row[0] is not None]
|
| 387 |
+
below = [row for row in judged_rows if row[0] < DROP_BELOW]
|
| 388 |
+
above = [row for row in judged_rows if row[0] >= DROP_BELOW]
|
| 389 |
+
unscored = [row for row in scored if row[0] is None]
|
| 390 |
+
|
| 391 |
+
if len(above) + len(unscored) < MIN_KEEP and below and above:
|
| 392 |
+
# Top up from the model's own ranking — never from the original order.
|
| 393 |
+
# Guarded on `above` being non-empty: when *nothing* cleared the bar
|
| 394 |
+
# that is not a thin page, it is a model that did not understand the
|
| 395 |
+
# query, and it is reported as starvation below instead of being
|
| 396 |
+
# disguised as two confident results.
|
| 397 |
+
need = MIN_KEEP - (len(above) + len(unscored))
|
| 398 |
+
above = above + below[:need]
|
| 399 |
+
below = below[need:]
|
| 400 |
+
|
| 401 |
+
kept = [r for _, _, r in above] + [r for _, _, r in unscored]
|
| 402 |
+
dropped = len(below)
|
| 403 |
|
| 404 |
out["scores"] = [
|
| 405 |
{"title": str(r.get("title") or "")[:80], "score": p}
|