File size: 3,729 Bytes
f0ad734 d88c8fe 0c36edf 4676010 d88c8fe 4676010 0c36edf 4676010 f0ad734 4676010 0e5ac9b 4676010 d88c8fe 4676010 d88c8fe 4676010 d88c8fe |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
import gradio as gr
import pdfplumber
import spacy
import os
# Load spaCy with minimal pipelines to save memory
try:
nlp = spacy.load("en_core_web_sm", disable=["ner", "lemmatizer"])
except Exception as e:
raise RuntimeError(f"Failed to load spaCy model: {str(e)}")
def generate_portfolio(resume_file):
# Check if a file was uploaded
if resume_file is None:
return "No file uploaded. Please upload a PDF resume."
# Extract text from PDF
try:
with pdfplumber.open(resume_file) as pdf:
text = "".join(page.extract_text() or "" for page in pdf.pages)
except Exception as e:
return f"Error processing PDF: {str(e)}"
# Parse resume with spaCy
doc = nlp(text)
data = {
"name": "",
"summary": "",
"experience": [],
"skills": [],
"contact": ""
}
for ent in doc.ents:
if ent.label_ == "PERSON" and not data["name"]:
data["name"] = ent.text
elif ent.label_ == "ORG":
data["experience"].append({"company": ent.text, "role": ""})
elif ent.label_ == "EMAIL":
data["contact"] = ent.text
# Extract skills (simple keyword-based)
skill_keywords = ["python", "javascript", "sql", "communication", "leadership"]
data["skills"] = [token.text for token in doc if token.text.lower() in skill_keywords]
data["summary"] = text[:200] + "..." # Truncate for demo
# Delete the uploaded file (privacy)
os.remove(resume_file)
# Generate portfolio HTML
portfolio_html = f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{data['name']}'s Portfolio</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<header class="bg-primary text-white text-center py-5">
<h1>{data['name']}</h1>
<p>Professional Portfolio</p>
</header>
<div class="container my-5">
<section>
<h2>About Me</h2>
<p>{data['summary']}</p>
</section>
<section>
<h2>Experience</h2>
{''.join([f'<div class="card mb-3"><div class="card-body"><h5 class="card-title">{exp["company"]}</h5><p class="card-text">{exp["role"]}</p></div></div>' for exp in data['experience']])}
</section>
<section>
<h2>Skills</h2>
<ul class="list-group">
{''.join([f'<li class="list-group-item">{skill}</li>' for skill in data['skills']])}
</ul>
</section>
<section>
<h2>Contact</h2>
<p>Email: {data['contact']}</p>
</section>
</div>
<footer class="bg-dark text-white text-center py-3">
<p>© 2025 {data['name']}</p>
<p>Generated by Resume-to-Portfolio AI. Your data was processed securely and not retained.</p>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
"""
return portfolio_html
# Gradio interface (adjusted for 3.50.0 compatibility)
interface = gr.Interface(
fn=generate_portfolio,
inputs=gr.inputs.File(label="Upload Resume (PDF)"),
outputs=gr.outputs.HTML(label="Your Portfolio"),
title="Resume to Portfolio Generator",
description="Upload your resume to generate a portfolio landing page. Your data is processed securely and not stored.",
allow_flagging="never"
)
interface.launch() |