| import os |
| import json |
| import pickle |
| import time |
| from pathlib import Path |
|
|
| from src.hard_filter import apply_hard_filter |
| from src.raw_score import compute_raw_scores |
| from src.availability import apply_multipliers |
| from src.output import write_submission |
|
|
| def run_pipeline(candidates_path: str, jd_path: str, output_path: str): |
| """Executes the complete candidate vetting, scoring, and ranking pipeline.""" |
| start_time = time.perf_counter() |
| |
| print("=" * 60) |
| print("STARTING VETTLY CANDIDATE SCORING AND FILTERING PIPELINE") |
| print("=" * 60) |
| |
| |
| cand_path = Path(candidates_path) |
| job_desc_path = Path(jd_path) |
| out_path = Path(output_path) |
| |
| |
| if not cand_path.exists(): |
| for alt in [Path("data").joinpath(cand_path.name), Path("[PUB] India_runs_data_and_ai_challenge").joinpath("India_runs_data_and_ai_challenge").joinpath(cand_path.name)]: |
| if alt.exists(): |
| cand_path = alt |
| break |
| |
| if not job_desc_path.exists(): |
| for alt in [Path("data").joinpath(job_desc_path.name), Path("[PUB] India_runs_data_and_ai_challenge").joinpath("India_runs_data_and_ai_challenge").joinpath(job_desc_path.name)]: |
| if alt.exists(): |
| job_desc_path = alt |
| break |
| |
| print(f"Candidates Path: {cand_path.resolve()}") |
| print(f"Job Description Path: {job_desc_path.resolve()}") |
| print(f"Output Path: {out_path.resolve()}") |
| |
| |
| if not cand_path.exists(): |
| raise FileNotFoundError(f"Candidates file not found at: {cand_path}") |
| if not job_desc_path.exists(): |
| raise FileNotFoundError(f"Job description file not found at: {job_desc_path}") |
| |
| print("Loading datasets...") |
| if str(cand_path).endswith(".jsonl"): |
| with open(cand_path, "r", encoding="utf-8") as f: |
| candidates = [json.loads(line) for line in f] |
| else: |
| with open(cand_path, "r", encoding="utf-8") as f: |
| candidates = json.load(f) |
| |
| with open(job_desc_path, "r", encoding="utf-8") as f: |
| jd = json.load(f) |
| |
| print(f"Loaded {len(candidates)} candidates.") |
| |
| |
| |
| precomputed_dir = cand_path.parent / "precomputed" |
| tfidf_path = precomputed_dir / "tfidf.pkl" |
| |
| if not tfidf_path.exists(): |
| |
| script_dir = Path(__file__).resolve().parent |
| tfidf_path = script_dir.parent / "data" / "precomputed" / "tfidf.pkl" |
| |
| print(f"Loading TF-IDF Vectorizer from: {tfidf_path}") |
| with open(tfidf_path, "rb") as f: |
| tfidf = pickle.load(f) |
| |
| |
| print("\n--- STAGE 1: Applying Hard Filters ---") |
| survivors, killed = apply_hard_filter(candidates, jd, tfidf) |
| print(f"Killed: {len(killed)} candidates.") |
| print(f"Surviving: {len(survivors)} candidates.") |
| |
| if not survivors: |
| print("WARNING: No candidates survived the hard filters! Pipeline exiting early.") |
| return |
| |
| |
| print("\n--- STAGE 2: Computing Raw Scores ---") |
| raw_scored = compute_raw_scores(survivors, jd) |
| |
| |
| print("\n--- STAGE 3: Applying Behavioral Multipliers ---") |
| final_scored = apply_multipliers(raw_scored, jd) |
| |
| |
| print("\n--- STAGE 4: Generating Output ---") |
| df_final = write_submission(final_scored, jd, str(out_path)) |
| |
| elapsed_time = time.perf_counter() - start_time |
| print("=" * 60) |
| print(f"PIPELINE EXECUTED IN {elapsed_time:.2f} SECONDS") |
| print("=" * 60) |
| |
| |
| print("\nTOP 10 CANDIDATES:") |
| print(df_final.head(10)) |
|
|
| if __name__ == "__main__": |
| |
| default_candidates = "data/candidates.json" |
| default_jd = "data/job_description.json" |
| default_output = "submission.csv" |
| |
| run_pipeline(default_candidates, default_jd, default_output) |
|
|