File size: 7,515 Bytes
8019603 3632434 8019603 e3566d2 8019603 d0dedea 8019603 d0dedea 8019603 d0dedea 8019603 5f52b42 8019603 5f52b42 e3566d2 5f52b42 d0dedea 8019603 d0dedea 8019603 e3566d2 8019603 d0dedea 5f52b42 d0dedea 5f52b42 d0dedea 5f52b42 d0dedea 5f52b42 d0dedea 8019603 5f52b42 e3566d2 d0dedea e3566d2 5f52b42 e3566d2 5f52b42 e3566d2 5f52b42 8019603 e3566d2 8019603 e3566d2 5f52b42 d0dedea 5f52b42 d0dedea b4c9df5 5f52b42 3632434 b4c9df5 3632434 b4c9df5 3632434 8019603 | 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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | 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("""
# <span style='color:#2c3e50'>πβ¨ Resume Analyzer & Job Matcher</span>
Upload your **resume** and let <span style='color:#1abc9c'>AI</span> 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()
|