gw0/jobfit-jevbench

Dataset

JobFit-JevBench

2

8 commits

2 linked in READMEs

updated Oct 9, 2026

See the code

README

JobFit-JevBench

GitHub HF Dataset HF Model HF Space CD Sponsor

A CV/job-post fit-scoring benchmark: 250 synthetic CVs, 404 job postings and 5,000 CV/job pairs, each judged on 17 questions with a score and a confidence. It trains and evaluates jobfit-model, a Jev-like typed-decision model (a state plus typed questions in, one typed answer per question id out).

Layout

questions.json      # the 17 questions: type, name, scope, question text, 5 criteria
cvs/*.md            # synthetic CVs, plain markdown
jobs/<company>/*.md # job postings, markdown with YAML frontmatter
labels/             # LLM-judge labels, one JSON object per line
splits/             # which pairs belong to train / val / test / calib

Files

cvs/<name>.md: a synthetic CV.

jobs/<company>/<posted_at>-<slug>.md: a job posting. Frontmatter keys: company, title, location, url (source page), posted_at.

questions.json: an object keyed by question id. Each entry has type (score), name, scope (pairwise, cv or job), question and criteria (5 level descriptions). Scores are on a 0–1 scale; the 5 levels map to 0, 0.25, 0.5, 0.75, 1.

scopequestion ids
pairwise (13)skills_match, experience_level_match, domain_industry_relevance, education_qualifications_match, seniority_role_level_fit, career_trajectory_fit, responsibilities_overlap, location_work_arrangement_fit, soft_skills_match, recency_of_relevant_experience, overall_fit, interview_readiness, culture_company_alignment
cv (2)cv_clarity_structure_quality, cv_likely_llm_generated
job (2)job_post_clarity_structure_quality, job_post_likely_llm_generated

labels/pairs.jsonl (5,000 rows): cv, job (paths relative to the corpus root), then <id>_score and <id>_confidence for each of the 13 pairwise ids, and labeling_method. Confidence is the judge's 0–1 certainty in its score.

labels/cvs.jsonl (250 rows): cv, then _score / _confidence for the 2 cv ids.

labels/jobs.jsonl (404 rows): job, then _score / _confidence for the 2 job ids.

labels/*_double.jsonl: a second, independent rating of a subset (300 pairs, 25 CVs, 87 jobs), same columns as the files above. Use them to measure inter-rater agreement.

splits/{train,val,test,calib}.jsonl (3,500 / 500 / 500 / 500 rows): {cv, job} keys only. Join on (cv, job) with labels/pairs.jsonl to get labels:

from datasets import load_dataset

root = "hf://datasets/gw0/jobfit-jevbench"
pairs = load_dataset("json", data_files=f"{root}/labels/pairs.jsonl", split="train").to_pandas()
test = load_dataset("json", data_files=f"{root}/splits/test.jsonl", split="train").to_pandas()
test = test.merge(pairs, on=["cv", "job"])

Construction

  • Jobs: public Greenhouse, Lever, Ashby and Workday (4 tenants) posting pages, at most 10 per company.
  • CVs: generated by an LLM over a seeded role / seniority / location / style grid.
  • Pairs: 20 jobs per CV, half the nearest by TF-IDF and half random, so fit labels spread over the whole scale instead of piling up at "no fit".
  • Splits: test is fully held out (its CVs appear nowhere else). train, val and calib are CV-disjoint from each other; jobs are shared across all four.
  • Labels: LLM-judged, one call per document and per pair, by claude-sonnet-5. The *_double files come from the second rater claude-opus-5-5. labeling_method records the rater per row.
  • *_likely_llm_generated is a model's estimate, not ground truth.

Job fetching (data/fetch_jobs/), CV generation, labelling and PII scrubbing (data/pii_scrub.py) live in jobfit-model.

Limitations

  • Labels come from LLM judges, not human recruiters; they carry the judges' biases. Compare against *_double for rater noise.
  • CVs are synthetic and stylistically more uniform than real ones; they are all English.
  • Job postings come from a few tech-oriented companies and reflect their 2026 hiring.
  • test has only 25 distinct CVs, so per-CV statistics are noisy; bootstrap over CVs.

Job-post sources

The dataset is for non-commercial ML research and demo use. Per-source review of public robots.txt and terms of service (2026-10-09) (engineering-level, not a legal opinion).

Source (posts)robots.txtTerms
Ashby (236)disallows /meeting/, /b/, /api/, none fetchedcustomer terms bind Ashby's customers; nothing found on readers of public pages
Greenhouse (116)no active rules on job pagesagreement unreachable; no anti-scraping clause found
Workday (40)careers sites allowed; only /refreshFacet/ and internal sites disallowedno public terms found; employer policy applies
Lever (12)Allow: /, Crawl-delay: 1ToS page unreachable; no clause found
  • Fetches are identified (descriptive, non-spoofed User-Agent) and rate-limited. Workday is fetched through its /wday/cxs/ JSON endpoints, which robots.txt does not name.
  • Vendor agreements were unreachable or are not written for readers, so no restriction is ruled out.
  • Get a legal review per source before any commercial use, or if a publisher or vendor objects.

License

Copyright © 2026 gw0 [email protected]. Licensed under AGPL-3.0-or-later.

CVs are synthetic. Job posts come from public Greenhouse, Lever, Ashby and Workday pages, keep their source url, and remain under their publishers' rights and licenses. Not a legal opinion.

If my work saves you time, money, or tokens, consider sponsoring the work that keeps it maintained — and tell whoever else benefits, human or agent.

job-matching
llm-as-judge
resume

gw0/jobfit-jevbench

Dataset

JobFit-JevBench

2

8 commits

2 linked in READMEs

updated Oct 9, 2026

See the code

README

JobFit-JevBench

GitHub HF Dataset HF Model HF Space CD Sponsor

A CV/job-post fit-scoring benchmark: 250 synthetic CVs, 404 job postings and 5,000 CV/job pairs, each judged on 17 questions with a score and a confidence. It trains and evaluates jobfit-model, a Jev-like typed-decision model (a state plus typed questions in, one typed answer per question id out).

Layout

questions.json      # the 17 questions: type, name, scope, question text, 5 criteria
cvs/*.md            # synthetic CVs, plain markdown
jobs/<company>/*.md # job postings, markdown with YAML frontmatter
labels/             # LLM-judge labels, one JSON object per line
splits/             # which pairs belong to train / val / test / calib

Files

cvs/<name>.md: a synthetic CV.

jobs/<company>/<posted_at>-<slug>.md: a job posting. Frontmatter keys: company, title, location, url (source page), posted_at.

questions.json: an object keyed by question id. Each entry has type (score), name, scope (pairwise, cv or job), question and criteria (5 level descriptions). Scores are on a 0–1 scale; the 5 levels map to 0, 0.25, 0.5, 0.75, 1.

scopequestion ids
pairwise (13)skills_match, experience_level_match, domain_industry_relevance, education_qualifications_match, seniority_role_level_fit, career_trajectory_fit, responsibilities_overlap, location_work_arrangement_fit, soft_skills_match, recency_of_relevant_experience, overall_fit, interview_readiness, culture_company_alignment
cv (2)cv_clarity_structure_quality, cv_likely_llm_generated
job (2)job_post_clarity_structure_quality, job_post_likely_llm_generated

labels/pairs.jsonl (5,000 rows): cv, job (paths relative to the corpus root), then <id>_score and <id>_confidence for each of the 13 pairwise ids, and labeling_method. Confidence is the judge's 0–1 certainty in its score.

labels/cvs.jsonl (250 rows): cv, then _score / _confidence for the 2 cv ids.

labels/jobs.jsonl (404 rows): job, then _score / _confidence for the 2 job ids.

labels/*_double.jsonl: a second, independent rating of a subset (300 pairs, 25 CVs, 87 jobs), same columns as the files above. Use them to measure inter-rater agreement.

splits/{train,val,test,calib}.jsonl (3,500 / 500 / 500 / 500 rows): {cv, job} keys only. Join on (cv, job) with labels/pairs.jsonl to get labels:

from datasets import load_dataset

root = "hf://datasets/gw0/jobfit-jevbench"
pairs = load_dataset("json", data_files=f"{root}/labels/pairs.jsonl", split="train").to_pandas()
test = load_dataset("json", data_files=f"{root}/splits/test.jsonl", split="train").to_pandas()
test = test.merge(pairs, on=["cv", "job"])

Construction

  • Jobs: public Greenhouse, Lever, Ashby and Workday (4 tenants) posting pages, at most 10 per company.
  • CVs: generated by an LLM over a seeded role / seniority / location / style grid.
  • Pairs: 20 jobs per CV, half the nearest by TF-IDF and half random, so fit labels spread over the whole scale instead of piling up at "no fit".
  • Splits: test is fully held out (its CVs appear nowhere else). train, val and calib are CV-disjoint from each other; jobs are shared across all four.
  • Labels: LLM-judged, one call per document and per pair, by claude-sonnet-5. The *_double files come from the second rater claude-opus-5-5. labeling_method records the rater per row.
  • *_likely_llm_generated is a model's estimate, not ground truth.

Job fetching (data/fetch_jobs/), CV generation, labelling and PII scrubbing (data/pii_scrub.py) live in jobfit-model.

Limitations

  • Labels come from LLM judges, not human recruiters; they carry the judges' biases. Compare against *_double for rater noise.
  • CVs are synthetic and stylistically more uniform than real ones; they are all English.
  • Job postings come from a few tech-oriented companies and reflect their 2026 hiring.
  • test has only 25 distinct CVs, so per-CV statistics are noisy; bootstrap over CVs.

Job-post sources

The dataset is for non-commercial ML research and demo use. Per-source review of public robots.txt and terms of service (2026-10-09) (engineering-level, not a legal opinion).

Source (posts)robots.txtTerms
Ashby (236)disallows /meeting/, /b/, /api/, none fetchedcustomer terms bind Ashby's customers; nothing found on readers of public pages
Greenhouse (116)no active rules on job pagesagreement unreachable; no anti-scraping clause found
Workday (40)careers sites allowed; only /refreshFacet/ and internal sites disallowedno public terms found; employer policy applies
Lever (12)Allow: /, Crawl-delay: 1ToS page unreachable; no clause found
  • Fetches are identified (descriptive, non-spoofed User-Agent) and rate-limited. Workday is fetched through its /wday/cxs/ JSON endpoints, which robots.txt does not name.
  • Vendor agreements were unreachable or are not written for readers, so no restriction is ruled out.
  • Get a legal review per source before any commercial use, or if a publisher or vendor objects.

License

Copyright © 2026 gw0 [email protected]. Licensed under AGPL-3.0-or-later.

CVs are synthetic. Job posts come from public Greenhouse, Lever, Ashby and Workday pages, keep their source url, and remain under their publishers' rights and licenses. Not a legal opinion.

If my work saves you time, money, or tokens, consider sponsoring the work that keeps it maintained — and tell whoever else benefits, human or agent.

job-matching
llm-as-judge
resume