A full-stack, RAG-powered resume intelligence platform
Upload any PDF resume β Get instant ATS scoring, AI-driven insights, domain detection, tailored interview questions, and a live chat interface β all powered by a custom vector pipeline and LLM reasoning.
- Overview
- Key Features
- System Architecture
- Tech Stack
- Project Structure
- API Reference
- Getting Started
- Usage Guide
- ATS Scoring Model
- RAG Pipeline
- Environment Variables
- Contributing
- License
AI Resume Analyzer is a production-inspired, modular full-stack application that transforms raw PDF resumes into actionable career intelligence. It leverages a custom Retrieval-Augmented Generation (RAG) pipeline built on sentence-transformers and cosine similarity β without needing a paid vector database β and routes LLM calls through OpenRouter using GPT-4o-mini for cost-effective, high-quality responses.
Use Case: Ideal for job seekers who want to understand how ATS systems evaluate them, get domain-specific feedback, and prepare targeted interview answers β all in one place.
| Feature | Description |
|---|---|
| π PDF Resume Parsing | Extracts clean text from any PDF resume using pdfplumber |
| π§ Domain Detection | Automatically classifies resumes into domains (GenAI, Web Dev, Data Science, DevOps, etc.) via LLM |
| π‘ AI Resume Analysis | Delivers structured improvement suggestions powered by GPT-4o-mini via OpenRouter |
| π Dynamic ATS Scoring | Multi-category scoring algorithm (100-point scale) with a detailed breakdown and missing skill detection |
| β Interview Question Generation | Generates 7 curated questions: 3 Technical, 2 HR, and 2 Project/Viva β tailored to the detected domain |
| π¬ RAG Chatbot | Ask anything about the uploaded resume in a live chat interface backed by semantic vector search |
| β‘ Custom Vector Store | In-memory cosine similarity search using sentence-transformers β zero external vector DB dependency |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β React + Vite Frontend β
β Upload β Analyze β ATS Score β Questions β Chat RAG β
βββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ
β HTTP / REST API
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FastAPI Backend (app.py) β
β β
β POST /upload-resume βββΊ resume_parser.py βββΊ PDF Text β
β β β
β βΌ β
β rag_pipeline.py β
β (Text Splitting + Embeddings) β
β (SimpleVectorStore in-memory) β
β β β
β GET /analyze-resume βββββββββββββββββββ€ β
β GET /ats-score βββ ats_score.py β β
β GET /generate-questions βββββββββββββββ€ β
β POST /chat βββββββββββββββββββ β
β β β
β βΌ β
β question_generator.py β
β (OpenRouter β GPT-4o-mini via utils.py) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Data Flow:
- User uploads a PDF β extracted to plain text via
pdfplumber - Text is chunked (
RecursiveCharacterTextSplitter) and embedded (all-MiniLM-L6-v2) - Embeddings are stored in an in-memory
SimpleVectorStorewith L2-normalized cosine similarity - On each query, the top-k relevant chunks are retrieved and passed as context to the LLM
- The LLM (GPT-4o-mini via OpenRouter) synthesizes responses grounded in the resume content
| Technology | Purpose |
|---|---|
| FastAPI | High-performance async REST API framework |
| pdfplumber | PDF text extraction |
| LangChain | RecursiveCharacterTextSplitter for intelligent text chunking |
| sentence-transformers | all-MiniLM-L6-v2 model for local text embeddings |
| NumPy | Cosine similarity computation for the custom vector store |
| OpenRouter API | LLM gateway (GPT-4o-mini) for analysis, detection, and generation |
| python-dotenv | Secure environment variable management |
| uv | Ultra-fast Python package manager and virtual environment tool |
| Technology | Purpose |
|---|---|
| React 19 | Component-based UI framework |
| Vite 8 | Lightning-fast build tool and dev server |
| Fetch API | Native REST communication with the FastAPI backend |
Resume Project/
β
βββ backend/
β βββ app.py # FastAPI routes: upload, analyze, ATS, questions, chat
β βββ ats_score.py # Rule-based ATS scoring engine (100-point multi-category)
β βββ question_generator.py # LLM calls: domain detection, analysis, Q&A, chat
β βββ rag_pipeline.py # Custom vector store with sentence-transformer embeddings
β βββ resume_parser.py # PDF text extraction using pdfplumber
β βββ utils.py # OpenRouter API client factory
β βββ requirements.txt # Backend-specific Python dependencies
β
βββ frontend/
β βββ src/
β β βββ App.jsx # Main UI: upload, analyze, ATS, questions, RAG chat
β β βββ main.jsx # React app entry point
β βββ index.html
β βββ package.json
β βββ vite.config.js
β
βββ uploads/ # Temporary directory for uploaded PDF files
βββ data/ # Supplementary data / notebook outputs
βββ notebook/ # Jupyter notebooks for experimentation
β
βββ .env # Environment variables (OPENROUTER_API_KEY)
βββ .gitignore
βββ pyproject.toml # Python project config (uv-managed)
βββ requirements.txt # Root-level Python dependencies
βββ README.md
Base URL: http://localhost:8000
Interactive Docs: http://localhost:8000/docs
| Method | Endpoint | Description |
|---|---|---|
POST |
/upload-resume |
Upload a PDF resume; parses text and builds the vector store |
GET |
/analyze-resume |
Detects domain and returns LLM-generated AI suggestions |
GET |
/ats-score |
Returns a 100-point ATS score with category breakdown and missing skills |
GET |
/generate-questions |
Generates 7 tailored interview questions (3 Technical + 2 HR + 2 Project) |
POST |
/chat |
Ask a custom question about the resume; returns a RAG-grounded answer |
POST /upload-resume
// multipart/form-data
// field: file = <your_resume.pdf>
// Response
{ "message": "Resume uploaded and parsed successfully.", "filename": "resume.pdf" }GET /analyze-resume
// Response
{
"domain": "GenAI",
"ai_suggestions": "The candidate demonstrates strong proficiency in RAG pipelines and LangChain..."
}GET /ats-score
// Response
{
"total_score": 78,
"breakdown": {
"Technical Skills": 32,
"Projects": 12,
"Experience": 5,
"Achievements": 6,
"Tools & Platforms": 13,
"Education": 5,
"Resume Structure": 5
},
"missing_skills": ["vector database"]
}POST /chat
// Request
{ "query": "What programming languages does the candidate know?" }
// Response
{ "response": "Based on the resume, the candidate is proficient in Python, JavaScript, and C++." }- Python β₯ 3.14 (managed via
uvor standardvenv) - Node.js β₯ 18.x and npm
- An OpenRouter API Key β get one free at openrouter.ai
Step 1: Clone the repository and navigate to the project root.
git clone <your-repo-url>
cd "Resume Project"Step 2: Create and activate a virtual environment.
# Using Python venv (recommended)
python -m venv .venv
# Activate on Windows
.venv\Scripts\activate
# Activate on macOS / Linux
source .venv/bin/activateTip: If you have
uvinstalled, you can useuv venv && uv syncat the project root instead β it readspyproject.tomlautomatically.
Step 3: Install backend dependencies.
cd backend
pip install -r requirements.txtStep 4: Configure your API key.
Create a .env file in the project root (not inside backend/):
OPENROUTER_API_KEY="sk-or-v1-your-key-here"Step 5: Start the FastAPI development server.
# 1. Activate the virtual environment (Windows)
.venv\Scripts\activate
# OR Activate the virtual environment (macOS/Linux)
source .venv/bin/activate
# 2. Start the API from the project root
uvicorn backend.app:app --reload --port 8000β
The API will be live at http://localhost:8000
π Swagger UI available at http://localhost:8000/docs
Step 1: Open a new terminal and navigate to the frontend directory.
cd frontendStep 2: Install npm dependencies.
npm installStep 3: Start the Vite development server.
npm run devβ
The frontend will be live at http://localhost:5173
Note: Ensure the backend server is running before using the frontend. The frontend calls
http://localhost:8000by default.
This project is configured with a root-level package.json build wrapper. When deploying the repository to Vercel:
- Keep the Vercel Root Directory setting as the default (
/repository root). - Vercel will automatically run
npm run buildfrom the root, which delegates dependency installation and compilation to thefrontend/folder, then moves the static output into the rootdist/directory for zero-config hosting.
- Open the frontend in your browser at
http://localhost:5173 - Upload Resume β Click "Upload" and select any
.pdfresume. The backend will extract text and build the semantic vector store. - Analyze Resume β Click "Analyze Resume" to detect the candidate's domain (e.g., GenAI, Web Development) and receive AI-powered suggestions.
- Get ATS Score β Click "Get ATS Score" to see a 100-point score with a detailed breakdown across 7 categories, plus a list of missing skills for the detected domain.
- Generate Questions β Click "Generate Questions" to receive 7 interview questions (3 Technical, 2 HR, 2 Project-based) tailored to the resume content and domain.
- Chat with Resume β Type any question in the chat box (e.g., "What are the candidate's top projects?") and receive a RAG-grounded answer sourced directly from the resume.
The scoring engine (ats_score.py) uses a rule-based, multi-weighted algorithm across 7 categories:
| Category | Max Points | Scoring Logic |
|---|---|---|
| Technical Skills | 40 | Core AI/ML keywords (Γ2), related tech keywords (Γ1), proficiency multiplier |
| Projects | 15 | Project section presence, quantified metrics, deployment signals |
| Experience | 10 | Years of experience detected via regex; intern experience credited |
| Achievements | 10 | Awards, certifications, patents, publications detected |
| Tools & Platforms | 15 | Docker, Git, cloud platforms, databases, frameworks |
| Education | 5 | Degree level detected; CGPA/GPA mentioned |
| Resume Structure | 5 | Presence of standard sections; use of bullet points |
Domain-aware missing skill detection is also performed post-scoring:
- GenAI domain β checks for:
llm,rag,embeddings,vector database - Web Development β checks for:
react,node.js,database,api
The custom RAG implementation in rag_pipeline.py is entirely dependency-free from paid vector databases:
Resume PDF Text
β
βΌ
RecursiveCharacterTextSplitter (chunk_size=400, overlap=50)
β
βΌ
SentenceTransformer("all-MiniLM-L6-v2") β float32 embeddings
β
βΌ
L2 Normalization β SimpleVectorStore (in-memory NumPy array)
β
βΌ
Query β encode β cosine similarity β top-k chunks β LLM context
Why this design?
- No FAISS, Chroma, or Pinecone dependency β runs on any machine
all-MiniLM-L6-v2is a fast, lightweight 384-dim model optimized for semantic similarity- L2 normalization converts dot product to cosine similarity for accurate ranking
| Variable | Required | Description |
|---|---|---|
OPENROUTER_API_KEY |
β Yes | Your OpenRouter API key for LLM access (GPT-4o-mini) |
OPENROUTER_MAX_TOKENS |
β No | Centralized maximum token limit (integer clamped between 256 and 4096; defaults to 4096) |
Create a .env file in the project root:
OPENROUTER_API_KEY="sk-or-v1-your-key-here"
OPENROUTER_MAX_TOKENS=4096
β οΈ Never commit your.envfile to version control. It is already listed in.gitignore.
Contributions, issues, and feature requests are welcome!
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature-name - Commit your changes:
git commit -m 'feat: add your feature' - Push to the branch:
git push origin feature/your-feature-name - Open a Pull Request
Ideas for contributions:
- Add support for DOCX resume formats
- Implement persistent storage (SQLite / PostgreSQL) for multi-user sessions
- Add a structured PDF export of the analysis report
- Build a comparison mode for multiple resumes
This project is licensed under the MIT License.
Feel free to use, modify, and distribute it for personal or commercial projects.
Built with β€οΈ using FastAPI, React, LangChain, and OpenRouter
API Docs β’ OpenRouter β’ Sentence Transformers