aryn25 commited on
Commit
eb68082
·
verified ·
1 Parent(s): bb9ead0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -90
app.py CHANGED
@@ -1,126 +1,115 @@
1
- # pip install transformers torch accelerate pdfplumber fpdf
 
2
 
 
3
  from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM
4
  import pdfplumber
5
  from fpdf import FPDF
6
  import re
 
7
 
8
- # === CONFIG ===
9
  MODEL_NAME = "MBZUAI/LaMini-Flan-T5-783M"
10
- PDF_INPUT = "Resume.Aryan-Salge.pdf"
11
- PDF_OUTPUT = "Final_Classic_Resume.pdf"
12
-
13
- JOB_DESCRIPTION = """
14
- Looking for a Customer Success Analyst skilled in CRM tools, stakeholder communication,
15
- data analysis, and reporting using Excel or Tableau.
16
- """
17
-
18
- # === 1. Extract Resume Text ===
19
- def extract_text(pdf_path):
20
- with pdfplumber.open(pdf_path) as pdf:
21
- return "\n".join(page.extract_text() or "" for page in pdf.pages)
22
-
23
- raw_resume = extract_text(PDF_INPUT)
24
-
25
- # === 2. Load Model ===
26
  tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
27
  model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME)
28
  generator = pipeline("text2text-generation", model=model, tokenizer=tokenizer)
29
 
30
- # === 3. Define Sections to Rewrite ===
31
- sections = {
32
- "Professional Summary": "",
33
- "Skills": "",
34
- "Work Experience": "",
35
- "Projects": "",
36
- "Education": "",
37
- "Certifications": "",
38
- "Leadership": ""
39
- }
40
-
41
- # === 4. Extract Section Texts from Resume ===
42
- for section in sections.keys():
43
- match = re.search(rf"{section.upper()}\n(.+?)(?=\n[A-Z ]{{4,}}|\Z)", raw_resume, re.DOTALL)
44
- if match:
45
- sections[section] = match.group(1).strip()
46
-
47
- # === 5. Rewrite Each Section Using AI ===
48
- def rewrite_section(section_title, content):
49
- if not content.strip():
50
- return ""
 
 
 
 
51
  prompt = f"""
52
- Rewrite the following section of a resume titled '{section_title}' to align with the job description below.
53
  Make it concise, professional, and rich in job-relevant keywords.
54
 
55
  Section:
56
  {content}
57
 
58
  Job Description:
59
- {JOB_DESCRIPTION}
60
  """
61
- result = generator(prompt, max_length=512, do_sample=True, top_p=0.9, temperature=0.7)[0]["generated_text"]
62
  return result.strip()
63
 
64
- rewritten_sections = {title: rewrite_section(title, content) for title, content in sections.items()}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
- # === 6. PDF Generator (Classic Resume Format) ===
67
- def save_resume_to_pdf(filename, personal_info, rewritten):
 
68
  pdf = FPDF()
69
  pdf.add_page()
70
  pdf.set_auto_page_break(auto=True, margin=15)
71
- pdf.set_font("Arial", size=12)
72
 
73
- # HEADER
74
  pdf.set_font("Arial", style="B", size=14)
75
- pdf.cell(200, 10, txt=personal_info["name"], ln=True, align="C")
76
  pdf.set_font("Arial", size=11)
77
- pdf.cell(200, 10, txt=personal_info["contact"], ln=True, align="C")
78
  pdf.ln(5)
79
 
80
- # SECTIONS
81
  for title, body in rewritten.items():
82
- if not body.strip():
83
- continue
84
  pdf.set_font("Arial", style="B", size=12)
85
  pdf.cell(200, 10, txt=title.upper(), ln=True)
86
  pdf.set_font("Arial", size=11)
87
- for line in body.split("\n"):
88
- pdf.multi_cell(0, 10, line.strip())
 
 
 
89
  pdf.ln(4)
90
 
91
- pdf.output(filename)
92
- print(f"✅ Resume saved as: {filename}")
93
-
94
- # === 7. Personal Header (manually extracted or hardcoded for now)
95
- def extract_personal_info(text):
96
- # Extract name: first non-empty line
97
- name = text.strip().split("\n")[0].strip()
98
-
99
- # Extract email
100
- email_match = re.search(r"[\w\.-]+@[\w\.-]+", text)
101
- email = email_match.group(0) if email_match else ""
102
-
103
- # Extract phone number (very flexible pattern)
104
- phone_match = re.search(r"(\+?\d[\d\s\-\(\)]{7,})", text)
105
- phone = phone_match.group(0).strip() if phone_match else ""
106
-
107
- # Extract LinkedIn / GitHub / site
108
- links = re.findall(r"(https?://[^\s]+|www\.[^\s]+)", text)
109
- linked_text = " | ".join(links)
110
-
111
- # Extract location if found
112
- location_match = re.search(r"\b(Dublin|Ireland|Mumbai|Pune|Hyderabad|New York|London|[A-Z][a-z]+,?\s?[A-Z][a-z]+?)\b", text)
113
- location = location_match.group(0) if location_match else ""
114
-
115
- contact_string = " | ".join(filter(None, [email, phone, linked_text, location]))
116
-
117
- return {
118
- "name": name.upper(),
119
- "contact": contact_string
120
- }
121
-
122
- # Use it:
123
- personal_info = extract_personal_info(raw_resume)
124
-
125
- # === 8. Generate the Final Resume PDF
126
- save_resume_to_pdf(PDF_OUTPUT, personal_info, rewritten_sections)
 
