import streamlit as st
import pandas as pd
import pickle
import os
import io
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib import colors
from reportlab.lib.units import inch
from datetime import datetime
from sentence_transformers import SentenceTransformer, util
import numpy as np
# FILE BASED PERSISTENT STORAGE
USERS_FILE = "skillsense_users.pkl"
HISTORY_FILE = "skillsense_history.pkl"
# Load/Save functions
def load_users():
if os.path.exists(USERS_FILE):
with open(USERS_FILE, 'rb') as f:
return pickle.load(f)
return {
"user@gmail.com": {"password": "user123", "role": "user"},
"hr@company.com": {"password": "hr456", "role": "user"}
}
def save_users(users):
with open(USERS_FILE, 'wb') as f:
pickle.dump(users, f)
def load_history():
if os.path.exists(HISTORY_FILE):
with open(HISTORY_FILE, 'rb') as f:
return pickle.load(f)
return []
def save_history(history):
with open(HISTORY_FILE, 'wb') as f:
pickle.dump(history, f)
# Load data
users_db = load_users()
history_db = load_history()
ADMIN_AUTH_CODE = "SSAI-ADMIN-2026-X7K9"
def generate_interview_questions(detected_skills, level):
"""Generate targeted interview questions based on detected skills"""
questions = []
for skill in detected_skills[:5]:
questions.extend([
f"Can you describe your hands-on experience with {skill}?",
f"What was the most challenging project you worked on using {skill}?",
f"How do you approach debugging issues in {skill} projects?"
])
return questions[:8]
# AI FUNCTION (HUGGINGFACE)
@st.cache_resource
def load_ai_model():
return SentenceTransformer('all-MiniLM-L6-v2')
def ai_resume_analysis(resume_text, job_role="Software Developer"):
try:
model = load_ai_model()
# Extract skills from resume
resume_lower = resume_text.lower()
detected_skills = []
skill_list = ["python", "react", "java", "sql", "aws", "docker", "angular", "node", "javascript", "mysql"]
for skill in skill_list:
if skill in resume_lower:
detected_skills.append(skill.title())
# Job required skills
job_skills = ["python", "react", "sql", "aws", "docker", "node"]
# AI Similarity calculation
if detected_skills:
resume_text = ", ".join(detected_skills)
job_text = ", ".join(job_skills)
resume_emb = model.encode([resume_text])
job_emb = model.encode([job_text])
similarity = util.cos_sim(resume_emb, job_emb).item() * 100
else:
similarity = 20
# AI Recommendation
score = min(95, max(25, int(similarity)))
recommendation = "HIRE" if score > 75 else "INTERVIEW" if score > 50 else "REVIEW"
# Generate interview questions
interview_questions = generate_interview_questions(detected_skills, "Mid")
return {
"ai_score": score,
"recommendation": recommendation,
"detected_skills": detected_skills[:8],
"job_fit": f"{score}% match for {job_role}",
"strengths": detected_skills[:3],
"confidence": "High" if score > 70 else "Medium",
"interview_questions": interview_questions
}
except:
return {
"ai_score": 50,
"recommendation": "REVIEW",
"detected_skills": [],
"job_fit": "AI temporarily unavailable",
"strengths": [],
"confidence": "Low",
"interview_questions": []
}
def generate_hiring_pdf(results):
buffer = io.BytesIO()
doc = SimpleDocTemplate(buffer, pagesize=A4, rightMargin=36, leftMargin=36, topMargin=36, bottomMargin=36)
styles = getSampleStyleSheet()
story = []
# HEADER
story.append(Paragraph("SkillSense AI - Resume Analysis Report", styles['Title']))
story.append(Paragraph(f"Generated: {datetime.now().strftime('%B %d, %Y %I:%M %p')}", styles['Normal']))
story.append(Spacer(1, 20))
# CANDIDATE INFO TABLE
candidate_data = [["Candidate Name:", results['candidate']],
["Position Level:", results.get('level', 'N/A')],
["Analysis Date:", datetime.now().strftime('%Y-%m-%d')]]
candidate_table = Table(candidate_data, colWidths=[2*inch, 3.5*inch])
candidate_table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, -1), colors.lightblue),
('FONTNAME', (0, 0), (0, 0), 'Helvetica-Bold'),
('ALIGN', (0, 0), (-1, -1), 'LEFT'),
('GRID', (0, 0), (-1, -1), 1, colors.black),
('FONTSIZE', (0, 0), (-1, -1), 12)
]))
story.extend([candidate_table, Spacer(1, 20)])
# MAIN DECISION TABLE
ai_score = results.get('ai_score', 0)
decision_data = [
["Metric", "Status", "Score"],
["Hiring Decision", results.get('recommendation', 'N/A'), f"{ai_score}%"],
["Skill Match", f"{len(results.get('detected_skills', []))} Skills"],
["AI Recommendation", results.get('job_fit', 'N/A')]
]
decision_table = Table(decision_data, colWidths=[1.8*inch, 2.2*inch, 1.8*inch])
decision_table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.darkgreen),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, 0), 14),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('BACKGROUND', (0, 1), (-1, -1), colors.lightgreen if ai_score > 70 else colors.lightcoral),
('GRID', (0, 0), (-1, -1), 2, colors.black),
('FONTSIZE', (0, 1), (-1, -1), 12)
]))
story.extend([Paragraph("AI-ENHANCED HIRING DECISION", styles['Heading1']),
Spacer(1, 12), decision_table, Spacer(1, 20)])
# SKILLS GRID
all_skills = results.get('detected_skills', [])
story.append(Paragraph("DETECTED TECHNICAL SKILLS", styles['Heading2']))
if all_skills:
skills_data = []
for i in range(0, len(all_skills), 2):
row = [all_skills[i]]
if i+1 < len(all_skills):
row.append(all_skills[i+1])
skills_data.append(row)
skills_table = Table(skills_data, colWidths=[3*inch, 3*inch])
skills_table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, -1), colors.ivory),
('FONTNAME', (0, 0), (-1, -1), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, -1), 11),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('GRID', (0, 0), (-1, -1), 1, colors.darkgreen),
('VALIGN', (0, 0), (-1, -1), 'MIDDLE')
]))
story.append(skills_table)
story.append(Spacer(1, 20))
# INTERVIEW QUESTIONS
questions = results.get('interview_questions', [])
if questions:
story.append(Paragraph("INTERVIEW QUESTIONS", styles['Heading2']))
for i, question in enumerate(questions[:6], 1):
story.append(Paragraph(f"{i}. {question}", styles['Normal']))
story.append(Spacer(1, 8))
# ANALYSIS
story.append(Paragraph("DETAILED AI ANALYSIS", styles['Heading2']))
analysis_para = Paragraph(f"""
AI Score: {ai_score}% semantic match using HuggingFace Transformers
Skills Found: {len(all_skills)} technical skills detected
Position Fit: {results.get('level', 'N/A')} level position
Recommendation: {results.get('recommendation', 'N/A')}
Powered by: SkillSense AI + HuggingFace AI
""", styles['Normal'])
story.append(analysis_para)
# FOOTER
story.append(Spacer(1, 20))
footer_data = [["Generated by:", "SkillSense AI Enterprise + HuggingFace AI"],
["Report ID:", f"SSAI-{datetime.now().strftime('%Y%m%d%H%M')}"]]
footer_table = Table(footer_data, colWidths=[2*inch, 3.5*inch])
footer_table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, -1), colors.lightgrey),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('GRID', (0, 0), (-1, -1), 1, colors.black)
]))
story.append(footer_table)
doc.build(story)
buffer.seek(0)
return buffer
# SESSION STATE
if 'logged_in' not in st.session_state:
st.session_state.logged_in = False
if 'current_user' not in st.session_state:
st.session_state.current_user = None
if 'user_role' not in st.session_state:
st.session_state.user_role = None
if 'results' not in st.session_state:
st.session_state.results = None
st.set_page_config(page_title="SkillSense AI", layout="wide")
# MAIN APP
if not st.session_state.logged_in:
st.title("SkillSense AI")
st.markdown("Professional Resume Analysis Platform")
tab1, tab2 = st.tabs(["Login", "Create Account"])
# TAB 1: LOGIN
with tab1:
st.markdown("Login with your saved account")
with st.form("login_form"):
email = st.text_input("Email")
password = st.text_input("Password", type="password")
if st.form_submit_button("LOGIN", type="primary"):
if email in users_db and users_db[email]["password"] == password:
st.session_state.logged_in = True
st.session_state.current_user = email
st.session_state.user_role = users_db[email]["role"]
st.success(f"Welcome back {email}!")
st.rerun()
else:
st.error("Invalid credentials!")
st.info("Default: user@gmail.com / user123")
# TAB 2: CREATE ACCOUNT
with tab2:
st.markdown("Create New Account (Saved Forever)")
with st.form("create_account"):
email = st.text_input("New Email")
password = st.text_input("New Password", type="password")
col1, col2 = st.columns(2)
with col1:
if st.form_submit_button("Create USER Account", type="secondary"):
if email and password:
if email not in users_db:
users_db[email] = {"password": password, "role": "user"}
save_users(users_db)
st.success(f"User account SAVED: {email}")
st.info("Login anytime with same details!")
else:
st.error("Email already exists!")
else:
st.error("Fill all fields!")
with col2:
admin_code = st.text_input("Admin Auth Code", type="password", placeholder="")
if st.form_submit_button("Create ADMIN Account", type="primary"):
if email and password:
if email not in users_db:
if admin_code == ADMIN_AUTH_CODE:
users_db[email] = {"password": password, "role": "admin"}
save_users(users_db)
st.success(f"Admin account SAVED: {email}")
else:
st.error("Wrong admin code!")
else:
st.error("Email already exists!")
else:
st.error("Fill all fields!")
else:
# DASHBOARD
st.sidebar.markdown("SkillSense AI")
st.sidebar.markdown(f"User: {st.session_state.current_user}")
st.sidebar.markdown(f"Role: {st.session_state.user_role.upper()}")
if st.sidebar.button("Logout"):
st.session_state.logged_in = False
st.session_state.current_user = None
st.session_state.user_role = None
st.session_state.results = None
st.rerun()
# Navigation
if st.session_state.user_role == "admin":
page = st.sidebar.radio("Dashboard", ["Resume Analyzer", "History", "Admin"])
else:
page = st.sidebar.radio("Dashboard", ["Resume Analyzer"])
if page == "Resume Analyzer":
st.title("SkillSense AI - Resume Analyzer")
col1, col2 = st.columns([2,1])
with col1:
resume_text = st.text_area("Paste Resume", height=300)
with col2:
name = st.text_input("Candidate Name")
level = st.select_slider("Level", ["Junior", "Mid", "Senior"])
# AI ANALYSIS BUTTON
if st.button("AI ANALYSIS", type="primary", use_container_width=True):
with st.spinner("AI analyzing with HuggingFace Transformers..."):
ai_result = ai_resume_analysis(resume_text)
ai_result["candidate"] = name or "Candidate"
ai_result["level"] = level
st.session_state.results = ai_result
history_db.append(ai_result)
save_history(history_db)
st.success(f"AI Score: {ai_result['ai_score']}%")
# DISPLAY RESULTS
if st.session_state.get('results'):
r = st.session_state.results
ai_score = r.get('ai_score', 0)
if ai_score > 75:
st.markdown(f"""