rak2315's picture
Show normalized 0-1 scores in demo
62666a7 verified
Raw
History Blame Contribute Delete
3.86 kB
"""Redrob Ranker — HuggingFace Space demo.
Runs the exact ranking engine (ranker/) on a <=100-candidate sample and shows the
ranked output with grounded reasoning, plus the honeypots it auto-rejected. A
reviewer can also upload their own small .jsonl. Numpy-only at inference time —
embeddings are precomputed (artifacts/), so no model runs here. No pandas, to
keep the Space build light and fast.
"""
from __future__ import annotations
import json
from pathlib import Path
import gradio as gr
from ranker.fit_score import fit_components
from ranker.pipeline import final_score
from ranker.honeypot import is_honeypot, honeypot_reasons
from ranker.dense import load_cosine_map
from ranker.combine import order_candidates, normalize_scores
from ranker.reasoning import template_reasoning
HERE = Path(__file__).resolve().parent
SAMPLE = HERE / "sample_100.jsonl"
COSINE = load_cosine_map(HERE / "artifacts") or {}
RANKED_HEADERS = ["rank", "candidate_id", "title", "yoe", "score", "reasoning"]
REJECT_HEADERS = ["candidate_id", "honeypot_reason"]
def _load(path: Path) -> list[dict]:
out = []
with open(path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if line:
out.append(json.loads(line))
return out
def rank(candidates: list[dict]):
by_id = {c["candidate_id"]: c for c in candidates}
rejected = [[c["candidate_id"], "; ".join(honeypot_reasons(c))]
for c in candidates if is_honeypot(c)]
scored, comps = [], {}
for c in candidates:
if is_honeypot(c):
continue
fc = fit_components(c)
scored.append((c["candidate_id"], final_score(c, fc, COSINE.get(c["candidate_id"], 0.0))))
comps[c["candidate_id"]] = fc
ordered = order_candidates(scored)[:100]
norm = normalize_scores(ordered) # clean 0-1 scores, same as the submission
rows = []
for rk, (cid, _score) in enumerate(ordered, 1):
c = by_id[cid]
rows.append([
rk, cid, c["profile"]["current_title"],
c["profile"]["years_of_experience"], norm[rk - 1],
template_reasoning(c, comps[cid], rk),
])
summary = (f"**Ranked {len(rows)} candidates.** "
f"Auto-rejected **{len(rejected)}** impossible/honeypot profiles before ranking.")
return summary, rows, rejected
def run_sample():
return rank(_load(SAMPLE))
def run_upload(file):
if file is None:
return ("Upload a `.jsonl` with up to 100 candidate records "
"(schema as in candidate_schema.json)."), [], []
return rank(_load(Path(file.name)))
with gr.Blocks(title="Redrob Candidate Ranker") as demo:
gr.Markdown(
"# Redrob Candidate Ranker — live demo\n"
"Interpretable multi-stage ranker for the Senior AI Engineer JD. "
"Ranks by **title + career substance** (not keyword count), blends dense "
"similarity, applies behavioral/availability modifiers, and **hard-rejects "
"impossible/honeypot profiles**. Reasoning is grounded in each profile.\n\n"
"Repo: https://github.com/RAK2315/redrob-hackathon"
)
with gr.Row():
btn = gr.Button("Run on bundled 100-candidate sample", variant="primary")
up = gr.File(label="…or upload your own .jsonl (<=100)", file_types=[".jsonl"])
status = gr.Markdown()
gr.Markdown("### Ranked candidates")
out = gr.Dataframe(headers=RANKED_HEADERS, wrap=True, interactive=False)
gr.Markdown("### Auto-rejected (honeypots / impossible profiles)")
rej = gr.Dataframe(headers=REJECT_HEADERS, wrap=True, interactive=False)
btn.click(run_sample, outputs=[status, out, rej])
up.change(run_upload, inputs=up, outputs=[status, out, rej])
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)