1
+ # Hugging Face Spaces-ready version of your JobPrep.AI classic resume generator
2
+ # Upload resume PDF + paste job description → get AI-rewritten resume PDF
3
 
4
+ import gradio as gr
5
  from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM
6
  import pdfplumber
7
  from fpdf import FPDF
8
  import re
9
+ import os
10
 
 
11
  MODEL_NAME = "MBZUAI/LaMini-Flan-T5-783M"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
13
  model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME)
14
  generator = pipeline("text2text-generation", model=model, tokenizer=tokenizer)
15
 
16
+ # Extract raw resume text from uploaded PDF
17
+ def extract_text(pdf_file):
18
+ with pdfplumber.open(pdf_file.name) as pdf:
19
+ return "\n".join(page.extract_text() or "" for page in pdf.pages)
20
+
21
+ # Extract name, email, phone, links from resume
22
+ def extract_personal_info(text):
23
+ name = text.strip().split("\n")[0].strip()
24
+ email = re.search(r"[\w\.-]+@[\w\.-]+", text)
25
+ phone = re.search(r"(\+?\d[\d\s\-\(\)]{7,})", text)
26
+ links = re.findall(r"(https?://[^\s]+|www\.[^\s]+)", text)
27
+ location = re.search(r"\b(Dublin|Ireland|[A-Z][a-z]+,?\s?[A-Z][a-z]+?)\b", text)
28
+ return {
29
+ "name": name.upper(),
30
+ "contact": " | ".join(filter(None, [
31
+ email.group(0) if email else "",
32
+ phone.group(0).strip() if phone else "",
33
+ " | ".join(links),
34
+ location.group(0) if location else ""
35
+ ]))
36
+ }
37
+
38
+ # Rewrite section using LLM
39
+ def rewrite_section(title, content, job):
40
+ if not content.strip(): return ""
41
  prompt = f"""
42
+ Rewrite the following section of a resume titled '{title}' to align with the job description below.
43
  Make it concise, professional, and rich in job-relevant keywords.
44
 
45
  Section:
46
  {content}
47
 
48
  Job Description:
49
+ {job}
50
  """
51
+ result = generator(prompt, max_length=512, do_sample=True, top_p=0.9, temperature=0.7)[0]['generated_text']
52
  return result.strip()
53
 
54
+ # Generate and save the final resume PDF
55
+ def generate_resume(pdf_file, job_description):
56
+ raw_text = extract_text(pdf_file)
57
+ personal = extract_personal_info(raw_text)
58
+
59
+ sections = {
60
+ "Professional Summary": "",
61
+ "Skills": "",
62
+ "Work Experience": "",
63
+ "Projects": "",
64
+ "Education": "",
65
+ "Certifications": "",
66
+ "Leadership": ""
67
+ }
68
+
69
+ for sec in sections.keys():
70
+ match = re.search(rf"{sec.upper()}\n(.+?)(?=\n[A-Z ]{{4,}}|\Z)", raw_text, re.DOTALL)
71
+ if match:
72
+ sections[sec] = match.group(1).strip()
73
 
74
+ rewritten = {title: rewrite_section(title, content, job_description) for title, content in sections.items()}
75
+
76
+ out_path = "final_resume.pdf"
77
  pdf = FPDF()
78
  pdf.add_page()
79
  pdf.set_auto_page_break(auto=True, margin=15)
80
+ pdf.set_font("Arial", size=11)
81
 
 
82
  pdf.set_font("Arial", style="B", size=14)
83
+ pdf.cell(200, 10, txt=personal['name'], ln=True, align="C")
84
  pdf.set_font("Arial", size=11)
85
+ pdf.multi_cell(0, 10, personal['contact'], align="C")
86
  pdf.ln(5)
87
 
 
88
  for title, body in rewritten.items():
89
+ if not body.strip(): continue
 
90
  pdf.set_font("Arial", style="B", size=12)
91
  pdf.cell(200, 10, txt=title.upper(), ln=True)
92
  pdf.set_font("Arial", size=11)
93
+ bullets = re.split(r"\s*-\s+", body.strip())
94
+ for bullet in bullets:
95
+ bullet = bullet.strip()
96
+ if bullet:
97
+ pdf.multi_cell(0, 10, f"- {bullet}")
98
  pdf.ln(4)
99
 
100
+ pdf.output(out_path)
101
+ return out_path
102
+
103
+ # Gradio Interface
104
+ demo = gr.Interface(
105
+ fn=generate_resume,
106
+ inputs=[
107
+ gr.File(label="Upload Your Resume PDF", type="file"),
108
+ gr.Textbox(label="Paste Job Description", lines=7, placeholder="Enter the job description here")
109
+ ],
110
+ outputs=gr.File(label="Download Final Resume PDF"),
111
+ title="JobPrep.AI | Resume Optimizer",
112
+ description="Upload your resume and tailor it instantly to any job description."
113
+ )
114
+
115
+ demo.launch()