arbabarshad commited on
Commit
583aa92
·
1 Parent(s): 3b931a0

minimal pdf

Browse files
.env.example ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hugging Face API Token (used for accessing LLM models)
2
+ HF_API_TOKEN=your_huggingface_token_here
3
+
4
+ # Model to use for job description analysis
5
+ LLM_MODEL=google/flan-t5-large
6
+
7
+ # Default template location (relative to app root)
8
+ DEFAULT_TEMPLATE_PATH=templates/resume_template.tex
9
+
10
+ # Output directory for generated files
11
+ OUTPUT_DIR=outputs
.gitignore ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ env/
8
+ build/
9
+ develop-eggs/
10
+ dist/
11
+ downloads/
12
+ eggs/
13
+ .eggs/
14
+ lib/
15
+ lib64/
16
+ parts/
17
+ sdist/
18
+ var/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual Environment
24
+ venv/
25
+ ENV/
26
+ env/
27
+
28
+ # IDE
29
+ .idea/
30
+ .vscode/
31
+ *.swp
32
+ *.swo
33
+
34
+ # Project specific
35
+ outputs/
36
+ *.pdf
37
+ *.aux
38
+ *.log
39
+ *.out
README.md ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Resume Customizer
2
+
3
+ A Hugging Face Spaces application that customizes your resume for specific job applications by analyzing job descriptions and generating tailored "Why Hire Me" sections.
4
+
5
+ ## Features
6
+
7
+ - Upload your base LaTeX resume template
8
+ - Input job descriptions to analyze
9
+ - Automatically generate a customized "Why Hire Me" section highlighting relevant skills and experience
10
+ - Convert the customized LaTeX resume to PDF
11
+ - Preview and download the final resume
12
+
13
+ ## How It Works
14
+
15
+ 1. The application takes your LaTeX resume template and a job description as input
16
+ 2. It uses a language model to analyze the job description and identify key requirements
17
+ 3. Based on the analysis, it generates a tailored "Why Hire Me" section that emphasizes your qualifications
18
+ 4. The new section is injected into your LaTeX resume
19
+ 5. The modified LaTeX is converted to PDF for download
20
+
21
+ ## Getting Started
22
+
23
+ ### Local Development
24
+
25
+ 1. Clone this repository
26
+ 2. Install dependencies: `pip install -r requirements.txt`
27
+ 3. Run the application: `python app/app.py`
28
+
29
+ ### Using Hugging Face Space
30
+
31
+ Simply visit the Hugging Face Space at [URL to be added] and use the interface directly in your browser.
32
+
33
+ ## Project Structure
34
+
35
+ - `app/` - Contains the main application code
36
+ - `app/app.py` - Main Gradio application
37
+ - `app/resume_processor.py` - LaTeX processing utilities
38
+ - `app/llm_utils.py` - LLM integration for job description analysis
39
+ - `templates/` - Default LaTeX resume template
40
+ - `assets/` - Static assets for the application
41
+
42
+ ## License
43
+
44
+ MIT
app.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Main entry point for the Resume Customizer application.
3
+ For Hugging Face Spaces deployment.
4
+ """
5
+
6
+ import os
7
+ import sys
8
+
9
+ # Add the current directory to Python's path to allow imports
10
+ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
11
+
12
+ # Import the create_interface function from the app module
13
+ from app.app import create_interface
14
+
15
+ # Create and launch the application
16
+ app = create_interface()
17
+
18
+ # For Hugging Face Spaces, we need to export the app
19
+ if __name__ == "__main__":
20
+ app.launch()
app/__init__.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ """
2
+ Resume Customizer application package.
3
+ """
4
+
5
+ __version__ = "0.1.0"
app/app.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ from huggingface_hub import InferenceClient
4
+ import tempfile
5
+ import shutil
6
+ import subprocess
7
+
8
+ # Constants
9
+ # Use the minimal template for testing
10
+ DEFAULT_TEMPLATE_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "templates", "minimal_resume.tex")
11
+ OUTPUT_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "outputs")
12
+
13
+ # Ensure output directory exists
14
+ os.makedirs(OUTPUT_DIR, exist_ok=True)
15
+
16
+ def customize_resume(job_description):
17
+ """
18
+ Main function to customize resume based on job description.
19
+
20
+ Args:
21
+ job_description (str): The job description text
22
+
23
+ Returns:
24
+ tuple: (PDF path, Status message)
25
+ """
26
+ # This is a placeholder for future implementation of LLM integration
27
+ # For now, we'll just add a simple "Why Hire Me" section
28
+ why_hire_me_section = "\\section{Why Hire Me?}\nThis is a placeholder for the Why Hire Me section that will be generated by an LLM in future milestones."
29
+
30
+ # Read the template
31
+ with open(DEFAULT_TEMPLATE_PATH, "r") as f:
32
+ template_content = f.read()
33
+
34
+ # Replace the placeholder with the generated section
35
+ modified_content = template_content.replace("% WHY_HIRE_ME_SECTION", why_hire_me_section)
36
+
37
+ # Save the modified content to a new file
38
+ output_tex_path = os.path.join(OUTPUT_DIR, "customized_resume.tex")
39
+ with open(output_tex_path, "w") as f:
40
+ f.write(modified_content)
41
+
42
+ # Convert to PDF using pdflatex
43
+ try:
44
+ pdf_path = convert_to_pdf(output_tex_path)
45
+ return pdf_path, f"Resume successfully generated! Click to download."
46
+ except Exception as e:
47
+ return None, f"Error converting to PDF: {str(e)}"
48
+
49
+ def convert_to_pdf(tex_path):
50
+ """
51
+ Convert a LaTeX file to PDF using pdflatex.
52
+
53
+ Args:
54
+ tex_path (str): Path to the LaTeX file
55
+
56
+ Returns:
57
+ str: Path to the generated PDF file
58
+ """
59
+ # Get the directory and filename
60
+ tex_dir = os.path.dirname(tex_path)
61
+ tex_filename = os.path.basename(tex_path)
62
+
63
+ # Change to the directory containing the tex file
64
+ original_dir = os.getcwd()
65
+ os.chdir(tex_dir)
66
+
67
+ try:
68
+ # Create a log file to capture output
69
+ log_path = os.path.join(tex_dir, "pdflatex_log.txt")
70
+ with open(log_path, 'w') as log_file:
71
+ # Run pdflatex and capture output to the log file
72
+ log_file.write("Running pdflatex - First pass\n")
73
+ result = subprocess.run(['pdflatex', '-interaction=nonstopmode', tex_filename],
74
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
75
+ log_file.write(f"Return code: {result.returncode}\n")
76
+ log_file.write(f"STDOUT:\n{result.stdout}\n")
77
+ log_file.write(f"STDERR:\n{result.stderr}\n\n")
78
+
79
+ # Run a second time to resolve references
80
+ log_file.write("Running pdflatex - Second pass\n")
81
+ result = subprocess.run(['pdflatex', '-interaction=nonstopmode', tex_filename],
82
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
83
+ log_file.write(f"Return code: {result.returncode}\n")
84
+ log_file.write(f"STDOUT:\n{result.stdout}\n")
85
+ log_file.write(f"STDERR:\n{result.stderr}\n")
86
+
87
+ # Get the PDF path
88
+ pdf_filename = tex_filename.replace('.tex', '.pdf')
89
+ pdf_path = os.path.join(tex_dir, pdf_filename)
90
+
91
+ # Check if the PDF was actually created
92
+ if not os.path.exists(pdf_path):
93
+ raise Exception(f"PDF file not created. See log at: {log_path}")
94
+
95
+ # Return the absolute path to the PDF
96
+ return os.path.abspath(pdf_path)
97
+ except subprocess.CalledProcessError as e:
98
+ raise Exception(f"PDF conversion failed: {e}\nSee log at: {os.path.abspath(log_path)}")
99
+ except Exception as e:
100
+ raise Exception(f"Error in PDF conversion: {str(e)}")
101
+ finally:
102
+ # Change back to the original directory
103
+ os.chdir(original_dir)
104
+
105
+ # Define the Gradio interface
106
+ def create_interface():
107
+ with gr.Blocks(title="Resume Customizer") as app:
108
+ gr.Markdown("# Resume Customizer")
109
+ gr.Markdown("Enter a job description to generate a customized resume.")
110
+
111
+ with gr.Row():
112
+ with gr.Column():
113
+ job_description = gr.Textbox(
114
+ label="Job Description",
115
+ placeholder="Paste the job description here...",
116
+ lines=10
117
+ )
118
+
119
+ customize_btn = gr.Button("Customize Resume")
120
+
121
+ with gr.Column():
122
+ pdf_output = gr.File(label="Download Resume")
123
+ status_text = gr.Textbox(label="Status", interactive=False)
124
+
125
+ customize_btn.click(
126
+ fn=customize_resume,
127
+ inputs=[job_description],
128
+ outputs=[pdf_output, status_text]
129
+ )
130
+
131
+ return app
132
+
133
+ # Main entry point
134
+ if __name__ == "__main__":
135
+ app = create_interface()
136
+ app.launch()
milestones.md ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Resume Customization Project Milestones
2
+ Note (when something is implemented write [done] in front of it)
3
+ ## Milestone 1: Project Setup [done]
4
+ - Set up project structure and repository [done]
5
+ - Create basic README with project overview [done]
6
+ - Set up Python environment with requirements.txt [done]
7
+ - Initialize Gradio application [done]
8
+
9
+ ## Milestone 2: LaTeX Resume Setup [done]
10
+ - Create or import base LaTeX resume template [done]
11
+ - Test LaTeX to PDF conversion pipeline [done]
12
+ - Set up file storage structure for template and customized resumes [done]
13
+
14
+ ## Milestone 3: Job Description Analysis with LLM
15
+ - Set up LLM integration (Hugging Face models)
16
+ - Develop prompt engineering for job description analysis
17
+ - Create function to extract key skills and requirements from job descriptions
18
+
19
+ ## Milestone 4: Resume Customization Logic
20
+ - Develop logic to generate "Why Hire Me" section based on job description
21
+ - Create function to inject new section into LaTeX resume
22
+ - Implement resume customization pipeline (job desc → analysis → LaTeX modification → PDF)
23
+
24
+ ## Milestone 5: Gradio UI Development
25
+ - Design simple UI with job description input
26
+ - Add file upload option for custom base resume (optional)
27
+ - Implement PDF preview and download functionality
28
+ - Style the interface for better user experience
29
+
30
+ ## Milestone 6: Testing and Refinement
31
+ - Test with various job descriptions
32
+ - Refine LLM prompts for better customization
33
+ - Optimize performance and resource usage
34
+ - Fix bugs and edge cases
35
+
36
+ ## Milestone 7: Hugging Face Deployment
37
+ - Prepare application for Hugging Face Spaces
38
+ - Configure deployment settings
39
+ - Create deployment documentation
40
+ - Deploy application to Hugging Face Spaces
41
+
42
+ ## Milestone 8: Documentation and Maintenance
43
+ - Complete user documentation
44
+ - Document code for future maintenance
45
+ - Create examples and usage instructions
46
+ - Plan for future enhancements
purpose.md ADDED
@@ -0,0 +1 @@
 
 
1
+ the purpose is the customize my resume for each job applied. so the input will be job description and output will be the pdf. essentially at backend there will be a a latex resume .tex file and it'll be converted to another tex file via LLM (it'll just add a why hire me section) on top of the resume using LLMs. essentiallyl that tex will be converted to pdf as well. it'll be a gradio, huggingface, python app.
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ gradio>=4.0.0
2
+ huggingface_hub>=0.20.0
3
+ transformers>=4.36.0
4
+ torch>=2.0.0
5
+ PyPDF2>=3.0.0
6
+ python-dotenv>=1.0.0
7
+ latex>=0.7.0
8
+ pdflatex>=0.1.3
templates/minimal_resume.tex ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ \documentclass[letterpaper,11pt]{article}
2
+
3
+ \usepackage[margin=1in]{geometry}
4
+ \usepackage{enumitem}
5
+
6
+ % WHY HIRE ME SECTION PLACEHOLDER - this will be modified by the app
7
+ % WHY_HIRE_ME_SECTION
8
+
9
+ \begin{document}
10
+
11
+ \centerline{\Huge\textbf{John Doe}}
12
+ \vspace{0.25em}
13
+ \centerline{123-456-7890 $\vert$ john.doe@email.com $\vert$ linkedin.com/in/johndoe}
14
+
15
+ \section*{Education}
16
+ \textbf{University of Technology} \hfill City, State\\
17
+ Master of Science in Computer Science \hfill 2018-2020
18
+
19
+ \section*{Experience}
20
+ \textbf{Senior Software Engineer} \hfill Jan 2021 - Present\\
21
+ Tech Company Inc. \hfill City, State
22
+ \begin{itemize}
23
+ \item Led development of cloud-based microservices architecture
24
+ \item Implemented CI/CD pipeline reducing deployment time by 40\%
25
+ \end{itemize}
26
+
27
+ \section*{Skills}
28
+ Languages: Python, JavaScript, Java, C++, SQL\\
29
+ Tools: Docker, Kubernetes, AWS, Git, Jenkins
30
+
31
+ \end{document}
templates/resume_template.tex ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ \documentclass[letterpaper,11pt]{article}
2
+
3
+ \usepackage{latexsym}
4
+ \usepackage[empty]{fullpage}
5
+ \usepackage{titlesec}
6
+ \usepackage[usenames,dvipsnames]{color}
7
+ \usepackage{verbatim}
8
+ \usepackage{enumitem}
9
+ \usepackage[hidelinks]{hyperref}
10
+ \usepackage{fancyhdr}
11
+ \usepackage[english]{babel}
12
+ \usepackage{tabularx}
13
+ \usepackage{multicol}
14
+ \setlength{\multicolsep}{-3.0pt}
15
+ \setlength{\columnsep}{-1pt}
16
+
17
+ % FONT SETTINGS
18
+ \usepackage[T1]{fontenc}
19
+
20
+ % PAGE SETTINGS
21
+ \pagestyle{fancy}
22
+ \fancyhf{} % clear all header and footer fields
23
+ \fancyfoot{}
24
+ \renewcommand{\headrulewidth}{0pt}
25
+ \renewcommand{\footrulewidth}{0pt}
26
+
27
+ % Adjust margins
28
+ \addtolength{\oddsidemargin}{-0.6in}
29
+ \addtolength{\evensidemargin}{-0.5in}
30
+ \addtolength{\textwidth}{1.19in}
31
+ \addtolength{\topmargin}{-.7in}
32
+ \addtolength{\textheight}{1.4in}
33
+
34
+ \urlstyle{same}
35
+
36
+ \raggedbottom
37
+ \raggedright
38
+ \setlength{\tabcolsep}{0in}
39
+
40
+ % SECTION FORMATTING
41
+ \titleformat{\section}{
42
+ \vspace{-4pt}\scshape\raggedright\large\bfseries
43
+ }{}{0em}{}[\color{black}\titlerule \vspace{-5pt}]
44
+
45
+ % CUSTOM COMMANDS
46
+ \newcommand{\resumeItem}[1]{
47
+ \item\small{
48
+ {#1 \vspace{-2pt}}
49
+ }
50
+ }
51
+
52
+ \newcommand{\resumeSubheading}[4]{
53
+ \vspace{-2pt}\item
54
+ \begin{tabular*}{1.0\textwidth}[t]{l@{\extracolsep{\fill}}r}
55
+ \textbf{#1} & #2 \\
56
+ \textit{\small#3} & \textit{\small #4} \\
57
+ \end{tabular*}\vspace{-7pt}
58
+ }
59
+
60
+ \newcommand{\resumeSubItem}[1]{\resumeItem{#1}\vspace{-4pt}}
61
+
62
+ \renewcommand\labelitemii{$\vcenter{\hbox{\tiny$\bullet$}}$}
63
+
64
+ \newcommand{\resumeSubHeadingListStart}{\begin{itemize}[leftmargin=0.15in, label={}]}
65
+ \newcommand{\resumeSubHeadingListEnd}{\end{itemize}}
66
+ \newcommand{\resumeItemListStart}{\begin{itemize}}
67
+ \newcommand{\resumeItemListEnd}{\end{itemize}\vspace{-5pt}}
68
+
69
+ % WHY HIRE ME SECTION PLACEHOLDER - this will be modified by the app
70
+ % WHY_HIRE_ME_SECTION
71
+
72
+ \begin{document}
73
+
74
+ \begin{center}
75
+ \textbf{\Huge John Doe} \\ \vspace{1pt}
76
+ \small +1-123-456-7890 $|$ \href{mailto:john.doe@email.com}{john.doe@email.com} $|$
77
+ \href{https://linkedin.com/in/johndoe}{linkedin.com/in/johndoe} $|$
78
+ \href{https://github.com/johndoe}{github.com/johndoe}
79
+ \end{center}
80
+
81
+ %----------------------------------------------------------------------------------------
82
+ % EDUCATION
83
+ %----------------------------------------------------------------------------------------
84
+
85
+ \section{Education}
86
+ \resumeSubHeadingListStart
87
+ \resumeSubheading
88
+ {University of Technology}{City, State}
89
+ {Master of Science in Computer Science}{Jan 2018 -- Dec 2020}
90
+ \resumeSubheading
91
+ {University of Science}{City, State}
92
+ {Bachelor of Science in Computer Engineering}{Aug 2014 -- Dec 2017}
93
+ \resumeSubHeadingListEnd
94
+
95
+ %----------------------------------------------------------------------------------------
96
+ % EXPERIENCE
97
+ %----------------------------------------------------------------------------------------
98
+
99
+ \section{Experience}
100
+ \resumeSubHeadingListStart
101
+
102
+ \resumeSubheading
103
+ {Senior Software Engineer}{Jan 2021 -- Present}
104
+ {Tech Company Inc.}{City, State}
105
+ \resumeItemListStart
106
+ \resumeItem{Led development of cloud-based microservices architecture serving 100k+ users}
107
+ \resumeItem{Implemented CI/CD pipeline reducing deployment time by 40\%}
108
+ \resumeItem{Mentored junior developers and conducted code reviews}
109
+ \resumeItemListEnd
110
+
111
+ \resumeSubheading
112
+ {Software Engineer}{Jan 2018 -- Dec 2020}
113
+ {Software Solutions LLC}{City, State}
114
+ \resumeItemListStart
115
+ \resumeItem{Developed RESTful APIs for client applications with Python and Django}
116
+ \resumeItem{Optimized database queries resulting in 30\% performance improvement}
117
+ \resumeItem{Collaborated with cross-functional teams to design new product features}
118
+ \resumeItemListEnd
119
+
120
+ \resumeSubHeadingListEnd
121
+
122
+ %----------------------------------------------------------------------------------------
123
+ % SKILLS
124
+ %----------------------------------------------------------------------------------------
125
+
126
+ \section{Skills}
127
+ \begin{itemize}[leftmargin=0.15in, label={}]
128
+ \small{\item{
129
+ \textbf{Languages}{: Python, JavaScript, TypeScript, Java, C++, SQL} \\
130
+ \textbf{Frameworks}{: React, Django, Flask, Express.js, Spring Boot} \\
131
+ \textbf{Tools}{: Docker, Kubernetes, AWS, Git, Jenkins, Jira} \\
132
+ \textbf{Databases}{: PostgreSQL, MongoDB, Redis, Elasticsearch} \\
133
+ }}
134
+ \end{itemize}
135
+
136
+ %----------------------------------------------------------------------------------------
137
+ % PROJECTS
138
+ %----------------------------------------------------------------------------------------
139
+
140
+ \section{Projects}
141
+ \resumeSubHeadingListStart
142
+ \resumeSubheading
143
+ {Personal Website}{https://github.com/johndoe/personal-website}
144
+ {Full-stack web application}{Jan 2021 -- Present}
145
+ \resumeItemListStart
146
+ \resumeItem{Designed and developed a personal portfolio website using React and Node.js}
147
+ \resumeItem{Implemented responsive design principles for optimal display across devices}
148
+ \resumeItemListEnd
149
+
150
+ \resumeSubheading
151
+ {Task Management App}{https://github.com/johndoe/task-manager}
152
+ {Mobile application}{Mar 2020 -- Nov 2020}
153
+ \resumeItemListStart
154
+ \resumeItem{Built a task management application using React Native and Firebase}
155
+ \resumeItem{Implemented user authentication, real-time database, and push notifications}
156
+ \resumeItemListEnd
157
+ \resumeSubHeadingListEnd
158
+
159
+ \end{document}