An AI-powered recruitment matching platform that ranks candidates' resumes against job postings using Vector Similarity Search (FAISS) and a trained XGBoost Machine Learning Classifier.
The TalentMatch system connects a modern Vite-React frontend with a FastAPI backend server. It relies on a high-speed vector search index for candidate matching, backed by a Neon PostgreSQL cloud database for metadata persistence.
graph TD
subgraph Client [React Frontend - Port 5173]
UI[Interactive Dashboard UI]
end
subgraph Server [FastAPI Server - Port 8000]
API[API Router /rank-candidates]
end
subgraph Database [Neon Cloud Database]
PG[(PostgreSQL Tables)]
end
subgraph ML [Machine Learning & Embeddings]
ST[SentenceTransformer model]
FI[FAISS Vector Index]
XG[Trained XGBoost Classifier]
end
UI -->|1. Select Title & Search| API
API -->|2. Query Job Details| PG
API -->|3. Embed Title + Description| ST
API -->|4. Search K-Nearest Resumes| FI
API -->|5. Fetch Candidate Resumes| PG
API -->|6. Compile Features & Run Inference| XG
API -->|7. Return Ranked Candidates| UI
The platform operates through a structured multi-stage data pipeline:
- Resume Cleaning: Raw resumes (
Resume.csv) are trimmed to keepresume_id,resume_text, andcategory, filtering out missing entries. - Job Postings Filtering: Raw postings (
postings.csv) are filtered down to tech-relevant roles (containing keywords like Software, Engineer, Developer, Data, Analyst), sampled to 5,000 items, and aggregated with job skills. - Database Ingestion:
db/setup_db.pycreatescandidatesandjobstables in your Neon PostgreSQL database.db/seed.pyseeds all 2,484 clean resumes and 5,000 clean jobs into PostgreSQL.
- Embed Resumes:
embeddings/embed_resumes.pyconverts all resume texts into dense 384-dimensional vectors using theall-MiniLM-L6-v2SentenceTransformer model, saving the vectors in a NumPy file (resume_embeddings.npy). - FAISS Indexing:
embeddings/faiss_index.pynormalizes these vectors to fit a cosine similarity space and builds a Flat Inner Product index (resume_faiss.index) for high-speed nearest-neighbor retrieval.
- Pairs Creation:
ml/create_training_pairs.pygenerates a balanced dataset of 30,000 matches and non-matches by mapping job titles to relevant/unrelated resume categories. - Feature Extraction:
ml/build_features.pycompiles feature matrices from these pairs (embedding distance, keyword overlap, etc.). - XGBoost Training:
ml/train_model.pytrains an XGBoost classifier, outputs precision/recall scores, and serializes the model tomodels/ranking_model.pkl.
Rather than relying on a hardcoded formula, TalentMatch uses a trained XGBoost Classifier to evaluate candidate suitability.
When a user triggers a candidate search, the backend extracts four distinct features for each retrieved candidate:
- Cosine Similarity (Weight:
0.3377): The semantic vector distance between the job posting (title + description) and the candidate's resume text, calculated usingall-MiniLM-L6-v2embeddings. - Title Keyword Match Ratio (Weight:
0.2675): The percentage of keywords in the job title that directly appear in the candidate's resume text. - Resume Character Length (Weight:
0.2389): The length of the candidate's resume text (helps evaluate resume completeness). - Skill Overlap Ratio (Weight:
0.1558): The fraction of the job's required skill abbreviations (e.g.IT,ENG,MGMT) found in the candidate's resume.
The model evaluates these features for the top candidate matches retrieved by FAISS and predicts the probability that the candidate is a match (0.0 to 1.0). Candidates are returned sorted by this predicted probability (final_score).
Below are the performance metrics of the trained XGBoost classifier evaluated on the test split:
| Metric | Value / Ratio | Definition / Context |
|---|---|---|
| Accuracy | 65.20% |
Total ratio of correctly predicted matches and non-matches. |
| Precision (Match) | 0.65 |
Out of all candidates labeled as a match by the model, how many were true matches. |
| Recall (Match) | 0.65 |
Out of all true matches, how many the model successfully detected. |
| F1-Score (Match) | 0.65 |
Balanced harmonic mean of Precision and Recall. |
Retrieves the list of unique job titles to populate dropdown menus on the UI.
- Endpoint:
GET /job-titles - Response Sample:
{
"titles": [
" Data Architect",
" AVP Underwriter ",
" Cyber Security Analyst 1 - Remote US",
" Software Engineer",
" Lead Semiconductor Engineer"
]
}Retrieves top candidate matches for a specific job title.
- Endpoint:
POST /rank-candidates - Content-Type:
application/json - Request Body:
{
"title": "Software Engineer",
"description": "Looking for a Software Engineer with Python and machine learning experience.",
"top_k": 5
}- Response Sample:
{
"job_title": "Software Engineer",
"results": [
{
"resume_id": 62994611,
"category": "AGRICULTURE",
"similarity": 0.5233,
"skill_overlap": 1.0,
"final_score": 0.9213
},
{
"resume_id": 61579998,
"category": "ENGINEERING",
"similarity": 0.5421,
"skill_overlap": 1.0,
"final_score": 0.9057
},
{
"resume_id": 36434348,
"category": "INFORMATION-TECHNOLOGY",
"similarity": 0.4969,
"skill_overlap": 0.5,
"final_score": 0.8905
}
]
}- Python 3.10+
- Node.js & npm
Create a .env file at the root of the project and add your Neon PostgreSQL connection string:
DATABASE_URL=postgresql://user:password@host/dbname?sslmode=require- Install Python packages:
pip install pandas numpy sentence-transformers faiss-cpu psycopg2-binary sqlalchemy python-dotenv xgboost scikit-learn joblib fastapi uvicorn
- Prep and Clean Data:
python process_data.py
- Set up and Seed Database Tables:
python db/setup_db.py python db/seed.py
- Build Embeddings & Search Index:
python embeddings/embed_resumes.py python embeddings/embed_jobs.py python embeddings/faiss_index.py
- Train Machine Learning Model:
python ml/create_training_pairs.py python ml/build_features.py python ml/train_model.py
- Start the API Server:
python -m uvicorn api.main:app --port 8000
In a new terminal window:
- Navigate to the frontend directory:
cd frontend - Install npm packages:
npm install
- Launch React:
npm run dev
- Open your browser and navigate to
http://localhost:5173/.