resumemakerats 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. resumemakerats-0.1.0/LICENSE +21 -0
  2. resumemakerats-0.1.0/PKG-INFO +309 -0
  3. resumemakerats-0.1.0/README.md +284 -0
  4. resumemakerats-0.1.0/pyproject.toml +42 -0
  5. resumemakerats-0.1.0/resumemakerats/__init__.py +0 -0
  6. resumemakerats-0.1.0/resumemakerats/__main__.py +3 -0
  7. resumemakerats-0.1.0/resumemakerats/ats_scorer.py +316 -0
  8. resumemakerats-0.1.0/resumemakerats/cli.py +346 -0
  9. resumemakerats-0.1.0/resumemakerats/config.py +6 -0
  10. resumemakerats-0.1.0/resumemakerats/evaluator.py +91 -0
  11. resumemakerats-0.1.0/resumemakerats/fabricator.py +382 -0
  12. resumemakerats-0.1.0/resumemakerats/github.py +476 -0
  13. resumemakerats-0.1.0/resumemakerats/inception_provider.py +144 -0
  14. resumemakerats-0.1.0/resumemakerats/jd_analyzer.py +70 -0
  15. resumemakerats-0.1.0/resumemakerats/llm_router.py +199 -0
  16. resumemakerats-0.1.0/resumemakerats/llm_utils.py +54 -0
  17. resumemakerats-0.1.0/resumemakerats/models.py +364 -0
  18. resumemakerats-0.1.0/resumemakerats/page_manager.py +406 -0
  19. resumemakerats-0.1.0/resumemakerats/pdf.py +324 -0
  20. resumemakerats-0.1.0/resumemakerats/pdf_editor.py +307 -0
  21. resumemakerats-0.1.0/resumemakerats/prompt.py +25 -0
  22. resumemakerats-0.1.0/resumemakerats/prompts/__init__.py +0 -0
  23. resumemakerats-0.1.0/resumemakerats/prompts/template_manager.py +110 -0
  24. resumemakerats-0.1.0/resumemakerats/prompts/templates/ats_scoring.jinja +28 -0
  25. resumemakerats-0.1.0/resumemakerats/prompts/templates/awards.jinja +20 -0
  26. resumemakerats-0.1.0/resumemakerats/prompts/templates/basics.jinja +55 -0
  27. resumemakerats-0.1.0/resumemakerats/prompts/templates/consolidate_content.jinja +42 -0
  28. resumemakerats-0.1.0/resumemakerats/prompts/templates/critic_bullet_enhance.jinja +23 -0
  29. resumemakerats-0.1.0/resumemakerats/prompts/templates/critic_improvement.jinja +24 -0
  30. resumemakerats-0.1.0/resumemakerats/prompts/templates/education.jinja +23 -0
  31. resumemakerats-0.1.0/resumemakerats/prompts/templates/fabricate_project.jinja +32 -0
  32. resumemakerats-0.1.0/resumemakerats/prompts/templates/fabricate_work_bullets.jinja +25 -0
  33. resumemakerats-0.1.0/resumemakerats/prompts/templates/fabrication_quality.jinja +32 -0
  34. resumemakerats-0.1.0/resumemakerats/prompts/templates/github_project_selection.jinja +100 -0
  35. resumemakerats-0.1.0/resumemakerats/prompts/templates/jd_analysis.jinja +39 -0
  36. resumemakerats-0.1.0/resumemakerats/prompts/templates/page_fill_improvement.jinja +26 -0
  37. resumemakerats-0.1.0/resumemakerats/prompts/templates/projects.jinja +21 -0
  38. resumemakerats-0.1.0/resumemakerats/prompts/templates/regeneration_feedback.jinja +31 -0
  39. resumemakerats-0.1.0/resumemakerats/prompts/templates/resume_evaluation_criteria.jinja +185 -0
  40. resumemakerats-0.1.0/resumemakerats/prompts/templates/resume_evaluation_system_message.jinja +49 -0
  41. resumemakerats-0.1.0/resumemakerats/prompts/templates/resume_tailor_highlights.jinja +40 -0
  42. resumemakerats-0.1.0/resumemakerats/prompts/templates/resume_tailor_projects.jinja +27 -0
  43. resumemakerats-0.1.0/resumemakerats/prompts/templates/resume_tailor_skills.jinja +33 -0
  44. resumemakerats-0.1.0/resumemakerats/prompts/templates/resume_tailor_summary.jinja +21 -0
  45. resumemakerats-0.1.0/resumemakerats/prompts/templates/resume_to_json.jinja +100 -0
  46. resumemakerats-0.1.0/resumemakerats/prompts/templates/skills.jinja +20 -0
  47. resumemakerats-0.1.0/resumemakerats/prompts/templates/system_message.jinja +5 -0
  48. resumemakerats-0.1.0/resumemakerats/prompts/templates/technical_audit.jinja +29 -0
  49. resumemakerats-0.1.0/resumemakerats/prompts/templates/work.jinja +36 -0
  50. resumemakerats-0.1.0/resumemakerats/pymupdf_rag.py +1377 -0
  51. resumemakerats-0.1.0/resumemakerats/renderer.py +515 -0
  52. resumemakerats-0.1.0/resumemakerats/resume_converter.py +133 -0
  53. resumemakerats-0.1.0/resumemakerats/resume_parser.py +682 -0
  54. resumemakerats-0.1.0/resumemakerats/resume_tailor.py +1415 -0
  55. resumemakerats-0.1.0/resumemakerats/score.py +309 -0
  56. resumemakerats-0.1.0/resumemakerats/skills_gap_analyzer.py +89 -0
  57. resumemakerats-0.1.0/resumemakerats/transform.py +939 -0
  58. resumemakerats-0.1.0/resumemakerats.egg-info/PKG-INFO +309 -0
  59. resumemakerats-0.1.0/resumemakerats.egg-info/SOURCES.txt +62 -0
  60. resumemakerats-0.1.0/resumemakerats.egg-info/dependency_links.txt +1 -0
  61. resumemakerats-0.1.0/resumemakerats.egg-info/entry_points.txt +2 -0
  62. resumemakerats-0.1.0/resumemakerats.egg-info/requires.txt +12 -0
  63. resumemakerats-0.1.0/resumemakerats.egg-info/top_level.txt +1 -0
  64. resumemakerats-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 HackerRank
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,309 @@
1
+ Metadata-Version: 2.4
2
+ Name: resumemakerats
3
+ Version: 0.1.0
4
+ Summary: AI-powered resume tailoring tool - optimizes your resume for specific job descriptions
5
+ Author: Siddhant
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/yourusername/ResumeMakerATS
8
+ Keywords: resume,ats,job-search,tailoring,ai
9
+ Requires-Python: >=3.11
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: PyMuPDF>=1.26.3
13
+ Requires-Dist: pydantic>=2.11.0
14
+ Requires-Dist: requests>=2.32.0
15
+ Requires-Dist: pymupdf4llm>=0.0.27
16
+ Requires-Dist: jinja2>=3.1.6
17
+ Requires-Dist: python-dotenv>=1.0.1
18
+ Requires-Dist: fpdf2>=2.8.0
19
+ Requires-Dist: openai>=1.50.0
20
+ Requires-Dist: tenacity>=8.2.0
21
+ Requires-Dist: rapidfuzz>=3.9.0
22
+ Requires-Dist: python-docx>=1.1.0
23
+ Requires-Dist: pdfplumber>=0.11.0
24
+ Dynamic: license-file
25
+
26
+ # Hiring Agent
27
+
28
+ <p align="center"><strong>Resume-to-Score pipeline</strong> that extracts structured data from PDFs, enriches with GitHub signals, and outputs a fair, explainable evaluation.</p>
29
+
30
+ <p align="center">
31
+ <a href="https://www.python.org/downloads/release/python-3110/">
32
+ <img alt="Python" src="https://img.shields.io/badge/python-3.11%2B-blue.svg">
33
+ </a>
34
+ <a href="https://github.com/interviewstreet/hiring-agent/blob/master/LICENSE">
35
+ <img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-yellow.svg">
36
+ </a>
37
+ <a href="https://github.com/psf/black">
38
+ <img alt="Code style: Black" src="https://img.shields.io/badge/code%20style-Black-000000.svg">
39
+ </a>
40
+ </p>
41
+
42
+ ---
43
+
44
+ ## Contents
45
+
46
+ - [Overview](#overview)
47
+ - [Architecture](#architecture)
48
+ - [Installation and Setup](#installation-and-setup)
49
+ - [Prerequisites](#prerequisites)
50
+ - [Quick setup with pip](#quick-setup-with-pip)
51
+ - [Ollama models](#ollama-models)
52
+ - [Configuration](#configuration)
53
+ - [How it works](#how-it-works)
54
+ - [CLI usage](#cli-usage)
55
+ - [Directory layout](#directory-layout)
56
+ - [Provider details](#provider-details)
57
+ - [Contributing](#contributing)
58
+ - [License](#license)
59
+
60
+ ---
61
+
62
+ ## Overview
63
+
64
+ Hiring Agent parses a resume PDF to Markdown, extracts sectioned JSON using a local or hosted LLM, augments the data with GitHub profile and repository signals, then produces an objective evaluation with category scores, evidence, bonus points, and deductions. You can run fully local with Ollama or use Google Gemini.
65
+
66
+ ---
67
+
68
+ ## Architecture
69
+
70
+ <table>
71
+ <tr>
72
+ <td>
73
+
74
+ **Flow**
75
+
76
+ 1. `pymupdf_rag.py` converts PDF pages to Markdown-like text.
77
+ 2. `pdf.py` calls the LLM per section using Jinja templates under `prompts/templates`.
78
+ 3. `github.py` fetches profile and repos, classifies projects, and asks the LLM to select the top 7.
79
+ 4. `evaluator.py` runs a strict-scored evaluation with fairness constraints.
80
+ 5. `score.py` orchestrates everything end to end and writes CSV when development mode is on.
81
+
82
+ </td>
83
+ <td>
84
+
85
+ **Key modules**
86
+
87
+ - `models.py`
88
+ Pydantic schemas and LLM provider interfaces.
89
+
90
+ - `llm_utils.py`
91
+ Provider initialization and response cleanup.
92
+
93
+ - `transform.py`
94
+ Normalization from loose LLM JSON to JSON Resume style.
95
+
96
+ - `prompts/`
97
+ All Jinja templates for extraction and scoring.
98
+
99
+ </td>
100
+ </tr>
101
+ </table>
102
+
103
+ ---
104
+
105
+ ## Installation and Setup
106
+
107
+ ### Prerequisites
108
+
109
+ - **Python 3.11+**
110
+
111
+ The repository pins `.python-version` to 3.11.13.
112
+
113
+ - **One LLM backend** (either of them)
114
+
115
+ - **Ollama** for local models
116
+ Install from the [official site](https://ollama.com/), then run `ollama serve`.
117
+ - **Google Gemini** if you have an API key, get it from [here](https://aistudio.google.com/api-keys).
118
+
119
+ ### Quick setup with pip
120
+
121
+ ```bash
122
+ $ git clone https://github.com/interviewstreet/hiring-agent
123
+ $ cd hiring-agent
124
+
125
+ $ python -m venv .venv
126
+ # Linux or macOS
127
+ $ source .venv/bin/activate
128
+ # Windows
129
+ # .venv\Scripts\activate
130
+
131
+ $ pip install -r requirements.txt
132
+ ```
133
+
134
+ ### Ollama Models
135
+
136
+ Pull the model you want to use. For example:
137
+
138
+ ```bash
139
+ $ ollama pull gemma3:4b
140
+ ```
141
+
142
+ If you want different results, you can pull other models such as:
143
+
144
+ ```bash
145
+ # For higher system configuration
146
+ $ ollama pull gemma3:12b
147
+
148
+ # For lower system configuration
149
+ $ ollama pull gemma3:1b
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Configuration
155
+
156
+ Copy the template and set your environment variables.
157
+
158
+ ```bash
159
+ $ cp .env.example .env
160
+ ```
161
+
162
+ **Environment variables**
163
+
164
+ | Variable | Values | Description |
165
+ | ---------------- | ------------------------------------------- | ---------------------------------------------------------------------- |
166
+ | `LLM_PROVIDER` | `ollama` or `gemini` | Chooses provider. Defaults to Ollama. |
167
+ | `DEFAULT_MODEL` | for example `gemma3:4b` or `gemini-2.5-pro` | Model name passed to the provider. |
168
+ | `GEMINI_API_KEY` | string | Required when `LLM_PROVIDER=gemini`. |
169
+ | `GITHUB_TOKEN` | optional | Inherits from your shell environment, improves GitHub API rate limits. |
170
+
171
+ Provider mapping lives in `prompt.py` and `models.py`. The `config.py` file has a single flag:
172
+
173
+ ```python
174
+ # config.py
175
+ DEVELOPMENT_MODE = True # enables caching and CSV export
176
+ ```
177
+
178
+ You can leave it on during iteration. See the next section for details.
179
+
180
+ ---
181
+
182
+ ## How it works
183
+
184
+ <details>
185
+ <summary><b>1) PDF extraction</b></summary>
186
+
187
+ - `pymupdf_rag.py` and `pdf.py` read the PDF using PyMuPDF and convert pages to Markdown-like text.
188
+ - The `to_markdown` routine handles headings, links, tables, and basic formatting.
189
+
190
+ </details>
191
+
192
+ <details>
193
+ <summary><b>2) Section parsing with templates</b></summary>
194
+
195
+ - `prompts/templates/*.jinja` define strict instructions for each section
196
+ Basics, Work, Education, Skills, Projects, Awards.
197
+ - `pdf.PDFHandler` calls the LLM per section and assembles a `JSONResume` object (see `models.py`).
198
+
199
+ </details>
200
+
201
+ <details>
202
+ <summary><b>3) GitHub enrichment</b></summary>
203
+
204
+ - `github.py` extracts a username from the resume profiles, fetches profile and repos, and classifies each project.
205
+ - It asks the LLM to select exactly 7 unique projects with a minimum author commit threshold, favoring meaningful contributions.
206
+
207
+ </details>
208
+
209
+ <details>
210
+ <summary><b>4) Evaluation</b></summary>
211
+
212
+ - `evaluator.py` uses templates that encode fairness and scoring rules.
213
+ - Scores include `open_source`, `self_projects`, `production`, and `technical_skills`, plus bonus and deductions, then an explanation for evidence.
214
+
215
+ </details>
216
+
217
+ <details>
218
+ <summary><b>5) Output and CSV export</b></summary>
219
+
220
+ - `score.py` prints a readable summary to stdout.
221
+ - When `DEVELOPMENT_MODE=True` it creates or appends a `resume_evaluations.csv` with key fields, and caches intermediate JSON under `cache/`.
222
+
223
+ </details>
224
+
225
+ ---
226
+
227
+ ## CLI usage
228
+
229
+ ### End to end scoring
230
+
231
+ Provide a path to a resume PDF.
232
+
233
+ ```bash
234
+ $ python score.py /path/to/resume.pdf
235
+ ```
236
+
237
+ What happens:
238
+
239
+ 1. If development mode is on, the PDF extraction result is cached to `cache/resumecache_<basename>.json`.
240
+ 2. If a GitHub profile is found in the resume, repositories are fetched and cached to `cache/githubcache_<basename>.json`.
241
+ 3. The evaluator prints a report and, in development mode, appends a CSV row to `resume_evaluations.csv`.
242
+
243
+ ---
244
+
245
+ ## Directory layout
246
+
247
+ ```text
248
+ .
249
+ ├── .env.example
250
+ ├── .python-version
251
+ ├── config.py
252
+ ├── evaluator.py
253
+ ├── github.py
254
+ ├── llm_utils.py
255
+ ├── models.py
256
+ ├── pdf.py
257
+ ├── prompt.py
258
+ ├── prompts/
259
+ │ ├── template_manager.py
260
+ │ └── templates/
261
+ │ ├── awards.jinja
262
+ │ ├── basics.jinja
263
+ │ ├── education.jinja
264
+ │ ├── github_project_selection.jinja
265
+ │ ├── projects.jinja
266
+ │ ├── resume_evaluation_criteria.jinja
267
+ │ ├── resume_evaluation_system_message.jinja
268
+ │ ├── skills.jinja
269
+ │ ├── system_message.jinja
270
+ │ └── work.jinja
271
+ ├── pymupdf_rag.py
272
+ ├── requirements.txt
273
+ ├── score.py
274
+ └── transform.py
275
+ ```
276
+
277
+ ---
278
+
279
+ ## Provider details
280
+
281
+ ### Ollama
282
+
283
+ - Set `LLM_PROVIDER=ollama`
284
+ - Set `DEFAULT_MODEL` to any pulled model, for example `gemma3:4b`
285
+ - The provider wrapper in `models.OllamaProvider` calls `ollama.chat`
286
+
287
+ ### Gemini
288
+
289
+ - Set `LLM_PROVIDER=gemini`
290
+ - Set `DEFAULT_MODEL` to a supported Gemini model, for example `gemini-2.0-flash`
291
+ - Provide `GEMINI_API_KEY`
292
+ - The wrapper in `models.GeminiProvider` adapts responses to a unified format
293
+
294
+ ---
295
+
296
+ ## Contributing
297
+
298
+ Please read the [CONTRIBUTING.md](./CONTRIBUTING.md) for detailed guidelines on filing issues, proposing changes, and submitting pull requests. Key principles include:
299
+
300
+ - Keep prompts declarative and provider-agnostic.
301
+ - Validate changes with a couple of real resumes under different providers.
302
+ - Add or adjust unit-free smoke tests that call each stage with minimal inputs.
303
+
304
+ ---
305
+
306
+
307
+ ## License
308
+
309
+ [MIT](https://github.com/interviewstreet/hiring-agent/blob/master/LICENSE) © HackerRank
@@ -0,0 +1,284 @@
1
+ # Hiring Agent
2
+
3
+ <p align="center"><strong>Resume-to-Score pipeline</strong> that extracts structured data from PDFs, enriches with GitHub signals, and outputs a fair, explainable evaluation.</p>
4
+
5
+ <p align="center">
6
+ <a href="https://www.python.org/downloads/release/python-3110/">
7
+ <img alt="Python" src="https://img.shields.io/badge/python-3.11%2B-blue.svg">
8
+ </a>
9
+ <a href="https://github.com/interviewstreet/hiring-agent/blob/master/LICENSE">
10
+ <img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-yellow.svg">
11
+ </a>
12
+ <a href="https://github.com/psf/black">
13
+ <img alt="Code style: Black" src="https://img.shields.io/badge/code%20style-Black-000000.svg">
14
+ </a>
15
+ </p>
16
+
17
+ ---
18
+
19
+ ## Contents
20
+
21
+ - [Overview](#overview)
22
+ - [Architecture](#architecture)
23
+ - [Installation and Setup](#installation-and-setup)
24
+ - [Prerequisites](#prerequisites)
25
+ - [Quick setup with pip](#quick-setup-with-pip)
26
+ - [Ollama models](#ollama-models)
27
+ - [Configuration](#configuration)
28
+ - [How it works](#how-it-works)
29
+ - [CLI usage](#cli-usage)
30
+ - [Directory layout](#directory-layout)
31
+ - [Provider details](#provider-details)
32
+ - [Contributing](#contributing)
33
+ - [License](#license)
34
+
35
+ ---
36
+
37
+ ## Overview
38
+
39
+ Hiring Agent parses a resume PDF to Markdown, extracts sectioned JSON using a local or hosted LLM, augments the data with GitHub profile and repository signals, then produces an objective evaluation with category scores, evidence, bonus points, and deductions. You can run fully local with Ollama or use Google Gemini.
40
+
41
+ ---
42
+
43
+ ## Architecture
44
+
45
+ <table>
46
+ <tr>
47
+ <td>
48
+
49
+ **Flow**
50
+
51
+ 1. `pymupdf_rag.py` converts PDF pages to Markdown-like text.
52
+ 2. `pdf.py` calls the LLM per section using Jinja templates under `prompts/templates`.
53
+ 3. `github.py` fetches profile and repos, classifies projects, and asks the LLM to select the top 7.
54
+ 4. `evaluator.py` runs a strict-scored evaluation with fairness constraints.
55
+ 5. `score.py` orchestrates everything end to end and writes CSV when development mode is on.
56
+
57
+ </td>
58
+ <td>
59
+
60
+ **Key modules**
61
+
62
+ - `models.py`
63
+ Pydantic schemas and LLM provider interfaces.
64
+
65
+ - `llm_utils.py`
66
+ Provider initialization and response cleanup.
67
+
68
+ - `transform.py`
69
+ Normalization from loose LLM JSON to JSON Resume style.
70
+
71
+ - `prompts/`
72
+ All Jinja templates for extraction and scoring.
73
+
74
+ </td>
75
+ </tr>
76
+ </table>
77
+
78
+ ---
79
+
80
+ ## Installation and Setup
81
+
82
+ ### Prerequisites
83
+
84
+ - **Python 3.11+**
85
+
86
+ The repository pins `.python-version` to 3.11.13.
87
+
88
+ - **One LLM backend** (either of them)
89
+
90
+ - **Ollama** for local models
91
+ Install from the [official site](https://ollama.com/), then run `ollama serve`.
92
+ - **Google Gemini** if you have an API key, get it from [here](https://aistudio.google.com/api-keys).
93
+
94
+ ### Quick setup with pip
95
+
96
+ ```bash
97
+ $ git clone https://github.com/interviewstreet/hiring-agent
98
+ $ cd hiring-agent
99
+
100
+ $ python -m venv .venv
101
+ # Linux or macOS
102
+ $ source .venv/bin/activate
103
+ # Windows
104
+ # .venv\Scripts\activate
105
+
106
+ $ pip install -r requirements.txt
107
+ ```
108
+
109
+ ### Ollama Models
110
+
111
+ Pull the model you want to use. For example:
112
+
113
+ ```bash
114
+ $ ollama pull gemma3:4b
115
+ ```
116
+
117
+ If you want different results, you can pull other models such as:
118
+
119
+ ```bash
120
+ # For higher system configuration
121
+ $ ollama pull gemma3:12b
122
+
123
+ # For lower system configuration
124
+ $ ollama pull gemma3:1b
125
+ ```
126
+
127
+ ---
128
+
129
+ ## Configuration
130
+
131
+ Copy the template and set your environment variables.
132
+
133
+ ```bash
134
+ $ cp .env.example .env
135
+ ```
136
+
137
+ **Environment variables**
138
+
139
+ | Variable | Values | Description |
140
+ | ---------------- | ------------------------------------------- | ---------------------------------------------------------------------- |
141
+ | `LLM_PROVIDER` | `ollama` or `gemini` | Chooses provider. Defaults to Ollama. |
142
+ | `DEFAULT_MODEL` | for example `gemma3:4b` or `gemini-2.5-pro` | Model name passed to the provider. |
143
+ | `GEMINI_API_KEY` | string | Required when `LLM_PROVIDER=gemini`. |
144
+ | `GITHUB_TOKEN` | optional | Inherits from your shell environment, improves GitHub API rate limits. |
145
+
146
+ Provider mapping lives in `prompt.py` and `models.py`. The `config.py` file has a single flag:
147
+
148
+ ```python
149
+ # config.py
150
+ DEVELOPMENT_MODE = True # enables caching and CSV export
151
+ ```
152
+
153
+ You can leave it on during iteration. See the next section for details.
154
+
155
+ ---
156
+
157
+ ## How it works
158
+
159
+ <details>
160
+ <summary><b>1) PDF extraction</b></summary>
161
+
162
+ - `pymupdf_rag.py` and `pdf.py` read the PDF using PyMuPDF and convert pages to Markdown-like text.
163
+ - The `to_markdown` routine handles headings, links, tables, and basic formatting.
164
+
165
+ </details>
166
+
167
+ <details>
168
+ <summary><b>2) Section parsing with templates</b></summary>
169
+
170
+ - `prompts/templates/*.jinja` define strict instructions for each section
171
+ Basics, Work, Education, Skills, Projects, Awards.
172
+ - `pdf.PDFHandler` calls the LLM per section and assembles a `JSONResume` object (see `models.py`).
173
+
174
+ </details>
175
+
176
+ <details>
177
+ <summary><b>3) GitHub enrichment</b></summary>
178
+
179
+ - `github.py` extracts a username from the resume profiles, fetches profile and repos, and classifies each project.
180
+ - It asks the LLM to select exactly 7 unique projects with a minimum author commit threshold, favoring meaningful contributions.
181
+
182
+ </details>
183
+
184
+ <details>
185
+ <summary><b>4) Evaluation</b></summary>
186
+
187
+ - `evaluator.py` uses templates that encode fairness and scoring rules.
188
+ - Scores include `open_source`, `self_projects`, `production`, and `technical_skills`, plus bonus and deductions, then an explanation for evidence.
189
+
190
+ </details>
191
+
192
+ <details>
193
+ <summary><b>5) Output and CSV export</b></summary>
194
+
195
+ - `score.py` prints a readable summary to stdout.
196
+ - When `DEVELOPMENT_MODE=True` it creates or appends a `resume_evaluations.csv` with key fields, and caches intermediate JSON under `cache/`.
197
+
198
+ </details>
199
+
200
+ ---
201
+
202
+ ## CLI usage
203
+
204
+ ### End to end scoring
205
+
206
+ Provide a path to a resume PDF.
207
+
208
+ ```bash
209
+ $ python score.py /path/to/resume.pdf
210
+ ```
211
+
212
+ What happens:
213
+
214
+ 1. If development mode is on, the PDF extraction result is cached to `cache/resumecache_<basename>.json`.
215
+ 2. If a GitHub profile is found in the resume, repositories are fetched and cached to `cache/githubcache_<basename>.json`.
216
+ 3. The evaluator prints a report and, in development mode, appends a CSV row to `resume_evaluations.csv`.
217
+
218
+ ---
219
+
220
+ ## Directory layout
221
+
222
+ ```text
223
+ .
224
+ ├── .env.example
225
+ ├── .python-version
226
+ ├── config.py
227
+ ├── evaluator.py
228
+ ├── github.py
229
+ ├── llm_utils.py
230
+ ├── models.py
231
+ ├── pdf.py
232
+ ├── prompt.py
233
+ ├── prompts/
234
+ │ ├── template_manager.py
235
+ │ └── templates/
236
+ │ ├── awards.jinja
237
+ │ ├── basics.jinja
238
+ │ ├── education.jinja
239
+ │ ├── github_project_selection.jinja
240
+ │ ├── projects.jinja
241
+ │ ├── resume_evaluation_criteria.jinja
242
+ │ ├── resume_evaluation_system_message.jinja
243
+ │ ├── skills.jinja
244
+ │ ├── system_message.jinja
245
+ │ └── work.jinja
246
+ ├── pymupdf_rag.py
247
+ ├── requirements.txt
248
+ ├── score.py
249
+ └── transform.py
250
+ ```
251
+
252
+ ---
253
+
254
+ ## Provider details
255
+
256
+ ### Ollama
257
+
258
+ - Set `LLM_PROVIDER=ollama`
259
+ - Set `DEFAULT_MODEL` to any pulled model, for example `gemma3:4b`
260
+ - The provider wrapper in `models.OllamaProvider` calls `ollama.chat`
261
+
262
+ ### Gemini
263
+
264
+ - Set `LLM_PROVIDER=gemini`
265
+ - Set `DEFAULT_MODEL` to a supported Gemini model, for example `gemini-2.0-flash`
266
+ - Provide `GEMINI_API_KEY`
267
+ - The wrapper in `models.GeminiProvider` adapts responses to a unified format
268
+
269
+ ---
270
+
271
+ ## Contributing
272
+
273
+ Please read the [CONTRIBUTING.md](./CONTRIBUTING.md) for detailed guidelines on filing issues, proposing changes, and submitting pull requests. Key principles include:
274
+
275
+ - Keep prompts declarative and provider-agnostic.
276
+ - Validate changes with a couple of real resumes under different providers.
277
+ - Add or adjust unit-free smoke tests that call each stage with minimal inputs.
278
+
279
+ ---
280
+
281
+
282
+ ## License
283
+
284
+ [MIT](https://github.com/interviewstreet/hiring-agent/blob/master/LICENSE) © HackerRank
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "resumemakerats"
7
+ version = "0.1.0"
8
+ description = "AI-powered resume tailoring tool - optimizes your resume for specific job descriptions"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.11"
12
+ keywords = ["resume", "ats", "job-search", "tailoring", "ai"]
13
+ authors = [
14
+ {name = "Siddhant"},
15
+ ]
16
+
17
+ dependencies = [
18
+ "PyMuPDF>=1.26.3",
19
+ "pydantic>=2.11.0",
20
+ "requests>=2.32.0",
21
+ "pymupdf4llm>=0.0.27",
22
+ "jinja2>=3.1.6",
23
+ "python-dotenv>=1.0.1",
24
+ "fpdf2>=2.8.0",
25
+ "openai>=1.50.0",
26
+ "tenacity>=8.2.0",
27
+ "rapidfuzz>=3.9.0",
28
+ "python-docx>=1.1.0",
29
+ "pdfplumber>=0.11.0",
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/yourusername/ResumeMakerATS"
34
+
35
+ [project.scripts]
36
+ resumemakerats = "resumemakerats.cli:main"
37
+
38
+ [tool.setuptools.packages.find]
39
+ include = ["resumemakerats*"]
40
+
41
+ [tool.setuptools.package-data]
42
+ "resumemakerats" = ["prompts/templates/*.jinja", "storage/.gitkeep"]
File without changes
@@ -0,0 +1,3 @@
1
+ from .cli import main
2
+
3
+ main()