|
|
|
|
|
|
|
|
|
|
|
import gradio as gr |
|
|
from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM |
|
|
import pdfplumber |
|
|
from fpdf import FPDF |
|
|
import re |
|
|
import os |
|
|
|
|
|
MODEL_NAME = "MBZUAI/LaMini-Flan-T5-783M" |
|
|
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME) |
|
|
model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME) |
|
|
generator = pipeline("text2text-generation", model=model, tokenizer=tokenizer) |
|
|
|
|
|
|
|
|
def extract_text(pdf_file): |
|
|
with pdfplumber.open(pdf_file.name) as pdf: |
|
|
return "\n".join(page.extract_text() or "" for page in pdf.pages) |
|
|
|
|
|
|
|
|
def extract_personal_info(text): |
|
|
name = text.strip().split("\n")[0].strip() |
|
|
email = re.search(r"[\w\.-]+@[\w\.-]+", text) |
|
|
phone = re.search(r"(\+?\d[\d\s\-\(\)]{7,})", text) |
|
|
links = re.findall(r"(https?://[^\s]+|www\.[^\s]+)", text) |
|
|
location = re.search(r"\b(Dublin|Ireland|[A-Z][a-z]+,?\s?[A-Z][a-z]+?)\b", text) |
|
|
return { |
|
|
"name": name.upper(), |
|
|
"contact": " | ".join(filter(None, [ |
|
|
email.group(0) if email else "", |
|
|
phone.group(0).strip() if phone else "", |
|
|
" | ".join(links), |
|
|
location.group(0) if location else "" |
|
|
])) |
|
|
} |
|
|
|
|
|
|
|
|
def rewrite_section(title, content, job): |
|
|
if not content.strip(): return "" |
|
|
prompt = f""" |
|
|
Rewrite the following section of a resume titled '{title}' to align with the job description below. |
|
|
Make it concise, professional, and rich in job-relevant keywords. |
|
|
|
|
|
Section: |
|
|
{content} |
|
|
|
|
|
Job Description: |
|
|
{job} |
|
|
""" |
|
|
result = generator(prompt, max_length=512, do_sample=True, top_p=0.9, temperature=0.7)[0]['generated_text'] |
|
|
return result.strip() |
|
|
|
|
|
|
|
|
def generate_resume(pdf_file, job_description): |
|
|
raw_text = extract_text(pdf_file) |
|
|
personal = extract_personal_info(raw_text) |
|
|
|
|
|
sections = { |
|
|
"Professional Summary": "", |
|
|
"Skills": "", |
|
|
"Work Experience": "", |
|
|
"Projects": "", |
|
|
"Education": "", |
|
|
"Certifications": "", |
|
|
"Leadership": "" |
|
|
} |
|
|
|
|
|
for sec in sections.keys(): |
|
|
match = re.search(rf"{sec.upper()}\n(.+?)(?=\n[A-Z ]{{4,}}|\Z)", raw_text, re.DOTALL) |
|
|
if match: |
|
|
sections[sec] = match.group(1).strip() |
|
|
|
|
|
rewritten = {title: rewrite_section(title, content, job_description) for title, content in sections.items()} |
|
|
|
|
|
out_path = "final_resume.pdf" |
|
|
pdf = FPDF() |
|
|
pdf.add_page() |
|
|
pdf.set_auto_page_break(auto=True, margin=15) |
|
|
pdf.set_font("Arial", size=11) |
|
|
|
|
|
pdf.set_font("Arial", style="B", size=14) |
|
|
pdf.cell(200, 10, txt=personal['name'], ln=True, align="C") |
|
|
pdf.set_font("Arial", size=11) |
|
|
pdf.multi_cell(0, 10, personal['contact'], align="C") |
|
|
pdf.ln(5) |
|
|
|
|
|
for title, body in rewritten.items(): |
|
|
if not body.strip(): continue |
|
|
pdf.set_font("Arial", style="B", size=12) |
|
|
pdf.cell(200, 10, txt=title.upper(), ln=True) |
|
|
pdf.set_font("Arial", size=11) |
|
|
bullets = re.split(r"\s*-\s+", body.strip()) |
|
|
for bullet in bullets: |
|
|
bullet = bullet.strip() |
|
|
if bullet: |
|
|
pdf.multi_cell(0, 10, f"- {bullet}") |
|
|
pdf.ln(4) |
|
|
|
|
|
pdf.output(out_path) |
|
|
return out_path |
|
|
|
|
|
|
|
|
demo = gr.Interface( |
|
|
fn=generate_resume, |
|
|
inputs=[ |
|
|
gr.File(label="Upload Your Resume PDF", type="filepath"), |
|
|
gr.Textbox(label="Paste Job Description", lines=7, placeholder="Enter the job description here") |
|
|
], |
|
|
outputs=gr.File(label="Download Final Resume PDF"), |
|
|
title="JobPrep.AI | Resume Optimizer", |
|
|
description="Upload your resume and tailor it instantly to any job description." |
|
|
) |
|
|
|
|
|
demo.launch() |
|
|
|