← Back to projects

HR Resume Screening Tool

A Flask web app that ranks uploaded resumes against a job description using TF-IDF cosine similarity, and generates an AI summary of each candidate using Google's Gemini model via LangChain.

Generative AI · Applied Build Flask LangChain + Gemini

Overview

Screening a stack of resumes against a single job description is repetitive, manual work. This app automates the first pass: an HR user logs in, pastes a job description, uploads a batch of PDF resumes, and gets back a ranked shortlist — each candidate scored by relevance and summarized in plain language.

How it works

1. Text extraction — each uploaded PDF resume is parsed with PyPDF2 to pull raw text.

2. Relevance ranking — the job description and every resume are vectorized with TfidfVectorizer, then ranked by cosine similarity against the job description, surfacing the closest match first.

3. AI summarization — each resume's text is sent to Gemini 1.5 Flash through LangChain's ChatGoogleGenerativeAI, producing a short summary alongside its score.

4. Persistence — job descriptions, resume text, scores, and summaries are logged to a local SQLite database for later review.

Core ranking logic

def rank_resumes(job_description, resumes):
    from sklearn.feature_extraction.text import TfidfVectorizer
    from sklearn.metrics.pairwise import cosine_similarity

    documents = [job_description] + resumes
    vectorizer = TfidfVectorizer().fit_transform(documents)
    vectors = vectorizer.toarray()

    job_vector = vectors[0]
    resume_vectors = vectors[1:]

    return cosine_similarity([job_vector], resume_vectors).flatten()

# Gemini-powered candidate summary, via LangChain
def summarize_text(text):
    llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", google_api_key=google_api_key)
    prompt = f"Summarize the following pdf resumes: {text[:1500]}"
    return llm.invoke(prompt).content.strip()

Screenshots

Tech stack

FlaskWeb app framework
PyPDF2PDF text extraction
scikit-learnTF-IDF + cosine similarity
LangChainLLM orchestration
Gemini 1.5 FlashCandidate summarization
SQLiteResult persistence
This is a coursework prototype, shown here as source code and screenshots rather than a live demo — GitHub Pages only serves static files, and the app needs a Python/Flask server plus a Gemini API key to run. The .env file holding that API key is intentionally excluded from this repository.
Back to the start

AEROVANT →