TalentMatch-AI / app.py
Zulkefl07's picture
Update app.py
683fe66 verified
Raw
History Blame Contribute Delete
4.48 kB
# ============================================================
# app.py β€” TalentMatch AI on Hugging Face Spaces
# This file runs the web interface using Gradio.
# Hugging Face automatically runs this file when your Space loads.
# ============================================================
import gradio as gr
import pandas as pd
from preprocess import full_preprocess
from skill_extractor import extract_skills, skill_match_percentage
from matcher import rank_candidates
# ── Load and preprocess data when the app FIRST starts ──────
# This runs ONCE when someone opens the Space β€” then it's ready.
print("Loading dataset...")
df = pd.read_csv("data/ats_resume_dataset_elite_v3.csv")
print("Preprocessing all resumes (this takes ~30 seconds)...")
df['cleaned_resume'] = df['resume_text'].apply(full_preprocess)
print("TalentMatch AI is ready!")
# ── The main function that Gradio calls ──────────────────────
def screen_candidates(job_description, num_results):
"""
Takes a job description and returns the top matching candidates.
This function is called every time someone clicks 'Submit'.
"""
# Handle empty input
if not job_description.strip():
return pd.DataFrame({"Message": ["Please paste a job description in the box above."]})
# Extract skills from the job description
job_skills = extract_skills(job_description)
# Rank all candidates using TF-IDF + Cosine Similarity
top_candidates = rank_candidates(df, job_description, top_n=int(num_results))
# Build a clean results table
results = []
for rank, (_, row) in enumerate(top_candidates.iterrows(), start=1):
resume_skills = extract_skills(str(row['resume_text']))
match_pct = skill_match_percentage(resume_skills, job_skills)
results.append({
'Rank' : rank,
'Resume ID' : row['resume_id'],
'Job Role' : row['job_role'],
'Experience' : f"{row['experience_years']} yrs",
'Education' : row['education_level'],
'ATS Score' : round(row['computed_similarity'], 3),
'Skill Match' : f"{int(match_pct * 100)}%",
'Shortlisted' : 'YES βœ…' if row['shortlisted'] == 1 else 'NO',
})
return pd.DataFrame(results)
# ── Build the Gradio web interface ───────────────────────────
demo = gr.Interface(
fn=screen_candidates,
inputs=[
gr.Textbox(
label="Paste Job Description Here",
placeholder=(
"Example:\n"
"We are looking for a Data Scientist.\n"
"Required skills: Python, Machine Learning, SQL, pandas, scikit-learn.\n"
"Minimum 2 years experience required."
),
lines=7
),
gr.Slider(
minimum=5,
maximum=20,
value=10,
step=1,
label="Number of Top Candidates to Show"
),
],
outputs=gr.Dataframe(
label="Top Matching Candidates β€” Ranked by AI",
wrap=True
),
title="TalentMatch AI β€” ATS Resume Screening System",
description=(
"Built using NLP, TF-IDF Vectorization, and Cosine Similarity. "
"Paste any job description β†’ AI ranks 6,000 resumes in seconds. "
"Built by an Undergraduate CS Student."
),
examples=[
[
"We need a Data Scientist with Python, Machine Learning, TensorFlow, SQL, and pandas. "
"2+ years experience required. Knowledge of NLP and deep learning is a plus.",
10
],
[
"Looking for a Frontend Developer skilled in React, JavaScript, HTML, CSS, and Node.js. "
"Must know REST APIs and Git. Fresh graduates welcome.",
8
],
[
"Hiring ML Engineer with PyTorch, scikit-learn, Docker, AWS, and Python. "
"Must have experience with model deployment and feature engineering.",
10
],
],
theme=gr.themes.Soft(),
)
# ── Launch the app ────────────────────────────────────────────
# On Hugging Face, demo.launch() with no arguments is correct.
# Locally, use demo.launch(share=True) to get a public link.
demo.launch()