Last year, I graduated with a degree in Computer Science. Like many others in my position, I’ve been sending out countless CVs, tailoring them to specific job postings, but with no luck—just silence. I know Python and JavaScript pretty well, but every rejection or, worse, non-response feels like a gut punch.
The frustration gets worse when I see people in forums saying, “My boss is asking me to finish this task, and I have no idea how to do it. Help!”. These are things I consider “basic,” yet while I’m busy editing my CV to fit each job posting, I’m not even getting responses for jobs I know I’m capable of doing. So, I decided to automate this entire process—make my CV match job descriptions automatically and save myself time and frustration.
The Idea
The idea behind this project is simple: automate the process of customizing my CV for each job posting using AI, saving it in a format that’s optimized for Applicant Tracking Systems (ATS). This way, I can quickly apply to jobs without manually re-editing my CV every time a new opportunity arises.
Stack
Here are the tools I used to build this solution:
- Python: For writing the script and automating the process.
- Groq:We are fast AI inference, powered by LPU™ AI inference technology which delivers fast, affordable, and energy efficient AI. (From the web.)
-
Docx Library: To create
.docx
files that can be opened and edited in Word or any compatible software. - Pyperclip: For clipboard operations, so I can easily copy and paste job descriptions.
Workflow
The workflow is simple:
- Run the script with your current CV as input. (In txt file format.) Like this:
python3 script.py path/to/cv.txt
- Copy the job description to your clipboard and hit
enter
. - Select the language of the cv.
Spanish
orEnglish
. - The AI generates a tailored, ATS-friendly CV based on the job description.
- Ask for a file name and save the new CV as a
.docx
file with a name based on the job profile (e.g.,Data_Scientist.docx
). - Done! You now have a personalized CV for that job, ready to be sent.
Code Breakdown
Here’s the Python script I used to automate this process:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import logging
import pyperclip # Importing pyperclip to handle clipboard operations
from groq import Groq # Importing Groq for AI-powered text generation
# Set up logging to track the flow and any potential errors
logging.basicConfig(level=logging.INFO)
# Initialize the Groq client with the API key stored in environment variables
client = Groq(
api_key=os.environ.get("GROQ_API_KEY"),
)
def ask_question(task):
"""
Send a question to the Groq AI and get a response.
Args:
task (str): The question or task description to send to the AI.
Returns:
response: The AI's response to the question.
"""
chat_completion = client.chat.completions.create(
messages=[
{
"role": "user",
"content": task,
}
],
model="llama3-8b-8192", # Specify the AI model to use
)
return chat_completion # Return the AI's response
def read_file(file_path):
"""
Read and return the content of a text file.
Args:
file_path (str): The path to the text file to read.
Returns:
str: The content of the file, or None if an error occurs.
"""
try:
with open(file_path, "r") as file: # Open the file in read mode
return file.read() # Return the content of the file
except Exception as e:
logging.error(f"An error occurred while reading {file_path}: {e}") # Log any errors
return None # Return None if there's an error
def create_cv_content(cv_text, job_posting, language):
"""
Create tailored cv content for a job application based on CV and job posting.
Args:
cv_text (str): The content of the CV.
job_posting (str): The job posting text.
language (str): The language for the response ('es' for Spanish, 'en' for English).
Returns:
str: The generated cv content.
"""
# Set the prompt based on the selected language
language_prompt = "in Spanish" if language == "es" else "in English"
task = (f"Write a tailored cv content for a job application {language_prompt}. "
f"Here is my CV:\n\n{cv_text}\n\nAnd here is the job posting:\n\n{job_posting}")
response = ask_question(task).choices[0].message.content # Get the AI's response
return response # Return the generated cv content
def main():
"""
Main function to execute the script.
It handles user input, reads files, and generates tailored cv content.
"""
if len(sys.argv) < 2:
logging.error("Usage: python script.py <cv_path>")
sys.exit(1) # Exit if no CV path is provided
cv_path = sys.argv[1] # Get the CV file path from command-line arguments
# Clear the clipboard before prompting the user
pyperclip.copy("")
input("Please copy the job position text to the clipboard, then press Enter to continue...")
# Read the job position text from the clipboard
job_posting_text = pyperclip.paste()
cv_text = read_file(cv_path) # Read the CV content from the specified file
if cv_text is None:
sys.exit(1) # Exit if there's an error reading the CV
# Ask for the user's language preference
language = input("Select language for the response (es for Spanish, en for English): ").strip().lower()
while language not in ['es', 'en']:
language = input("Invalid choice. Please select 'es' for Spanish or 'en' for English: ").strip().lower()
# Generate the tailored cv content using the CV and job posting
cv_content = create_cv_content(cv_text, job_posting_text, language)
# Copy the tailored cv content to the clipboard for easy pasting
pyperclip.copy(cv_content)
# Inform the user that the job is done and display the cv content
print("----- Tailored Job Application CV -----")
print(cv_content)
print("\nThe tailored cv content has been copied to your clipboard. Job done!")
if __name__ == "__main__":
main() # Run the main function when the script is executed
IMPORTANT:
Likewise, the content of the generated CV should be reviewed and some formatting styles added. For ex. center, underline, align, etc.
Conclusion
This simple script allows me to automate the process of creating a job-specific, ATS-compatible CV, saving me time and reducing frustration. If this project proves successful, I’ll be sure to write a follow-up blog post about the next steps.
Thanks for reading!
Top comments (0)