Spaces:
Sleeping
Sleeping
File size: 6,248 Bytes
200bbd8 db51f41 f1cc55c 385da16 db51f41 f1cc55c db51f41 f1cc55c db51f41 f1cc55c db51f41 f1cc55c db51f41 f1cc55c db51f41 f1cc55c db51f41 ceb65f9 db51f41 f1cc55c db51f41 f1cc55c 385da16 f1cc55c 385da16 f1cc55c 385da16 f1cc55c 385da16 f1cc55c 385da16 f1cc55c 385da16 f1cc55c 385da16 f1cc55c 385da16 f1cc55c 385da16 f1cc55c 385da16 f1cc55c 385da16 f1cc55c ceb65f9 | 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 | import streamlit as st
from transformers import AutoTokenizer, AutoModel
import torch
import spacy
import numpy as np
st.set_page_config(
page_title="ATS Resume Optimizer",
page_icon="π",
layout="wide",
initial_sidebar_state="expanded"
)
TEST_DATA = {
"Data Scientist (Senior)": {
"resume": "Led a data science team for 5 years. Developed scalable ETL pipelines using Python, SQL, and TensorFlow. Successfully reduced model latency by 20%.",
"job_desc": "Seeking a Senior Data Scientist who will spearhead complex data pipelines. Must be proficient in Python, SQL, and have experience with TensorFlow. Strong project management skills required."
},
"Frontend Developer": {
"resume": "Built responsive web applications using React, JavaScript, and CSS. Implemented UI designs and optimized performance. Experienced in Git workflows and REST APIs.",
"job_desc": "Looking for a Frontend Developer skilled in React, JavaScript, CSS, and web performance optimization. Knowledge of REST APIs and Git required."
},
"Project Manager": {
"resume": "Managed multiple projects across software development teams. Skilled in Agile methodologies, stakeholder management, and risk assessment. Led teams to deliver projects on time.",
"job_desc": "Hiring a Project Manager with experience in Agile frameworks, team coordination, and risk management. Must ensure timely delivery and quality control."
},
"Marketing Specialist": {
"resume": "Executed digital marketing campaigns across social media and email. Analyzed performance metrics and improved ROI by 25%. Skilled in SEO, SEM, and content creation.",
"job_desc": "Seeking a Marketing Specialist to manage digital campaigns, analyze KPIs, and optimize marketing ROI. SEO, SEM, and content creation skills are essential."
},
"Machine Learning Engineer": {
"resume": "Developed ML models for predictive analytics using Python, PyTorch, and scikit-learn. Implemented end-to-end pipelines and deployed models in production.",
"job_desc": "Looking for a Machine Learning Engineer experienced in Python, PyTorch, scikit-learn, and model deployment. Must be able to create production-ready ML pipelines."
}
}
with st.sidebar:
st.title("π ATS Resume Optimizer")
st.markdown("Select a test dataset to quickly populate resume and job description fields:")
test_choice = st.selectbox("Choose Test Data", ["Custom"] + list(TEST_DATA.keys()))
if test_choice != "Custom":
resume_input_default = TEST_DATA[test_choice]["resume"]
job_desc_input_default = TEST_DATA[test_choice]["job_desc"]
else:
resume_input_default = ""
job_desc_input_default = ""
st.markdown("---")
st.caption("Built with Streamlit + MiniLM + spaCy")
@st.cache_resource
def load_models():
"""Loads lightweight MiniLM and spaCy models compatible with Hugging Face Spaces."""
model_name = "sentence-transformers/all-MiniLM-L6-v2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name, trust_remote_code=True)
try:
nlp = spacy.load("en_core_web_sm")
except OSError:
st.error("spaCy model 'en_core_web_sm' not found.")
raise
return tokenizer, model, nlp
tokenizer, model, nlp = load_models()
def embed(text):
inputs = tokenizer(text, return_tensors="pt", truncation=True)
with torch.no_grad():
output = model(**inputs)
embedding = output.last_hidden_state.mean(dim=1)
return embedding
def calculate_ats_match(resume_text: str, job_desc_text: str) -> tuple[float, list]:
emb_resume = embed(resume_text)
emb_job = embed(job_desc_text)
cosine_score = torch.nn.functional.cosine_similarity(emb_resume, emb_job).cpu().item()
ats_score = round(float(cosine_score) * 100, 2)
job_doc = nlp(job_desc_text.lower())
resume_doc = nlp(resume_text.lower())
job_keywords = {token.text for token in job_doc
if token.pos_ in ["NOUN", "PROPN", "VERB"] and not token.is_stop and len(token.text) > 2}
resume_keywords = {token.text for token in resume_doc
if token.pos_ in ["NOUN", "PROPN", "VERB"] and not token.is_stop and len(token.text) > 2}
missing_keywords = list(job_keywords - resume_keywords)
return ats_score, missing_keywords
st.markdown("## π Maximize Your ATS Compatibility")
st.markdown("Paste your resume and job description to get a semantic match score and optimization suggestions.")
col1, col2 = st.columns(2)
with col1:
resume_input = st.text_area(
"π Resume Text",
height=350,
placeholder="Paste your resume here...",
value=resume_input_default
)
with col2:
job_desc_input = st.text_area(
"πΌ Job Description",
height=350,
placeholder="Paste the job description here...",
value=job_desc_input_default
)
st.markdown("---")
if st.button("π Analyze ATS Match Score"):
if resume_input.strip() and job_desc_input.strip():
with st.spinner("Calculating semantic similarity and extracting keywords..."):
score, missing = calculate_ats_match(resume_input, job_desc_input)
st.metric(label="ATS Match Score", value=f"{score}%")
if score > 75:
feedback = "π― HIGH MATCH. Ready to submit!"
color = "green"
elif score > 50:
feedback = "β οΈ MEDIUM MATCH. Review keyword suggestions."
color = "orange"
else:
feedback = "β LOW MATCH. Major revision required."
color = "red"
st.markdown(f"### Optimization Feedback: <span style='color:{color}'>{feedback}</span>", unsafe_allow_html=True)
st.markdown("### π Missing High-Value Keywords")
if missing:
st.info(f"Consider adding these concepts: **{', '.join(missing[:15])}**")
else:
st.success("Your resume covers all high-value concepts. Great job! π")
else:
st.warning("Please paste text into both the Resume and Job Description boxes.") |