Spaces:
Sleeping
Sleeping
File size: 4,996 Bytes
7f21468 88dce1c 7f21468 7ad3944 88dce1c 7ad3944 7f21468 88dce1c 7f21468 7ad3944 88dce1c 7f21468 7ad3944 88dce1c 7ad3944 88dce1c 7ad3944 7f21468 7ad3944 7f21468 88dce1c 7f21468 88dce1c 7f21468 |
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 |
import streamlit as st
import fitz # PyMuPDF for PDF extraction
import pandas as pd
import torch
from sentence_transformers import SentenceTransformer
from model import JobRecommendationSystem
# ----------------- PAGE CONFIG (must be FIRST) -----------------
st.set_page_config(page_title="AI Job Recommender", page_icon="πΌ", layout="wide")
# ----------------- CACHE HEAVY STUFF -----------------
@st.cache_resource
def load_model():
"""Load and quantize the SentenceTransformer model once"""
try:
model = SentenceTransformer("./paraphrase-MiniLM-L6-v2", device="cpu") # local
except Exception:
model = SentenceTransformer("sentence-transformers/paraphrase-MiniLM-L6-v2", device="cpu") # fallback
return torch.quantization.quantize_dynamic(model, {torch.nn.Linear}, dtype=torch.qint8)
@st.cache_resource
def load_recommender():
"""Load recommender system once with cached embeddings"""
return JobRecommendationSystem("JobsFE.csv")
MODEL = load_model()
recommender = load_recommender()
# ----------------- STREAMLIT UI -----------------
st.markdown(
"""
<style>
.recommend-card {
padding: 20px;
border-radius: 15px;
background-color: #f9f9f9;
margin-bottom: 20px;
box-shadow: 0 4px 8px rgba(0,0,0,0.05);
}
.job-title {
font-size: 20px;
font-weight: 700;
color: #2c3e50;
}
.company-name {
font-size: 16px;
font-weight: 500;
color: #16a085;
}
.salary {
font-size: 15px;
font-weight: 500;
color: #e67e22;
}
</style>
""",
unsafe_allow_html=True
)
st.title("πΌ AI-Powered Job Recommendation System")
st.write("π Upload your resume as a **PDF file** and get tailored job recommendations with direct apply links.")
# ----------------- FILE UPLOADER -----------------
uploaded_file = st.file_uploader("Upload your resume (PDF only)", type=["pdf"], help="Only PDF resumes are supported.")
def extract_text_from_pdf(pdf_file):
"""Extract text from uploaded PDF resume"""
doc = fitz.open(stream=pdf_file.read(), filetype="pdf")
text = "\n".join([page.get_text("text") for page in doc])
return text.strip()
resume_text = ""
if uploaded_file:
with st.spinner("β³ Extracting text from your resume..."):
resume_text = extract_text_from_pdf(uploaded_file)
# ----------------- JOB RECOMMENDATIONS -----------------
if st.button("π Recommend Jobs"):
if resume_text:
with st.spinner("π€ Analyzing your resume and finding best matches..."):
job_results = recommender.recommend_jobs(resume_text, top_n=20)
st.success(f"β
Found {len(job_results)} job recommendations for you!")
for i, job in enumerate(job_results, start=1):
with st.container():
st.markdown('<div class="recommend-card">', unsafe_allow_html=True)
st.markdown(f"<div class='job-title'> {i}. {job.get('position', 'N/A')} </div>", unsafe_allow_html=True)
st.markdown(
f"<div class='company-name'>π’ {job.get('workplace', 'N/A')} ({job.get('formatted_work_type', 'N/A')})</div>",
unsafe_allow_html=True,
)
if job.get("salary_range") and "N/A" not in job.get("salary_range"):
st.markdown(f"<div class='salary'>π° {job['salary_range']}</div>", unsafe_allow_html=True)
if job.get("experience_level") and job.get("experience_level") != "N/A":
st.write(f"**π― Experience Level:** {job['experience_level']}")
if job.get("job_role_and_duties"):
st.write(f"**π Duties:** {job['job_role_and_duties']}")
if job.get("skills"):
st.write(f"**π Required Skills:** {job['skills']}")
if job.get("benefits"):
st.write(f"**π Benefits:** {job['benefits']}")
if job.get("location") and job.get("location").strip(", "):
st.write(f"**π Location:** {job['location']}")
if job.get("company_size") and job.get("company_size") != "N/A":
st.write(f"**π’ Company Size:** {job['company_size']}")
if job.get("employee_count") and job.get("employee_count") != "N/A":
st.write(f"**π₯ Employees:** {job['employee_count']}")
if job.get("company_website") and job.get("company_website") != "N/A":
st.markdown(f"[π Company Website]({job['company_website']})", unsafe_allow_html=True)
if job.get("apply_link") and job.get("apply_link") != "N/A":
st.markdown(f"[π Apply Here]({job['apply_link']})", unsafe_allow_html=True)
st.markdown('</div>', unsafe_allow_html=True)
else:
st.warning("β οΈ Please upload a valid PDF resume before proceeding.")
|