Skip to content

ismail-kattakath/resume-optimizer

Repository files navigation

Resume Optimizer

A multi-agent system that optimizes resumes for specific job descriptions using LLM-powered analysis.

Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                         RESUME OPTIMIZER FLOW                               │
└─────────────────────────────────────────────────────────────────────────────┘

  INPUTS
  ══════
  ┌──────────────┐    ┌──────────────────┐
  │ resume.json  │    │ job-description  │
  │   (your CV)  │    │     .txt (JD)    │
  └──────┬───────┘    └────────┬─────────┘
         │                     │
         └──────────┬──────────┘
                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                        GRAPH EXECUTION (3 LLM calls)                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   ┌─────────────────┐      ┌─────────────────┐      ┌─────────────────┐    │
│   │  JobAnalyzer    │      │  ResumeWriter   │      │   ATSScorer     │    │
│   │    (Agent)      │─────▶│    (Agent)      │─────▶│    (Agent)      │    │
│   └─────────────────┘      └─────────────────┘      └─────────────────┘    │
│          │                        │                        │               │
│          ▼                        ▼                        ▼               │
│   ┌─────────────────┐      ┌─────────────────┐      ┌─────────────────┐    │
│   │ Extracts:       │      │ Optimizes:      │      │ Evaluates:      │    │
│   │ - Tech stack    │      │ - Title/label * │      │ - ATS score     │    │
│   │ - Domains       │      │ - Summary       │      │ - Match %       │    │
│   │ - Principles    │      │ - Skills order  │      │ - Suggestions   │    │
│   │                 │      │ - Highlights    │      │                 │    │
│   └─────────────────┘      └─────────────────┘      └─────────────────┘    │
│                                                                             │
│   Output: Markdown         Output: Raw text         Output: Markdown       │
│   (used as-is)             (needs extraction)       (used as-is)           │
│                                                                             │
│   * Title/label is used for output folder naming                           │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                   STRUCTURED EXTRACTION (1 LLM call)                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   JobAnalyzer   → Markdown saved as-is (no extra LLM call)                 │
│   ResumeWriter  → structured_output() → ResumeSchema (complex, needs LLM)  │
│   ATSScorer     → Markdown saved as-is (no extra LLM call)                 │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
                    │
                    ▼
  OUTPUTS
  ═══════
  ┌───────────────────────────────────────┐
  │  output/<position-slug>/              │
  │    ├── resume.json    (structured)    │
  │    └── ats_report.md (plain)    │
  └───────────────────────────────────────┘

Agents

Agent Role Output Format
JobAnalyzer Extract domains, tech stack, principles from JD Markdown (saved as-is)
ResumeWriter Update title to match position, rewrite summary, reorder skills, tailor highlights Raw text → structured via LLM
ATSScorer Evaluate resume-JD match, provide score and suggestions Markdown (saved as-is)

LLM Call Flow

The system makes 4 LLM calls total:

  1. Graph execution (3 calls): JobAnalyzer → ResumeWriter → ATSScorer
  2. Structured extraction (1 call): Only ResumeWriter output needs LLM parsing

Why This Design?

  • JobAnalyzer: Markdown analysis → saved directly, no parsing needed
  • ResumeWriter: Complex nested schema (ResumeSchema) → needs structured_output() for reliability
  • ATSScorer: Markdown report → saved directly to file, no parsing needed

Output Folder Naming

The output folder name is derived from basics.label in the optimized resume (the position title set by ResumeWriter):

  • ResumeWriter sets basics.label to match the target position
  • This label is slugified: "Senior Software Engineer"senior-software-engineer
  • Output saved to: output/senior-software-engineer/

Installation

Local Installation

pip install -r requirements.txt -r gradio_requirements.txt

Docker Installation

docker compose build

Configuration

Create a .env file or set environment variables:

# Model configuration
STRANDS_MODEL_ID=qwen/qwen3-coder-30b
STRANDS_API_KEY=not-needed
STRANDS_BASE_URL=http://10.0.0.28:1234/v1

# Input paths (optional)
RESUME_PATH=data/resume.md
JOB_DESCRIPTION_PATH=data/job-description.txt

Usage

Command Line Mode

  1. Place your resume in data/resume.json (JSON Resume format)
  2. Place the job description in data/job-description.txt
  3. Run:
    python main.py

Gradio UI Mode

  1. Place your resume in data/resume.json (JSON Resume format)
  2. Run the Gradio UI:
    python gradio_ui.py
  3. The UI will be available at http://localhost:7860

The Gradio interface allows you to:

  • Select from available LM Studio models
  • Paste job descriptions in a text box
  • See processing logs in real-time
  • Download the optimized resume when complete

Docker Mode

Run the Gradio UI in a Docker container:

  1. Make sure LM Studio is running on your host machine with a model loaded
  2. Place your resume in data/resume.json
  3. Build and run:
    docker compose up --build
  4. Access the UI at http://localhost:7860

The Docker setup:

  • Automatically connects to LM Studio on your host via host.docker.internal
  • Mounts data/ and output/ directories for persistence
  • Runs in the background with -d flag: docker compose up --build -d

Output

Results are saved to output/<position-slug>/:

  • resume.json - Optimized resume in JSON format
  • ats_report.md - ATS compatibility report in markdown

The folder name is derived from the job title (e.g., senior-software-engineer).

Project Structure

resume-agents/
├── main.py              # CLI entry point
├── gradio_ui.py         # Web UI entry point
├── optimizer_graph.py   # Multi-agent graph definition
├── schemas.py           # Pydantic models for structured output
├── Dockerfile           # Container image definition
├── docker-compose.yml   # Docker orchestration
├── data/
│   ├── resume.json      # Input resume (JSON Resume format)
│   └── job-description.txt
└── output/
    └── <position-slug>/
        ├── resume.json
        └── ats_report.md

Schemas

ResumeSchema (structured extraction via LLM)

Based on JSON Resume format:

  • basics: name, label (job title), email, phone, summary, location, profiles
  • work: company, position, dates, summary, highlights, keywords
  • skills: name, level, keywords
  • education, languages, etc.

Markdown Outputs

Both JobAnalyzer and ATSScorer output markdown saved directly to ats_report.md.

About

AI-powered resume optimizer using multi-agent LLM workflows

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors