*This is a personal GitHub project built to showcase this work in my portfolio.
Resume/JD Comparator is an AI-assisted tool that helps recruiters and hiring teams quickly evaluate resume-to-role fit. It exposes two features:
You paste a job description and a candidate resume, and the app returns a structured assessment with:
- overall fit score
- key matching strengths
- concise reasoning grounded in the provided documents
This is a fast first-pass screening aid, or a quick way to check whether a single resume matches a target job. It runs a single LLM scoring call and returns strict JSON.
You pick a job description already saved in the system, and the app will find the best-matching candidates from the pool of resumes.
It works in two steps: first it quickly narrows the whole resume pool down to a short list of the most relevant ones, then it runs the deeper AI review (the same one used in feature 1) on just that short list to rank them. This way the heavier AI work only runs on candidates that are actually worth a closer look.
- RAG pre-filter — the JD is embedded and matched against all stored resumes in Qdrant
- LLM analysis — each shortlisted resume is run through the same Compare pipeline, and ranked by score
Resumes and job descriptions are added from the "Add a JD/Resume" tab.
- Frontend: Vue 3 + Vite + Tailwind
- Backend: Python (Flask)
- LLM scoring: a single LLM call returns strict JSON for both features.
- RAG store: Qdrant vector database holding separate
resumesandjob_descriptionscollections. - Document store: SQLite holds the raw text of each resume/JD plus the Qdrant chunk ids generated for it.
- LLM runtime: local Ollama (
llmDocker service) or Gemini via Vertex AI.
Use Docker Compose to run everything (frontend + backend + local LLM + Qdrant vector store).
-
Copy the env template, and fill the values:
cp .env.example .env
-
Start containers:
docker compose up -d --build
-
Open the app:
- Frontend: http://localhost:9919
- Backend API:
http://localhost:5000 - Qdrant dashboard: http://localhost:6333/dashboard
-
Seed the database + RAG store (required for the "Find the Best Match" feature). The "Find the Best Match" feature needs job descriptions and resumes already stored and embedded. Run the populate script once against the running backend to download a sample of resumes + job descriptions from HuggingFace and ingest them (into both SQLite and Qdrant):
python scripts/populate.py
You can also add documents one at a time from the "Add a JD/Resume" tab in the UI.
-
In Google Cloud, enable
Vertex AI API, create a service account with Vertex AI User role, and create a JSON key for it. -
Download the key, and then, in
.env, setGOOGLE_CREDENTIALS_FILEto the path of that file on your machine, and add the other Vertex settings:LLM_PROVIDER=gemini-vertex LLM_MODEL=gemini-2.5-flash-lite GOOGLE_CLOUD_PROJECT=your-project-id GOOGLE_CLOUD_LOCATION=global GOOGLE_CREDENTIALS_FILE=$HOME/.config/google/vertex-credentials.jsonThe file is mounted into the container at
/opt/vertex-credentials.jsonand used for authentication. -
Start containers:
docker compose up -d --build
- Traces for LangChain model calls are sent to LangSmith when tracing is enabled.
- Frontend Cloudflare Pages : builds and deploy on push to
main - Backend AWS EC2 : GitHub Actions builds the Docker image, pushes to AWS ECR, then SSHs into EC2 to pull and restart the container
Note: The public demo is currently offline. The deployment pipeline remains fully functional and can be re-enabled at any time.
- Typed runtime config is centralized in
backend/infrastructure/config/settings.py.
- Focus only on skills, experience, and qualifications.
- Pasted job description and resume are sent as-is to the AI provider. (see later updates below)
- Constrain outputs to strict JSON objects.

