import streamlit as st import pickle import re import docx import PyPDF2 from sklearn.metrics.pairwise import cosine_similarity # 1. CONFIG st.set_page_config( page_title="AI Resume Screening", layout="wide", initial_sidebar_state="collapsed" ) # Custom CSS for styling st.markdown(""" """, unsafe_allow_html=True) # 2. LOAD RESOURCES @st.cache_resource def load_resources(): try: clf = pickle.load(open('clf.pkl', 'rb')) tfidf = pickle.load(open('tfidf.pkl', 'rb')) le = pickle.load(open('encoder.pkl', 'rb')) ats = pickle.load(open('ats_scorer.pkl', 'rb')) prototypes = pickle.load(open('prototypes.pkl', 'rb')) return clf, tfidf, le, ats, prototypes except FileNotFoundError: return None, None, None, None, None clf, tfidf, le, ats_model, prototypes = load_resources() # 3. UTILS def clean_text(txt): txt = re.sub(r'http\S+\s', ' ', txt) txt = re.sub(r'[^\w\s]', ' ', txt) return txt.lower() def extract_text(file): try: if file.name.endswith('.pdf'): reader = PyPDF2.PdfReader(file) return " ".join([page.extract_text() for page in reader.pages]) elif file.name.endswith('.docx'): doc = docx.Document(file) return " ".join([p.text for p in doc.paragraphs]) elif file.name.endswith('.txt'): return file.read().decode('utf-8') except: return "" def calculate_scores(text, category): if category not in prototypes: return 0, 0, 0 master_profile = prototypes[category] cleaned_resume = clean_text(text) # Cosine Similarity vecs = tfidf.transform([cleaned_resume, master_profile]) cosine_sim = cosine_similarity(vecs[0], vecs[1])[0][0] # Keyword Match res_tokens = set(cleaned_resume.split()) mp_tokens = set(master_profile.split()) keyword_match = len(res_tokens.intersection(mp_tokens)) / len(mp_tokens) if mp_tokens else 0 # AI Prediction try: ml_score = ats_model.predict([[cosine_sim, keyword_match]])[0] except: ml_score = 0 # Fallback Logic if ml_score < 10: final_score = cosine_sim * 100 else: final_score = ml_score if final_score < 1: final_score *= 100 return round(final_score, 1), round(cosine_sim*100, 1), round(keyword_match*100, 1) # 4. MAIN APP def main(): # Header st.markdown("
Powered by Machine Learning & Natural Language Processing
", unsafe_allow_html=True) if not clf: st.error("⚠️ Models missing! Run `train_model.py` then `train_ats_model.py`.") st.stop() # Upload section st.markdown("