Spaces:
Sleeping
Sleeping
| import os | |
| import numpy as np | |
| from src.jd import JD_TEXT, PROFICIENCY_WEIGHT | |
| MODEL_NAME = "paraphrase-MiniLM-L6-v2" | |
| CACHE_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), ".model_cache") | |
| def _build_text(candidate: dict) -> str: | |
| p = candidate["profile"] | |
| parts = [ | |
| p.get("headline", ""), | |
| p.get("summary", ""), | |
| p.get("current_title", ""), | |
| ] | |
| for job in candidate.get("career_history", [])[:2]: | |
| parts.append(job.get("description", "")) | |
| skills_text = " ".join( | |
| s["name"] for s in sorted( | |
| candidate.get("skills", []), | |
| key=lambda x: PROFICIENCY_WEIGHT.get(x["proficiency"], 0), | |
| reverse=True, | |
| )[:15] | |
| ) | |
| parts.append(skills_text) | |
| return " ".join(filter(None, parts))[:1000] | |
| def refine_scores(scored_batch: list[dict]) -> None: | |
| try: | |
| from sentence_transformers import SentenceTransformer | |
| model = SentenceTransformer(MODEL_NAME, cache_folder=CACHE_DIR) | |
| jd_vec = model.encode([JD_TEXT], convert_to_numpy=True, show_progress_bar=False)[0] | |
| jd_norm = jd_vec / (np.linalg.norm(jd_vec) + 1e-9) | |
| texts = [_build_text(s["c"]) for s in scored_batch] | |
| vecs = model.encode(texts, convert_to_numpy=True, show_progress_bar=False, batch_size=64) | |
| for i, s in enumerate(scored_batch): | |
| v = vecs[i] / (np.linalg.norm(vecs[i]) + 1e-9) | |
| sim = float(np.dot(jd_norm, v)) | |
| sem = (sim + 1) / 2.0 | |
| s["score"] = s["score"] * 0.80 + sem * 0.20 | |
| s["components"]["semantic_score"] = round(sem, 3) | |
| except Exception as e: | |
| print(f" embed step skipped: {e}") | |