dougdotcon's picture
Release transparent PT-BR RAG reranker baseline v0.1
e7c3795 verified
Raw History Blame Contribute Delete
1.83 kB
from __future__ import annotations
import argparse
import json
import re
import unicodedata
from difflib import SequenceMatcher
from pathlib import Path
STOPWORDS = {"a", "o", "as", "os", "de", "da", "do", "das", "dos", "e", "em", "um", "uma", "para", "por", "que", "é", "são", "como", "qual", "quais", "quando", "não", "com"}
def tokens(text: str) -> set[str]:
normalized = unicodedata.normalize("NFKD", text.lower()).encode("ascii", "ignore").decode("ascii")
return {token for token in re.findall(r"[a-z0-9]+", normalized) if token not in {unicodedata.normalize("NFKD", w).encode("ascii", "ignore").decode("ascii") for w in STOPWORDS} and len(token) > 2}
def score_pair(query: str, document: str) -> dict:
q = tokens(query)
d = tokens(document)
exact = len(q & d) / max(1, len(q))
fuzzy_hits = 0
for query_token in q - d:
if any(SequenceMatcher(None, query_token, doc_token).ratio() >= 0.72 for doc_token in d):
fuzzy_hits += 1
overlap = min(1.0, exact + 0.5 * fuzzy_hits / max(1, len(q)))
numbers_q = set(re.findall(r"\d+", query))
numbers_d = set(re.findall(r"\d+", document))
number_bonus = 0.15 if numbers_q and numbers_q & numbers_d else 0.0
score = min(1.0, overlap + number_bonus)
label = 2 if score >= 0.42 else 1 if score >= 0.16 else 0
return {"score": round(score, 6), "predicted_label": label, "overlap": round(overlap, 6), "number_bonus": number_bonus, "human_review_required": True}
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("record_json", type=Path)
args = parser.parse_args()
row = json.loads(args.record_json.read_text(encoding="utf-8"))
print(json.dumps(score_pair(row["query"], row["document"]), ensure_ascii=False, indent=2))
if __name__ == "__main__":
main()