import streamlit as st import pdfplumber import io import spacy from transformers import pipeline import subprocess import sys st.set_page_config( page_title="Resume Screener & Skill Extractor", page_icon="📄", layout="wide" ) # Download spaCy model if not already downloaded @st.cache_resource def download_spacy_model(): try: nlp = spacy.load("en_core_web_sm") except OSError: subprocess.check_call([sys.executable, "-m", "spacy", "download", "en_core_web_sm"]) nlp = spacy.load("en_core_web_sm") return nlp # Load the NLP models @st.cache_resource def load_models(): summarizer = pipeline("summarization", model="facebook/bart-large-cnn") nlp = download_spacy_model() return summarizer, nlp # Initialize models summarizer, nlp = load_models() # Job descriptions and required skills job_descriptions = { "Software Engineer": { "skills": ["python", "java", "javascript", "sql", "algorithms", "data structures", "git", "cloud", "web development", "software development", "coding"], "description": "Looking for software engineers with strong programming skills and experience in software development." }, "Interaction Designer": { "skills": ["ui", "ux", "user research", "wireframing", "prototyping", "figma", "sketch", "adobe", "design thinking", "interaction design"], "description": "Seeking interaction designers with expertise in user experience and interface design." }, "Data Scientist": { "skills": ["python", "r", "statistics", "machine learning", "data analysis", "sql", "tensorflow", "pytorch", "pandas", "numpy"], "description": "Looking for data scientists with strong analytical and machine learning skills." } } def extract_text_from_pdf(pdf_file): text = "" with pdfplumber.open(pdf_file) as pdf: for page in pdf.pages: text += page.extract_text() or "" return text def analyze_resume(text, job_title): # Extract relevant skills doc = nlp(text.lower()) found_skills = [] required_skills = job_descriptions[job_title]["skills"] for skill in required_skills: if skill in text.lower(): found_skills.append(skill) # Generate summary chunks = [text[i:i + 1000] for i in range(0, len(text), 1000)] summaries = [] for chunk in chunks[:3]: # Process first 3000 characters to avoid token limits summary = summarizer(chunk, max_length=150, min_length=50, do_sample=False)[0]["summary_text"] summaries.append(summary) return found_skills, " ".join(summaries) # Streamlit UI st.title("📄 Resume Screener & Skill Extractor") # Add description st.markdown(""" This app helps recruiters analyze resumes by: - Extracting relevant skills for specific job positions - Generating a concise summary of the candidate's background - Identifying skill gaps for the selected role """) # Create two columns col1, col2 = st.columns([2, 1]) with col1: # File upload uploaded_file = st.file_uploader("Upload Resume (PDF)", type=["pdf"]) with col2: # Job selection job_title = st.selectbox("Select Job Position", list(job_descriptions.keys())) # Show job description if job_title: st.info(f"**Required Skills:**\n" + "\n".join([f"- {skill.title()}" for skill in job_descriptions[job_title]["skills"]])) if uploaded_file and job_title: try: # Show spinner while processing with st.spinner("Analyzing resume..."): # Extract text from PDF text = extract_text_from_pdf(uploaded_file) # Analyze resume found_skills, summary = analyze_resume(text, job_title) # Display results in tabs tab1, tab2, tab3 = st.tabs(["📊 Skills Match", "📝 Resume Summary", "🎯 Skills Gap"]) with tab1: # Display matched skills st.subheader("🎯 Matched Skills") if found_skills: for skill in found_skills: st.success(f"✅ {skill.title()}") # Calculate match percentage match_percentage = len(found_skills) / len(job_descriptions[job_title]["skills"]) * 100 st.metric("Skills Match", f"{match_percentage:.1f}%") else: st.warning("No direct skill matches found.") with tab2: # Display resume summary st.subheader("📝 Resume Summary") st.write(summary) with tab3: # Display missing skills st.subheader("📌 Skills to Develop") missing_skills = [skill for skill in job_descriptions[job_title]["skills"] if skill not in found_skills] if missing_skills: for skill in missing_skills: st.warning(f"➖ {skill.title()}") else: st.success("Great! The candidate has all the required skills!") except Exception as e: st.error(f"An error occurred while processing the resume: {str(e)}") # Add footer st.markdown("---") st.markdown("Made with ❤️ using Streamlit and Hugging Face")