Spaces:
Runtime error
Runtime error
File size: 8,668 Bytes
0f1b38d b5caa7d 0f1b38d |
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 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
import streamlit as st
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import re
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
import string
import json
import os
from utils import load_job_data, preprocess_text, get_top_skills, get_job_recommendations
# Download NLTK resources
try:
nltk.download('punkt')
nltk.download('stopwords')
except:
pass # In case downloads fail, continue with what's available
# Page configuration
st.set_page_config(
page_title="Job Title Recommender",
page_icon="πΌ",
layout="wide"
)
# Custom CSS
st.markdown("""
<style>
.main-header {
font-size: 2.5rem;
font-weight: bold;
color: #0A66C2;
text-align: center;
margin-bottom: 1rem;
}
.sub-header {
font-size: 1.2rem;
color: #666;
text-align: center;
margin-bottom: 2rem;
}
.footer {
text-align: center;
margin-top: 2rem;
color: #666;
font-size: 0.9rem;
}
.recommendation-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 1rem;
margin-bottom: 1rem;
background-color: #f9f9f9;
}
.skill-tag {
display: inline-block;
background-color: #0A66C2;
color: white;
padding: 0.3rem 0.8rem;
border-radius: 15px;
margin: 0.2rem;
font-size: 0.9rem;
}
</style>
""", unsafe_allow_html=True)
# Initialize session state
if 'job_data' not in st.session_state:
st.session_state.job_data = load_job_data()
if 'vectorizer' not in st.session_state:
st.session_state.vectorizer = None
if 'job_vectors' not in st.session_state:
st.session_state.job_vectors = None
# Header
st.markdown('<div class="main-header">πΌ Job Title Recommender</div>', unsafe_allow_html=True)
st.markdown('<div class="sub-header">Find the perfect job titles based on your LinkedIn profile or resume</div>', unsafe_allow_html=True)
# Built with anycoder
st.markdown('<div style="text-align: center; margin-bottom: 1rem;">Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a></div>', unsafe_allow_html=True)
# Main content
col1, col2 = st.columns([1, 1])
with col1:
st.header("π Input Your Profile")
# Input method selection
input_method = st.radio(
"Choose input method:",
["Text Input", "File Upload"],
horizontal=True
)
if input_method == "Text Input":
profile_text = st.text_area(
"Paste your LinkedIn profile or resume text here:",
height=300,
placeholder="Include your work experience, skills, education, and any other relevant information..."
)
else:
uploaded_file = st.file_uploader(
"Upload your resume (PDF or TXT):",
type=["pdf", "txt"],
help="Upload your resume file to analyze"
)
if uploaded_file:
try:
if uploaded_file.type == "application/pdf":
# For PDF files (would need additional libraries)
st.warning("PDF parsing requires additional libraries. Please use text input or upload a .txt file.")
profile_text = ""
else:
# For text files
profile_text = uploaded_file.read().decode("utf-8")
st.success("File uploaded successfully!")
except Exception as e:
st.error(f"Error reading file: {e}")
profile_text = ""
# Skills input
st.subheader("Key Skills")
skills_input = st.text_input(
"Enter your key skills (comma separated):",
placeholder="e.g., Python, Machine Learning, Project Management"
)
# Experience level
experience_level = st.select_slider(
"Years of Experience:",
options=["0-2 years", "3-5 years", "6-10 years", "10+ years"],
value="3-5 years"
)
# Education level
education_level = st.selectbox(
"Highest Education Level:",
["High School", "Associate Degree", "Bachelor's Degree", "Master's Degree", "PhD"]
)
# Analyze button
analyze_button = st.button("π Analyze & Get Recommendations", type="primary")
with col2:
st.header("π― Your Recommendations")
if analyze_button and profile_text:
with st.spinner("Analyzing your profile..."):
try:
# Preprocess the input text
processed_text = preprocess_text(profile_text)
# Extract skills from input
input_skills = [skill.strip() for skill in skills_input.split(",")] if skills_input else []
extracted_skills = get_top_skills(processed_text, top_n=10)
# Combine all skills
all_skills = list(set(input_skills + extracted_skills))
# Create user profile vector
if st.session_state.vectorizer is None or st.session_state.job_vectors is None:
# Initialize vectorizer and job vectors if not already done
job_descriptions = st.session_state.job_data['description'].tolist()
st.session_state.vectorizer = TfidfVectorizer(stop_words='english', max_features=5000)
st.session_state.job_vectors = st.session_state.vectorizer.fit_transform(job_descriptions)
# Transform user profile
user_vector = st.session_state.vectorizer.transform([processed_text])
# Get recommendations
recommendations = get_job_recommendations(
user_vector,
st.session_state.job_vectors,
st.session_state.job_data,
all_skills,
experience_level,
education_level,
top_n=5
)
if recommendations.empty:
st.warning("No suitable job titles found. Try adding more details to your profile.")
else:
st.success(f"Found {len(recommendations)} suitable job titles for you!")
for idx, row in recommendations.iterrows():
with st.expander(f"π {row['job_title']} (Match: {row['match_score']:.1%})"):
st.markdown(f"**Industry:** {row['industry']}")
st.markdown(f"**Experience Level:** {row['experience_level']}")
st.markdown(f"**Education Requirement:** {row['education_requirement']}")
# Display skills
st.markdown("**Key Skills:**")
job_skills = [skill.strip() for skill in row['required_skills'].split(",")]
for skill in job_skills[:5]: # Show top 5 skills
st.markdown(f'<span class="skill-tag">{skill}</span>', unsafe_allow_html=True)
st.markdown(f"**Average Salary:** {row['avg_salary']}")
if st.button(f"Learn more about {row['job_title']}", key=f"learn_{idx}"):
st.info(f"This would typically link to more information about the {row['job_title']} role.")
# Show skills analysis
st.subheader("Your Skills Analysis")
if all_skills:
st.markdown("**Detected Skills:**")
for skill in all_skills[:10]: # Show top 10 skills
st.markdown(f'<span class="skill-tag">{skill}</span>', unsafe_allow_html=True)
else:
st.info("No specific skills detected. Consider adding more details to your profile.")
except Exception as e:
st.error(f"An error occurred during analysis: {e}")
elif analyze_button and not profile_text:
st.warning("Please enter your profile information or upload a file.")
else:
st.info("Enter your LinkedIn profile or resume information and click 'Analyze' to get job recommendations.")
# Footer
st.markdown("""
<div class="footer">
<p>This tool uses natural language processing to match your skills and experience with suitable job titles.</p>
<p>For best results, provide detailed information about your work experience, skills, and education.</p>
</div>
""", unsafe_allow_html=True) |