Spaces:
Sleeping
Sleeping
File size: 5,534 Bytes
909d302 f373840 909d302 f373840 909d302 f373840 909d302 f373840 909d302 f373840 | 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 | import streamlit as st
import joblib
from textblob import TextBlob
import mammoth
import pdfplumber
import io
import re
import os
# --- 1. MODEL FUNCTION ---
def ekkok(text):
try:
words = TextBlob(str(text)).words
return [word.lemmatize() for word in words]
except:
return str(text).split()
# --- PAGE CONFIG ---
st.set_page_config(page_title="AI Resume Analyzer", layout="centered", page_icon="🎯")
# --- SECTOR KEYWORDS ---
SECTOR_KEYWORDS = {
"Hospitality & Management": ["hospitality", "restaurant", "hotel", "waiter", "bartender", "bar manager", "chef", "tourism"],
"Marketing / Advertising": ["marketing", "advertising", "social media", "branding", "seo", "store manager", "salesman"],
"Information Technology": ["software", "developer", "java", "python", "javascript", "cloud", "data science"],
"Finance & Accounting": ["finance", "accounting", "audit", "banking", "tax", "budget"],
"Human Resources": ["recruitment", "hr", "payroll", "onboarding", "talent acquisition"]
}
# --- FILE EXTRACTOR ---
def extract_text(uploaded_file):
try:
if uploaded_file.name.lower().endswith('.docx'):
return mammoth.extract_raw_text(io.BytesIO(uploaded_file.getvalue())).value
elif uploaded_file.name.lower().endswith('.pdf'):
full_text = ""
with pdfplumber.open(io.BytesIO(uploaded_file.getvalue())) as pdf:
for page in pdf.pages:
page_text = page.extract_text()
if page_text: full_text += page_text + "\n"
return full_text if full_text.strip() else "ERR_SCAN"
except: return None
# --- LOAD ASSETS ---
@st.cache_resource
def load_assets():
m_p, v_p = "best_model.pkl", "tfidf_vectorizer.pkl"
if os.path.exists(m_p) and os.path.exists(v_p):
try: return joblib.load(m_p), joblib.load(v_p)
except: return None, None
return None, None
model, vectorizer = load_assets()
# --- BILINGUAL TITLE (İNGİLİZCE & TÜRKÇE BAŞLIK) ---
st.markdown("""
<div style="text-align: center;">
<h1 style="color: #1E3A8A; margin-bottom: 0;">🎯 AI Resume Classifier / Akıllı CV Sınıflandırıcı</h1>
<p style="color: #666; font-size: 1.1rem; margin-top: 5px;">Automated Department Prediction System / Otomatik Bölüm Tahmin Sistemi</p>
</div>
""", unsafe_allow_html=True)
st.divider()
# --- INPUT SECTION ---
# 1. Metin Girişi
manual_input = st.text_area("✍️ Paste CV Text / CV Metnini Yapıştırın:", height=150, key="m_input")
# 2. Dosya Yükleme
uploaded_file = st.file_uploader("📂 Upload CV (PDF/DOCX) / Dosya Yükleyin:", type=['pdf', 'docx'], key="f_input")
# --- VALIDATION ---
final_cv_text = ""
if manual_input.strip() and uploaded_file:
st.error("⚠️ Please use ONLY ONE method! Delete text OR remove file. / Lütfen SADECE BİR yöntem kullanın! Metni silin VEYA dosyayı kaldırın.")
elif manual_input.strip():
final_cv_text = manual_input
elif uploaded_file:
with st.spinner('Reading...'):
res = extract_text(uploaded_file)
if res == "ERR_SCAN":
st.error("❌ This PDF is an image. Please paste text instead. / Bu PDF resimden oluşuyor, lütfen metni kopyalayıp kutuya yapıştırın.")
elif res:
final_cv_text = res
st.success(f"✅ {uploaded_file.name} ready!")
st.divider()
# --- ANALYSIS BUTTON ---
if st.button("🚀 START ANALYSIS / ANALİZİ BAŞLAT", use_container_width=True):
if not final_cv_text or len(final_cv_text.strip()) < 10:
st.warning("⚠️ Please provide CV content! / Lütfen CV içeriği sağlayın!")
else:
with st.spinner('Processing...'):
# Email Identity
email_id = "NOT FOUND"
match = re.search(r'([a-zA-Z0-9_.+-]+)@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+', final_cv_text)
if match: email_id = match.group(1).upper()
# Prediction
low_txt = final_cv_text.lower()
scores = {s: sum(1 for k in kw if k in low_txt) for s, kw in SECTOR_KEYWORDS.items()}
prediction = max(scores, key=scores.get)
if scores[prediction] == 0 and model:
try: prediction = model.predict(vectorizer.transform([final_cv_text]))[0]
except: prediction = "Unclassified"
st.balloons()
st.success("### Results / Sonuçlar")
c1, c2 = st.columns(2)
c1.metric("Email Identity / E-posta", email_id)
c2.metric("Department / Bölüm", prediction)
# --- FOOTER ---
st.markdown("<br><br><br><hr>", unsafe_allow_html=True)
footer_html = """
<div style="display: flex; justify-content: space-between; align-items: center; font-family: sans-serif;">
<div style="text-align: left;">
<h4 style="margin:0; color: #1E3A8A;">Developed by Data Science Dept.</h4>
<p style="margin:0; font-size: 0.8rem; color: #666;">Advanced HR Analytics Solutions</p>
</div>
<div style="text-align: right;">
<h4 style="margin:0; color: #1E3A8A;">Veri Bilimi Departmanı</h4>
<p style="margin:0; font-size: 0.8rem; color: #666;">Gelişmiş İK Analitik Çözümleri</p>
</div>
</div>
<div style="text-align: center; margin-top: 15px; border-top: 1px solid #eee; padding-top: 10px;">
<span style="color: #444; font-size: 0.9rem;">Developer / Geliştirici: <b>EsmaTuğba MERGEN</b> | <b>v37.0</b></span>
</div>
"""
st.markdown(footer_html, unsafe_allow_html=True) |