Resume-ATS-Fit

A smart AI model that helps match resumes with job descriptions

This model was created to solve a common problem in hiring: How well does a candidate's resume fit a job?

It works like a smart assistant that reads both the resume and the job description, then gives a score showing how good the match is.

Why This Model Was Made

Traditional ATS (Applicant Tracking Systems) often miss good candidates because they only look for exact keywords.
This model understands meaning and context, not just keywords.

How It Works (Simple Explanation)

  1. The model turns both the resume and job description into numbers (embeddings).
  2. It calculates how similar these two sets of numbers are (using cosine similarity).
  3. Based on the similarity score, it decides:
    • Good Fit β†’ Strong match
    • Potential Fit β†’ Moderate match
    • No Fit β†’ Weak match

Training Details

  • Base Model: nomic-ai/nomic-embed-text-v1 (a strong open-source embedding model)
  • Dataset Used: med2425/resume-job-fit-merged-v1
  • Training Hardware: NVIDIA RTX 5090 (32GB VRAM)
  • Training Method: Contrastive Learning (InfoNCE) with Hard Negative Penalty
  • Best Epoch: 33

Performance on Official Test Set

Metric Score What it means
F1 Good Fit 0.8299 How accurately the model finds real Good Fit resumes
Macro F1 0.8987 Overall accuracy across both Good Fit and No Fit
ROC-AUC 0.9734 How well the model ranks candidates (very high = excellent)
Gap 0.1290 How much better Good Fit resumes score compared to No Fit ones

How to Use the Model

Simple Code Example

from transformers import AutoTokenizer
import torch

# Load the model
tokenizer = AutoTokenizer.from_pretrained("med2425/resume-ats-fit", trust_remote_code=True)
model = NomicContrastive("nomic-ai/nomic-embed-text-v1", pooling="mean").to("cuda")

# Load weights
model.load_state_dict(torch.load("pytorch_model.bin", map_location="cuda")["model_state_dict"])
model.eval()

def check_match(resume_text, job_description, threshold=0.65):
    # Tokenize
    resume_enc = tokenizer(resume_text, truncation=True, max_length=4096, return_tensors="pt").to("cuda")
    jd_enc = tokenizer(job_description, truncation=True, max_length=2048, return_tensors="pt").to("cuda")
    
    with torch.no_grad():
        r_emb, j_emb = model(resume_enc["input_ids"], resume_enc["attention_mask"],
                             jd_enc["input_ids"], jd_enc["attention_mask"])
        similarity = torch.sum(r_emb * j_emb, dim=1).item()
    
    if similarity >= 0.75:
        return "βœ… Strong Good Fit", round(similarity, 4)
    elif similarity >= 0.65:
        return "⚠️ Potential Fit", round(similarity, 4)
    else:
        return "❌ No Fit", round(similarity, 4)

# Example usage
resume = "Your candidate resume text here..."
jd = "Your job description here..."

result, score = check_match(resume, jd)
print(f"Result: {result} (Score: {score})")

Citation

@misc{resume-ats-fit,
  title = {Resume ATS Fit},
  author = {Mohamed Douali},                   
  year = {2026},
  publisher = {Hugging Face},
  howpublished = {\url{https://huggingface.co/med2425/resume-ats-fit}}
}
Downloads last month
161
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ 1 Ask for provider support