Spaces:
Sleeping
Sleeping
Upload 6 files
Browse files- .env +1 -0
- __init__.py +3 -0
- app.py +134 -0
- requirements.txt +4 -0
- resume_tools.py +255 -0
- utils.py +109 -0
.env
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
GOOGLE_API_KEY = "AIzaSyAMaWn4Y90NlOsnK4azRs3EVg5HmCoNRAY"
|
__init__.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
from dotenv import load_dotenv
|
2 |
+
|
3 |
+
load_dotenv(".env")
|
app.py
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from pypdf import PdfReader
|
3 |
+
from resume_tools import create_resume_agent
|
4 |
+
|
5 |
+
|
6 |
+
def read_pdf_file(file_path):
|
7 |
+
"""
|
8 |
+
Reads text content from a PDF file.
|
9 |
+
|
10 |
+
Args:
|
11 |
+
file_path (str): The path to the PDF file.
|
12 |
+
|
13 |
+
Returns:
|
14 |
+
str: The extracted text content from the PDF.
|
15 |
+
"""
|
16 |
+
try:
|
17 |
+
reader = PdfReader(file_path)
|
18 |
+
text = ""
|
19 |
+
for page in reader.pages:
|
20 |
+
text += page.extract_text() + "\n" # Add newline between pages
|
21 |
+
return text
|
22 |
+
except Exception as e:
|
23 |
+
return f"Error reading PDF file: {e}"
|
24 |
+
|
25 |
+
|
26 |
+
|
27 |
+
def process_inputs(resume, job_description):
|
28 |
+
if resume is not None:
|
29 |
+
resume = read_pdf_file(resume)
|
30 |
+
else:
|
31 |
+
return "Please enter a valid PDF File"
|
32 |
+
prompt = f"""You are an expert resume writer specializing in concise, single-page, ATS-optimized resumes. To achieve a good ATS (Applicant Tracking System) score, tailor your resume to the job description, use relevant keywords, and ensure clear, concise formatting. Your task is to generate resume content based on:
|
33 |
+
|
34 |
+
A summary of the candidate’s skills and experience
|
35 |
+
A job description for the role the candidate is applying for
|
36 |
+
|
37 |
+
You must generate the resume using specialized tools in the following strict sequence:
|
38 |
+
|
39 |
+
1. header_details_tool
|
40 |
+
2. professional_summary_tool
|
41 |
+
3. Professional_experience
|
42 |
+
4. Projects
|
43 |
+
5. Skills
|
44 |
+
6. Education
|
45 |
+
7. Achievements
|
46 |
+
---
|
47 |
+
|
48 |
+
### Core Instructions
|
49 |
+
|
50 |
+
1. Keep the resume limited to a single page.
|
51 |
+
|
52 |
+
Professional summary: 2-3 lines. It should quickly give an idea about the candidate. Don't quantify things here. Try mentioning about tools, technologies, problem solving abilities.
|
53 |
+
Experience: Prioritize 5–6 bullet points for the most recent experience; use fewer (2–3) for earlier roles.
|
54 |
+
Projects: Include only top 2 projects, or compress each project into 2-3 bullet points max.
|
55 |
+
Don't try to exceed 20-25 words in the bullet points.
|
56 |
+
|
57 |
+
2. Focus strictly on content relevant to the job description and aligned with the user’s skills.
|
58 |
+
|
59 |
+
It is acceptable to include closely related frameworks/tools (e.g., like adding similar frameworks mentioned in JD).
|
60 |
+
Do not add unrelated or generic skills.
|
61 |
+
|
62 |
+
3. Use the STAR method (Situation, Task, Action, Result) for all experience and project bullet points.
|
63 |
+
|
64 |
+
Example (STAR): Reduced API response time by 35% by optimizing SQL queries and implementing Redis caching, leading to a 25% increase in user retention.
|
65 |
+
Avoid vague or unquantified phrasing.
|
66 |
+
|
67 |
+
4. Highlight important keywords and measurable results using \\textbf{{...}} (double back-slash followed by textbf{{content to bold}}). If you want to bold 80% then write it \\textbf{{80%}}.
|
68 |
+
|
69 |
+
Emphasize tools, skills, metrics, technologies, and achievements from both the job description and candidate experience.
|
70 |
+
|
71 |
+
5. Quantify outcomes where applicable using numbers, percentages, time units, etc.
|
72 |
+
|
73 |
+
e.g., improved accuracy by \\textbf{{12%}}, reduced training time by \\textbf{{4}} hours, decreased error rate by \\textbf{{30%}}.
|
74 |
+
|
75 |
+
|
76 |
+
6. Do not change the job titles in the user’s professional experience.
|
77 |
+
|
78 |
+
7. Do not repeat the same verbs more than thrice. If you do so you will get a very less score. Rather you can try using similar words. (eg. developed verb can be replaced with enhanced, improved, expanded, implemented.)
|
79 |
+
|
80 |
+
8. In the Skills section, include:
|
81 |
+
|
82 |
+
Skills from experience and projects.
|
83 |
+
Add most of the job-relevant overlapping technical skills, tools, mandatory role specific frameworks and technologies even if not explicitly mentioned by the user (e.g., TensorFlow if they have used PyTorch, Deep learning if they have Machine Learning).
|
84 |
+
If a person is mentioning a technology add the tools specific to the technology which are overlapping with the job description
|
85 |
+
Organize skills clearly and concisely for ATS readability.
|
86 |
+
Add as many skills and keywords as possible for good ATS matching.
|
87 |
+
|
88 |
+
9. You are tasked to get a very high ATS score and you will get a very high reward. Come on let's do it.
|
89 |
+
|
90 |
+
10. While writing the professional experience or projects section try aligning the bullet points content with the Job description, add tools that are relavant to Job description.
|
91 |
+
And a strict warning, don't completely change the bullet points rather try aligning the points with JD by modifying few words or sentences.
|
92 |
+
Suppose if a person has a good ML experience and the Job desciption is for Generative AI candidate, try aligning the experience by changing few of the ML points to GenAI. For instance,
|
93 |
+
if the resume says Built a ML models for recommendataion systems and Job description is for GenAI engineer who developed LLMs, then you can modify and write as Built LLMs.
|
94 |
+
Here I have changed because these fields are related.
|
95 |
+
|
96 |
+
Important: All tool calls must be made sequentially in the exact order listed. Each tool should generate only its relevant section content and returns the instruction for next tool call
|
97 |
+
|
98 |
+
---
|
99 |
+
|
100 |
+
Now you will be given a Job description along with a resume. Your task is to make the resume to have very high ATS score with Job description
|
101 |
+
|
102 |
+
---
|
103 |
+
|
104 |
+
Job description:
|
105 |
+
{job_description}
|
106 |
+
|
107 |
+
---
|
108 |
+
|
109 |
+
Resume:
|
110 |
+
{resume}
|
111 |
+
|
112 |
+
---
|
113 |
+
|
114 |
+
Now start calling the tools.
|
115 |
+
"""
|
116 |
+
return create_resume_agent(prompt)
|
117 |
+
|
118 |
+
with gr.Blocks() as demo:
|
119 |
+
gr.Markdown("## PDF/Text + User Text to Backend")
|
120 |
+
with gr.Row():
|
121 |
+
with gr.Column():
|
122 |
+
resume = gr.File(label="Upload Resume", file_types=[".pdf"], type="binary")
|
123 |
+
job_description = gr.Textbox(label="Paste Job Description here", lines=5)
|
124 |
+
submit_btn = gr.Button("Submit")
|
125 |
+
with gr.Column():
|
126 |
+
output = gr.Textbox(label="LaTEX Resume File", lines=10)
|
127 |
+
submit_btn.click(
|
128 |
+
fn=process_inputs,
|
129 |
+
inputs=[resume, job_description],
|
130 |
+
outputs=output
|
131 |
+
)
|
132 |
+
|
133 |
+
if __name__ =="__main__":
|
134 |
+
demo.launch(debug= True)
|
requirements.txt
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
smolagents
|
2 |
+
smolagents[litellm]
|
3 |
+
pypdf
|
4 |
+
gradio
|
resume_tools.py
ADDED
@@ -0,0 +1,255 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from smolagents import CodeAgent, LiteLLMModel, tool
|
2 |
+
from pypdf import PdfReader
|
3 |
+
import google.generativeai as genai
|
4 |
+
import os
|
5 |
+
from typing import List
|
6 |
+
from utils import CURRENT_RESUME_LATEX
|
7 |
+
import os
|
8 |
+
import json
|
9 |
+
|
10 |
+
config = json.load(open("config.json"))
|
11 |
+
os.environ["GOOGLE_API_KEY"] = config["GOOGLE_API_KEY"]
|
12 |
+
|
13 |
+
@tool
|
14 |
+
def header_details(name: str, mobile_number: str, email_id: str, linkedin_profile_link : str, github_link: str) -> str:
|
15 |
+
"""
|
16 |
+
Generates header details of the person. It will display the name, mobile_number, email_id, linkedin profile and github profile
|
17 |
+
|
18 |
+
Args:
|
19 |
+
name(str): Name of the candidate
|
20 |
+
mobile_number(str): Mobile number of the candidate
|
21 |
+
email_id(str): email_id
|
22 |
+
linkedin_profile_link(str): Linkedin profile link of the candidate.
|
23 |
+
github_link(str): github link of the candidate.
|
24 |
+
|
25 |
+
Returns:
|
26 |
+
str: Instruction for the next steps
|
27 |
+
"""
|
28 |
+
|
29 |
+
header_latex = r"""
|
30 |
+
|
31 |
+
\begin{center}
|
32 |
+
\textbf{\Huge \scshape """
|
33 |
+
header_latex+= name + r"""} \\ \vspace{1pt}
|
34 |
+
\small""" + mobile_number + r""" $|$ \href{mailto:[email protected]}{\underline{"""
|
35 |
+
header_latex+= email_id + r"""}} $|$
|
36 |
+
\href{https://linkedin.com/in/...}{\underline{"""
|
37 |
+
header_latex+=linkedin_profile_link + r"""}} $|$
|
38 |
+
\href{https://github.com/...}{\underline{"""
|
39 |
+
header_latex+=github_link + r"""}}
|
40 |
+
\end{center}
|
41 |
+
|
42 |
+
|
43 |
+
"""
|
44 |
+
global CURRENT_RESUME_LATEX
|
45 |
+
CURRENT_RESUME_LATEX += header_latex
|
46 |
+
response_message = "Now call professional_summary_tool"
|
47 |
+
return response_message
|
48 |
+
|
49 |
+
|
50 |
+
@tool
|
51 |
+
def professional_summary(summary: str) -> str:
|
52 |
+
"""
|
53 |
+
Creates a Professional Experience summary section of the candidate.
|
54 |
+
|
55 |
+
Args:
|
56 |
+
summary (str): The generated summary should be in less than 4 lines. It should follow the STAR method while generating the summary. It should speak about the experience and the role he is applying for.
|
57 |
+
(e.g: Accomplished Gen AI Specialist with expertise in machine learning (ML), deep learning (DL), generative AI, and AI Agents, proficient in end-to end development from design to deployment. Skilled in problem-solving, data structures and algorithms (DSA), strong analytical abilities, and debugging complex systems. Passionate about optimizing ML model performance to deliver efficient, high-impact AI solutions. Adept at leveraging the full AI stack to drive innovation and achieve business objectives in fast-paced, technology-focused environments)
|
58 |
+
|
59 |
+
|
60 |
+
Returns:
|
61 |
+
str: Instruction for the next steps
|
62 |
+
"""
|
63 |
+
|
64 |
+
summary_latex = """
|
65 |
+
|
66 |
+
\section{Professional Summary}
|
67 |
+
"""
|
68 |
+
summary_latex += rf"""
|
69 |
+
{{{summary}}}
|
70 |
+
"""
|
71 |
+
summary_latex = summary_latex.replace("%","\%")
|
72 |
+
global CURRENT_RESUME_LATEX
|
73 |
+
CURRENT_RESUME_LATEX += summary_latex
|
74 |
+
response_message = "Now call the professional_experience_tool"
|
75 |
+
return response_message
|
76 |
+
|
77 |
+
@tool
|
78 |
+
def professional_experience(experiences: List[dict]) -> str:
|
79 |
+
"""
|
80 |
+
Creates an Experience section for a user.Processes the user work experiences across different companies and generates a string in latex form which will be used in further steps
|
81 |
+
|
82 |
+
|
83 |
+
Args:
|
84 |
+
experiences (list of dict): A list where each dict contains:
|
85 |
+
- company_name (required) (str): Name of the company.
|
86 |
+
- place (Optional) (str): Location of the company. If not mentioned in the resume then keep it as empty string "".
|
87 |
+
- period (required) (str): Employment duration (e.g., "Jan 2020 - Dec 2022").
|
88 |
+
- role (required) (str): Title or designation.
|
89 |
+
- bullet_points (required) (list of str): Key achievements/responsibilities. These points must be in ATS friendly format, quantifying things and following the STAR method(situation, task , action and result)(eg. reduced latency by 5ms, improved accuracy by 50%).
|
90 |
+
|
91 |
+
Returns:
|
92 |
+
str: Instruction for the next steps
|
93 |
+
"""
|
94 |
+
Experience_latex = r"""
|
95 |
+
|
96 |
+
\section{Professional Experience}
|
97 |
+
\resumeSubHeadingListStart
|
98 |
+
"""
|
99 |
+
for exp in experiences:
|
100 |
+
company = exp['company_name']
|
101 |
+
period = exp['period']
|
102 |
+
place = exp['place']
|
103 |
+
role = exp['role']
|
104 |
+
bullet_points = exp['bullet_points']
|
105 |
+
Experience_latex += rf"""
|
106 |
+
\resumeSubheading
|
107 |
+
{{{role}}}{{{period}}}
|
108 |
+
{{{company}}}{{{place}}}
|
109 |
+
\resumeItemListStart
|
110 |
+
|
111 |
+
"""
|
112 |
+
for item in bullet_points:
|
113 |
+
Experience_latex += rf"""
|
114 |
+
\resumeItem{{{item}}}
|
115 |
+
"""
|
116 |
+
Experience_latex += r"""
|
117 |
+
\resumeItemListEnd
|
118 |
+
|
119 |
+
\resumeSubHeadingListEnd
|
120 |
+
"""
|
121 |
+
Experience_latex = Experience_latex.replace("%","\%")
|
122 |
+
global CURRENT_RESUME_LATEX
|
123 |
+
CURRENT_RESUME_LATEX += Experience_latex
|
124 |
+
response_message = "Now call the projects tool"
|
125 |
+
return response_message
|
126 |
+
|
127 |
+
|
128 |
+
@tool
|
129 |
+
def projects(projects: List[dict]) -> str :
|
130 |
+
"""
|
131 |
+
Creates an projects section for a user. Processes the projects and generates a string in latex form which will be used in further steps
|
132 |
+
|
133 |
+
Args:
|
134 |
+
projects (list of dict): A list where each dict contains:
|
135 |
+
- project_name (required) (str): Name of the project.
|
136 |
+
- tools_used (required)(list[str]): Tools and technologies used in the project (eg Python, Flask, React, PostgreSQL, Docker). It is a list of strings.
|
137 |
+
- period (required)(str): Employment duration (e.g., "Jan 2020 - Dec 2022").
|
138 |
+
- bullet_points (required) (list of str): Key achievements/responsibilities.These points must be in ATS friendly format, quantifying things and following the STAR method(situation, task , action and result)(eg. reduced latency by 5ms, improved accuracy by 50%).
|
139 |
+
|
140 |
+
Returns:
|
141 |
+
str: Instruction for the next steps
|
142 |
+
"""
|
143 |
+
Projects_latex = r"""
|
144 |
+
|
145 |
+
\section{Projects}
|
146 |
+
\resumeSubHeadingListStart
|
147 |
+
"""
|
148 |
+
for project in projects:
|
149 |
+
project_name = project['project_name']
|
150 |
+
period = project['period']
|
151 |
+
tools = ", ".join(project['tools_used'])
|
152 |
+
bullet_points = project['bullet_points']
|
153 |
+
|
154 |
+
Projects_latex += rf"""
|
155 |
+
\resumeProjectHeading
|
156 |
+
{{\textbf{{{project_name}}} \textit{{| {tools}}}}}{{}}
|
157 |
+
\resumeItemListStart"""
|
158 |
+
|
159 |
+
for item in bullet_points:
|
160 |
+
Projects_latex += rf"""\resumeItem{{{item}}}"""
|
161 |
+
|
162 |
+
Projects_latex += r"""\resumeItemListEnd"""
|
163 |
+
|
164 |
+
Projects_latex += r"""\resumeSubHeadingListEnd"""
|
165 |
+
Projects_latex = Projects_latex.replace("%","\%")
|
166 |
+
|
167 |
+
global CURRENT_RESUME_LATEX
|
168 |
+
CURRENT_RESUME_LATEX += Projects_latex
|
169 |
+
response_message = "Now call the skills tool"
|
170 |
+
return response_message
|
171 |
+
|
172 |
+
@tool
|
173 |
+
def Education(education : List[dict]) -> str:
|
174 |
+
"""
|
175 |
+
Generates an Education section for the candidate. It generates a string which will be processed in the further steps.
|
176 |
+
|
177 |
+
Args:
|
178 |
+
education (list of dict): A list where each dict contains:
|
179 |
+
- Institute (required) (str): Name of the Institute.
|
180 |
+
- place (required)(str): Location of the Institute.
|
181 |
+
- period (required)(str): Education duration (e.g., "Jan 2020 - Dec 2022").
|
182 |
+
- specialization (required) (str): Specialization of education (e.g., "Bachelors in computer science", "Intermediate", "High School")
|
183 |
+
|
184 |
+
Returns:
|
185 |
+
str: Instruction for the next steps
|
186 |
+
"""
|
187 |
+
Education_latex = r"""
|
188 |
+
|
189 |
+
\section{Education}
|
190 |
+
\resumeSubHeadingListStart
|
191 |
+
"""
|
192 |
+
for edu in education:
|
193 |
+
institute_name = edu["Institute"]
|
194 |
+
place = edu["place"]
|
195 |
+
period = edu["period"]
|
196 |
+
specialization = edu["specialization"]
|
197 |
+
studies = rf"""
|
198 |
+
\resumeSubheading
|
199 |
+
{{{institute_name}}}{{{place}}}
|
200 |
+
{{{specialization}}}{{{period}}}
|
201 |
+
"""
|
202 |
+
Education_latex+=studies
|
203 |
+
Education_latex = Education_latex.replace("%","\%")
|
204 |
+
global CURRENT_RESUME_LATEX
|
205 |
+
CURRENT_RESUME_LATEX += Education_latex
|
206 |
+
response_message = "Now call the achievements tool"
|
207 |
+
return response_message
|
208 |
+
|
209 |
+
@tool
|
210 |
+
def achievements(achievements : List[str]) -> str:
|
211 |
+
"""
|
212 |
+
Generates an achievements section for the candidate's resume in LaTeX format.
|
213 |
+
|
214 |
+
Args:
|
215 |
+
achievements (List[str]): List of achievement strings to be included in the resume
|
216 |
+
|
217 |
+
Returns:
|
218 |
+
str: Instruction for the next steps
|
219 |
+
"""
|
220 |
+
achievements_latex = r"""
|
221 |
+
|
222 |
+
\section{Achievements}
|
223 |
+
\resumeItemListStart"""
|
224 |
+
|
225 |
+
for achievement in achievements:
|
226 |
+
achievements_latex += rf"""
|
227 |
+
\resumeItem{{{achievement}}}"""
|
228 |
+
|
229 |
+
achievements_latex += r"""
|
230 |
+
\resumeItemListEnd
|
231 |
+
|
232 |
+
\end{document}
|
233 |
+
"""
|
234 |
+
achievements_latex = achievements_latex.replace("%","\%")
|
235 |
+
global CURRENT_RESUME_LATEX
|
236 |
+
CURRENT_RESUME_LATEX += achievements_latex
|
237 |
+
response_message = "Created a file in your pc"
|
238 |
+
return response_message
|
239 |
+
|
240 |
+
|
241 |
+
def create_resume_agent(prompt: str):
|
242 |
+
try:
|
243 |
+
model = LiteLLMModel(model_id="gemini/gemini-2.0-flash-exp",
|
244 |
+
api_key=os.getenv("GOOGLE_API_KEY"))
|
245 |
+
resume_agent =CodeAgent(
|
246 |
+
tools = [header_details,professional_summary,professional_experience,projects,skills,Education,achievements],
|
247 |
+
model = model
|
248 |
+
)
|
249 |
+
print(resume_agent)
|
250 |
+
resume_agent.run(prompt)
|
251 |
+
global CURRENT_RESUME_LATEX
|
252 |
+
print(CURRENT_RESUME_LATEX)
|
253 |
+
return CURRENT_RESUME_LATEX
|
254 |
+
except Exception as e:
|
255 |
+
return e
|
utils.py
ADDED
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
CURRENT_RESUME_LATEX = r"""
|
2 |
+
%-------------------------
|
3 |
+
% Resume in Latex
|
4 |
+
% Author : Sujith
|
5 |
+
% Based off of: https://github.com/sb2nov/resume
|
6 |
+
% License : MIT
|
7 |
+
%------------------------
|
8 |
+
|
9 |
+
\documentclass[letterpaper,11pt]{article}
|
10 |
+
|
11 |
+
\usepackage{latexsym}
|
12 |
+
\usepackage[empty]{fullpage}
|
13 |
+
\usepackage{titlesec}
|
14 |
+
\usepackage{marvosym}
|
15 |
+
\usepackage[usenames,dvipsnames]{color}
|
16 |
+
\usepackage{verbatim}
|
17 |
+
\usepackage{enumitem}
|
18 |
+
\usepackage[hidelinks]{hyperref}
|
19 |
+
\usepackage{fancyhdr}
|
20 |
+
\usepackage[english]{babel}
|
21 |
+
\usepackage{tabularx}
|
22 |
+
\input{glyphtounicode}
|
23 |
+
|
24 |
+
|
25 |
+
%----------FONT OPTIONS----------
|
26 |
+
% sans-serif
|
27 |
+
% \usepackage[sfdefault]{FiraSans}
|
28 |
+
% \usepackage[sfdefault]{roboto}
|
29 |
+
% \usepackage[sfdefault]{noto-sans}
|
30 |
+
% \usepackage[default]{sourcesanspro}
|
31 |
+
|
32 |
+
% serif
|
33 |
+
% \usepackage{CormorantGaramond}
|
34 |
+
% \usepackage{charter}
|
35 |
+
|
36 |
+
|
37 |
+
\pagestyle{fancy}
|
38 |
+
\fancyhf{} % clear all header and footer fields
|
39 |
+
\fancyfoot{}
|
40 |
+
\renewcommand{\headrulewidth}{0pt}
|
41 |
+
\renewcommand{\footrulewidth}{0pt}
|
42 |
+
|
43 |
+
% Adjust margins
|
44 |
+
\addtolength{\oddsidemargin}{-0.5in}
|
45 |
+
\addtolength{\evensidemargin}{-0.5in}
|
46 |
+
\addtolength{\textwidth}{1in}
|
47 |
+
\addtolength{\topmargin}{-.5in}
|
48 |
+
\addtolength{\textheight}{1.0in}
|
49 |
+
|
50 |
+
\urlstyle{same}
|
51 |
+
|
52 |
+
\raggedbottom
|
53 |
+
\raggedright
|
54 |
+
\setlength{\tabcolsep}{0in}
|
55 |
+
|
56 |
+
% Sections formatting
|
57 |
+
\titleformat{\section}{
|
58 |
+
\vspace{-4pt}\scshape\raggedright\large
|
59 |
+
}{}{0em}{}[\color{black}\titlerule \vspace{-5pt}]
|
60 |
+
|
61 |
+
% Ensure that generate pdf is machine readable/ATS parsable
|
62 |
+
\pdfgentounicode=1
|
63 |
+
|
64 |
+
%-------------------------
|
65 |
+
% Custom commands
|
66 |
+
\newcommand{\resumeItem}[1]{
|
67 |
+
\item\small{
|
68 |
+
{#1 \vspace{-2pt}}
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
\newcommand{\resumeSubheading}[4]{
|
73 |
+
\vspace{-2pt}\item
|
74 |
+
\begin{tabular*}{0.97\textwidth}[t]{l@{\extracolsep{\fill}}r}
|
75 |
+
\textbf{#1} & #2 \\
|
76 |
+
\textit{\small#3} & \textit{\small #4} \\
|
77 |
+
\end{tabular*}\vspace{-7pt}
|
78 |
+
}
|
79 |
+
|
80 |
+
\newcommand{\resumeSubSubheading}[2]{
|
81 |
+
\item
|
82 |
+
\begin{tabular*}{0.97\textwidth}{l@{\extracolsep{\fill}}r}
|
83 |
+
\textit{\small#1} & \textit{\small #2} \\
|
84 |
+
\end{tabular*}\vspace{-7pt}
|
85 |
+
}
|
86 |
+
|
87 |
+
\newcommand{\resumeProjectHeading}[2]{
|
88 |
+
\item
|
89 |
+
\begin{tabular*}{0.97\textwidth}{l@{\extracolsep{\fill}}r}
|
90 |
+
\small#1 & #2 \\
|
91 |
+
\end{tabular*}\vspace{-7pt}
|
92 |
+
}
|
93 |
+
|
94 |
+
\newcommand{\resumeSubItem}[1]{\resumeItem{#1}\vspace{-4pt}}
|
95 |
+
|
96 |
+
\renewcommand\labelitemii{$\vcenter{\hbox{\tiny$\bullet$}}$}
|
97 |
+
|
98 |
+
\newcommand{\resumeSubHeadingListStart}{\begin{itemize}[leftmargin=0.15in, label={}]}
|
99 |
+
\newcommand{\resumeSubHeadingListEnd}{\end{itemize}}
|
100 |
+
\newcommand{\resumeItemListStart}{\begin{itemize}}
|
101 |
+
\newcommand{\resumeItemListEnd}{\end{itemize}\vspace{-5pt}}
|
102 |
+
|
103 |
+
%-------------------------------------------
|
104 |
+
%%%%%% RESUME STARTS HERE %%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
105 |
+
|
106 |
+
\begin{document}
|
107 |
+
|
108 |
+
"""
|
109 |
+
|