import gradio as gr
import fitz
import docx
from sentence_transformers import SentenceTransformer, util
from gtts import gTTS
import tempfile
# Load the model
model = SentenceTransformer("all-MiniLM-L6-v2")
# Define a multi-domain skill set
top_skills = [
# Tech
"Python", "JavaScript", "SQL", "Machine Learning", "AWS", "Docker", "React",
# Marketing
"SEO", "Content Creation", "Brand Management", "Google Analytics", "Social Media Marketing",
# Finance
"Financial Analysis", "Accounting", "Risk Management",
# Healthcare
"Patient Care", "Diagnosis", "Treatment Planning",
# Education
"Lesson Planning", "Curriculum Design", "Classroom Management",
# Soft Skills
"Communication", "Leadership", "Teamwork", "Problem Solving", "Critical Thinking"
]
# Job mapping
job_roles = [
("Data Analyst", {"Python", "SQL", "Data Analysis"}),
("Frontend Developer", {"JavaScript", "React"}),
("Backend Developer", {"Python", "Docker", "AWS"}),
("Machine Learning Engineer", {"Machine Learning", "Python"}),
("Marketing Manager", {"SEO", "Content Creation", "Brand Management"}),
("Digital Marketer", {"Google Analytics", "Social Media Marketing", "Content Creation"}),
("Financial Analyst", {"Financial Analysis", "Accounting"}),
("Risk Manager", {"Risk Management", "Accounting"}),
("Nurse", {"Patient Care", "Diagnosis"}),
("Healthcare Administrator", {"Treatment Planning", "Leadership"}),
("Teacher", {"Lesson Planning", "Classroom Management"}),
("Project Manager", {"Leadership", "Project Management"})
]
def extract_text_from_pdf(pdf_file):
doc = fitz.open(pdf_file)
text = ""
for page in doc:
text += page.get_text()
return text
def extract_text_from_docx(docx_file):
doc = docx.Document(docx_file)
return "\n".join([p.text for p in doc.paragraphs])
def detect_skills(text):
sentences = [s.strip() for s in text.split(".") if len(s.strip()) > 5]
if not sentences:
return [], []
sentence_embeddings = model.encode(sentences, convert_to_tensor=True)
skill_embeddings = model.encode(top_skills, convert_to_tensor=True)
cosine_scores = util.cos_sim(skill_embeddings, sentence_embeddings)
found_skills = []
for idx, skill in enumerate(top_skills):
score = max(cosine_scores[idx])
if score > 0.4:
found_skills.append(skill)
missing_skills = [s for s in top_skills if s not in found_skills]
return found_skills, missing_skills
def suggest_jobs(found_skills):
matched_jobs = []
skill_set = set(found_skills)
scored_jobs = []
for title, required_skills in job_roles:
matches = skill_set & required_skills
score = len(matches) / len(required_skills) # proportion matched
if score > 0: # at least one skill matched
scored_jobs.append((title, score))
if scored_jobs:
scored_jobs.sort(key=lambda x: x[1], reverse=True)
matched_jobs = [title for title, _ in scored_jobs[:3]]
else:
matched_jobs = ["General Roles"]
return matched_jobs
def recommend_skills(found_skills, matched_jobs):
skill_set = set(found_skills)
if matched_jobs == ["General Roles"]:
return [s for s in top_skills if s not in skill_set][:5]
relevant_skills = set()
for job, required_skills in job_roles:
if job in matched_jobs:
relevant_skills |= required_skills
missing_in_domain = [s for s in relevant_skills if s not in skill_set]
if len(missing_in_domain) < 5:
others = [s for s in top_skills if s not in skill_set and s not in missing_in_domain]
missing_in_domain.extend(others[:5 - len(missing_in_domain)])
return missing_in_domain[:5]
def summarize_resume(found_skills):
if not found_skills:
return "No clear skills detected in resume."
return "This resume highlights skills in " + ", ".join(found_skills) + "."
def score_resume(found_skills):
score = int(len(found_skills) / len(top_skills) * 100)
return min(score, 100)
def save_report(text, skills, jobs, missing, summary, score):
report = f"""
--- Resume Analysis Report ---
Summary:
{summary}
Resume Text:
{text}
Detected Skills:
{skills}
Suggested Job Titles:
{jobs}
Recommended Skills to Learn:
{missing}
Resume Score: {score}/100
"""
tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode='w', encoding='utf-8')
tmp.write(report)
tmp.close()
return tmp.name
def text_to_speech(jobs):
tts = gTTS(f"Based on your resume, recommended job titles are: {jobs}")
tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
tts.save(tmp.name)
return tmp.name
def process_resume(file_obj):
filename = file_obj.name
ext = filename.split(".")[-1].lower()
if ext == "pdf":
resume_text = extract_text_from_pdf(filename)
elif ext == "txt":
resume_text = file_obj.read().decode("utf-8")
elif ext == "docx":
resume_text = extract_text_from_docx(filename)
else:
return "Unsupported file format", "", "", "", "", "", None, None
found_skills, _ = detect_skills(resume_text)
matched_jobs = suggest_jobs(found_skills)
recommended = recommend_skills(found_skills, matched_jobs)
summary = summarize_resume(found_skills)
skills_str = ", ".join(found_skills)
jobs_str = ", ".join(matched_jobs)
missing_str = ", ".join(recommended)
score = score_resume(found_skills)
report_path = save_report(resume_text, skills_str, jobs_str, missing_str, summary, score)
audio_path = text_to_speech(jobs_str)
return resume_text, summary, skills_str, jobs_str, missing_str, f"{score}/100", report_path, audio_path
# Build the UI
with gr.Blocks(theme="soft") as demo:
gr.Markdown("""
# 📄✨ Resume Analyzer & Job Matcher
Upload your **resume** and let AI analyze it for:
- 🧠**Summary of your profile**
- ✅ Detected **skills**
- 💼 Suggested **job titles**
- 🚀 Recommended **skills to learn**
- 🎯 **Resume score**
- 🔊 Audio feedback
- 📄 Downloadable report
Supported formats: `.pdf`, `.docx`, `.txt`
""")
with gr.Row():
with gr.Column():
file = gr.File(label="📤 Upload your resume here")
btn = gr.Button("🚀 Analyze Resume", elem_classes="analyze-btn")
with gr.Tabs():
with gr.Tab("📋 Resume Text"):
resume_text = gr.Textbox(label="Your Resume Text", lines=15, interactive=False)
with gr.Tab("🧠Summary"):
summary = gr.Textbox(label="Resume Summary", interactive=False)
with gr.Tab("🧰 Skills & Jobs"):
skills = gr.Textbox(label="Detected Skills", interactive=False)
jobs = gr.Textbox(label="Suggested Job Titles", interactive=False)
missing = gr.Textbox(label="Recommended Skills to Learn", interactive=False)
with gr.Tab("📊 Score"):
score = gr.Textbox(label="Resume Score", interactive=False)
with gr.Tab("📄 Download & 🔊 Audio"):
report = gr.File(label="📄 Download Analysis Report")
audio = gr.Audio(label="🔊 Job Titles Audio")
btn.click(
fn=process_resume,
inputs=file,
outputs=[
resume_text, summary, skills, jobs, missing, score, report, audio
]
)
if __name__ == "__main__":
demo.launch()