CVOpt / app.py
Afeezee's picture
Update app.py
50afc78 verified
import os
import gradio as gr
from pdfminer.high_level import extract_text
from docx import Document
from groq import Groq
key = "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"
client = Groq(api_key=key)
# Function to read PDF files
def read_pdf(file_path):
return extract_text(file_path)
# Function to read DOCX files
def read_docx(file_path):
doc = Document(file_path)
return "\n".join([paragraph.text for paragraph in doc.paragraphs])
# Function to optimize CV using Llama 3.1 and Groq API
def optimize_cv_with_llama(cv_text, job_description):
try:
# Compose the prompt
system_message = (
"You are an experienced Human Resource expert with 30 years of experience working for major international companies. "
"Your task is to optimize the following CV or Resume based on the provided job description. Tailor the CV content to align "
"with the job requirements and highlight relevant skills, experiences, and achievements. Present the optimized CV in Markdown format. "
"Ensure the formatting is professional and avoid adding extra comments."
)
# Send the job description and CV text to the Groq API
completion = client.chat.completions.create(
model="meta-llama/llama-4-maverick-17b-128e-instruct",
messages=[
{"role": "system", "content": system_message},
{"role": "user", "content": f"Job Description:\n{job_description}\n\nCV:\n{cv_text}"}
],
temperature=0.7,
max_tokens=2048,
top_p=0.9,
stream=False,
)
# Return the optimized Markdown text
return ''.join([chunk.message.content for chunk in completion.choices])
except Exception as e:
return f"Error optimizing CV: {e}"
# Function to save optimized Markdown as DOCX
from markdown2 import markdown
from bs4 import BeautifulSoup
def save_markdown_to_docx(markdown_text, output_docx_path="optimized_cv.docx"):
# Convert Markdown to HTML
html_content = markdown(markdown_text)
# Parse HTML with BeautifulSoup
soup = BeautifulSoup(html_content, "html.parser")
# Create a new DOCX document
doc = Document()
# Iterate through HTML elements and map them to DOCX formatting
for element in soup.descendants:
if element.name == "h1":
para = doc.add_paragraph(element.text, style="Heading 1")
elif element.name == "h2":
para = doc.add_paragraph(element.text, style="Heading 2")
elif element.name == "h3":
para = doc.add_paragraph(element.text, style="Heading 3")
elif element.name == "ul": # Unordered list
for li in element.find_all("li"):
doc.add_paragraph(li.text, style="List Bullet")
elif element.name == "ol": # Ordered list
for li in element.find_all("li"):
doc.add_paragraph(li.text, style="List Number")
elif element.name == "p": # Paragraph
doc.add_paragraph(element.text)
elif element.name == "strong": # Bold text
para = doc.add_paragraph()
run = para.add_run(element.text)
run.bold = True
elif element.name == "em": # Italics
para = doc.add_paragraph()
run = para.add_run(element.text)
run.italic = True
elif element.name == "a": # Hyperlink
para = doc.add_paragraph(element.text) # Add the text of the hyperlink
# Add the URL as well, optionally
para.add_run(f" ({element.get('href')})").italic = True
# Save the document
doc.save(output_docx_path)
return output_docx_path
# Function to process file upload and optimization
def process_inputs(cv_file, job_description):
try:
# Extract text from uploaded file
file_path = cv_file.name
file_extension = os.path.splitext(file_path)[1].lower()
if file_extension == ".pdf":
cv_text = read_pdf(file_path)
elif file_extension == ".docx":
cv_text = read_docx(file_path)
else:
return "Unsupported file format", None
# Optimize the CV based on the job description
optimized_markdown = optimize_cv_with_llama(cv_text, job_description)
# Save the optimized Markdown as DOCX
output_docx_path = "optimized_cv.docx"
save_markdown_to_docx(optimized_markdown, output_docx_path)
return optimized_markdown, output_docx_path
except Exception as e:
return f"Error processing inputs: {e}", None
# Gradio Interface
def main():
with gr.Blocks() as app:
# Title and Description
gr.Markdown(
"""
# **AI-Powered CV or Resume Optimizer**
Optimize your CV or Resume to match job descriptions using the power of AI.
This application processes your uploaded CV along with a job description and generates a tailored, professional CV ready for submission.
"""
)
# Input components
file_input = gr.File(label="Upload Your Resume (PDF or DOCX)", file_count="single",
file_types=[".pdf", ".docx"], # <-- Ensures you can select PDF/DOCX in the picker
type="filepath" # <-- Returns a string path your code can read
)
job_description = gr.Textbox(
label="Job Description",
placeholder="Paste the job description here...",
lines=5
)
# Output components
markdown_output = gr.Markdown(label="Optimized CV Preview")
download_button = gr.File(label="Download Optimized CV (DOCX)")
# Button to process inputs
run_button = gr.Button("Optimize CV")
# Define the interaction logic
def handle_inputs(cv_file, job_description):
markdown_text, docx_path = process_inputs(cv_file, job_description)
return markdown_text, docx_path
run_button.click(
handle_inputs,
inputs=[file_input, job_description],
outputs=[markdown_output, download_button]
)
app.launch()
if __name__ == "__main__":
main()