Imports
We start by importing just a few hand Python libraries. The important thing ones are openai for accessing GPT-4o-mini, in addition to markdown and weasyprint to create a PDF version of the ultimate resume. Note: An OpenAI API secret is required for this project, which I imported from a separate Python script.
from IPython.display import display, Markdown
from openai import OpenAI
from top_secret import my_skfrom markdown import markdown
from weasyprint import HTML
Step 1: Input Resume & JD
Next, we’ll load our input resume into Python as a string and use Python’s input() function to permit us to copy-paste it into any job description after we run the script.
# open and browse the markdown file
with open("resumes/resume.md", "r", encoding="utf-8") as file:
resume_string = file.read()# input job description
jd_string = input()
A detail here is that the resume is saved in a markdown format. This is vital because it would encourage GPT-4o-mini to generate a brand new resume in markdown, which we will easily style right into a PDF. Note: ChatGPT (or the like) can convert your PDF resume to markdown.
Step 2: Construct Prompt
With our resume and JD imported, we will now craft a prompt to instruct the model to optimize the resume. A professional tip here is to use ChatGPT to put in writing an initial version of this prompt because 1) it’s pretty long, and a couple of) LLMs tend to put in writing instructions more aligned with the expectations of other LLMs.
After some experimentation, I ended up with the next prompt template, which rewrites the resume and makes additional suggestions for improvement if skill gaps exist.
prompt_template = lambda resume_string, jd_string : f"""
You're knowledgeable resume optimization expert specializing in tailoring
resumes to specific job descriptions. Your goal is to optimize my resume and
provide actionable suggestions for improvement to align with the goal role.### Guidelines:
1. **Relevance**:
- Prioritize experiences, skills, and achievements **most relevant to the
job description**.
- Remove or de-emphasize irrelevant details to make sure a **concise** and
**targeted** resume.
- Limit work experience section to 2-3 most relevant roles
- Limit bullet points under each role to 2-3 most relevant impacts
2. **Motion-Driven Results**:
- Use **strong motion verbs** and **quantifiable results** (e.g.,
percentages, revenue, efficiency improvements) to focus on impact.
3. **Keyword Optimization**:
- Integrate **keywords** and phrases from the job description naturally to
optimize for ATS (Applicant Tracking Systems).
4. **Additional Suggestions** *(If Gaps Exist)*:
- If the resume doesn't fully align with the job description, suggest:
1. **Additional technical or soft skills** that I could add to make my
profile stronger.
2. **Certifications or courses** I could pursue to bridge the gap.
3. **Project ideas or experiences** that will higher align with the role.
5. **Formatting**:
- Output the tailored resume in **clean Markdown format**.
- Include an **"Additional Suggestions"** section at the tip with
actionable improvement recommendations.
---
### Input:
- **My resume**:
{resume_string}
- **The job description**:
{jd_string}
---
### Output:
1. **Tailored Resume**:
- A resume in **Markdown format** that emphasizes relevant experience,
skills, and achievements.
- Incorporates job description **keywords** to optimize for ATS.
- Uses strong language and is not any longer than **one page**.
2. **Additional Suggestions** *(if applicable)*:
- List **skills** that might strengthen alignment with the role.
- Recommend **certifications or courses** to pursue.
- Suggest **specific projects or experiences** to develop.
"""
Step 3: Make API Call
Using the above prompt template, we will dynamically construct a prompt using the input resume and JD after which send it to OpenAI via their API.
# create prompt
prompt = prompt_template(resume_string, jd_string)# setup api client
client = OpenAI(api_key=my_sk)
# make api call
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Expert resume writer"},
{"role": "user", "content": prompt}
],
temperature = 0.7
)
# extract response
response_string = response.selections[0].message.content
Step 4: Save Latest Resume
Finally, we will extract the optimized resume and suggestions for improvement.
# separate recent resume from improvement suggestions
response_list = response_string.split("## Additional Suggestions")
For the resume, we will convert the markdown output to HTML using the markdown library. Then, convert the HTML to a PDF using weasyprint.
# save as PDF
output_pdf_file = "resumes/resume_new.pdf"# Convert Markdown to HTML
html_content = markdown(response_list[0])
# Convert HTML to PDF and save
HTML(string=html_content).write_pdf(output_pdf_file,
stylesheets=['resumes/style.css'])
Here’s what the looks like.
For the development suggestions, we will print those directly.
display(Markdown(response_list[1]))
Bonus: Construct a GUI
While the code above streamlines this process to some extent, we will do higher. To enhance the usability of this tool, we will create an easy web interface using Gradio.
The ultimate product is shown below. A user can upload a markdown file of their resume and paste it into any job description more straightforwardly. I also added an area where users can edit the brand new resume before exporting it as a PDF.
The example code is accessible on the GitHub repository here. Take a look at the YouTube video to see me talk through the code.
While tailoring one’s resume to specific job descriptions is an efficient technique to make an application stand out, it could be quite tedious. Here, we walk through the implementation of an AI-powered resume optimization tool using Python and OpenAI’s API.
If you will have any questions or need to dive deeper into any of the topics covered, let me know within the comments 🙂
—
y2b.io helped me write this text.