# ============================================================ # matcher.py # This file is the HEART of the project. # It calculates how similar a resume is to a job description # using TF-IDF and Cosine Similarity. # ============================================================ from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity import pandas as pd def build_tfidf_vectorizer(): """ Creates a TF-IDF Vectorizer. TF-IDF stands for Term Frequency-Inverse Document Frequency. It converts text into numbers. Words that appear a lot in one resume but rarely in others get a HIGH score (they are more important/unique). Common words like 'the', 'is', 'a' get a LOW score. ngram_range=(1,2) means we look at: - single words: 'python', 'machine' - word pairs: 'machine learning', 'deep learning' max_features=5000 means we only keep the top 5000 words. """ vectorizer = TfidfVectorizer( ngram_range=(1, 2), # use single words AND word pairs max_features=5000, # keep only top 5000 important words min_df=2, # ignore words that appear in less than 2 documents max_df=0.95, # ignore words that appear in 95%+ of all documents stop_words='english' # auto-remove common English words ) return vectorizer def calculate_similarity(resume_text, job_text): """ Calculates how similar ONE resume is to ONE job description. Steps: 1. Combine both texts 2. Convert them to TF-IDF vectors (numbers) 3. Use cosine similarity to compare the two vectors Cosine Similarity returns a value between 0 and 1: - 1.0 = perfect match - 0.0 = completely different Think of it like measuring the angle between two arrows — if they point in the same direction, they are very similar! """ vectorizer = build_tfidf_vectorizer() # Fit and transform both texts together tfidf_matrix = vectorizer.fit_transform([resume_text, job_text]) # Calculate cosine similarity between resume (row 0) and job (row 1) score = cosine_similarity(tfidf_matrix[0:1], tfidf_matrix[1:2]) return round(float(score[0][0]), 4) # return as a clean number def rank_candidates(df, job_description, resume_col='cleaned_resume', top_n=10): """ Ranks ALL candidates in the dataset against a given job description. Steps: 1. Vectorize all resumes + job description together 2. Calculate similarity of EACH resume vs. job description 3. Sort by similarity score (highest first) 4. Return the top N candidates Parameters: df - the DataFrame with all resumes job_description - the job description text (already cleaned) resume_col - which column has the cleaned resume text top_n - how many top candidates to return (default: 10) """ # Combine all resumes + job description into one list all_texts = list(df[resume_col].values) + [job_description] # Build TF-IDF vectors for everything vectorizer = build_tfidf_vectorizer() tfidf_matrix = vectorizer.fit_transform(all_texts) # The job description vector is the LAST item job_vector = tfidf_matrix[-1] # Calculate similarity of each resume vs. job description similarities = cosine_similarity(tfidf_matrix[:-1], job_vector) # Add the scores back to the DataFrame (copy to avoid warnings) ranked_df = df.copy() ranked_df['computed_similarity'] = similarities.flatten() # Sort by similarity score — best match first ranked_df = ranked_df.sort_values( by='computed_similarity', ascending=False ).reset_index(drop=True) # Return only the top N results return ranked_df.head(top_n)