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)