Spaces:
Sleeping
Sleeping
| # ============================================================ | |
| # 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() | |