OC_P2_frontend / src /streamlit_app.py
KLEB38's picture
fix : errors 500
c76e8db
import streamlit as st
import requests
API_URL = "https://kleb38-oc-p5.hf.space"
st.set_page_config(page_title="FUTURISYS — HR Prediction", page_icon="👥", layout="wide")
st.title("👥 FUTURISYS — HR Departure Prediction")
tab2, tab1 = st.tabs(["🔍 Search by ID", "📝 Manual Prediction"])
# ─── Common functions ─────────────────────────────────────────────────────────
def afficher_resultat(data):
prediction = data["statut_employe"]
score = data["probability_score"]
facteurs = data["top_5_factors"]
if "HIGH" in prediction:
st.error(f"🚨 {prediction}")
else:
st.success(f"✅ {prediction}")
st.metric("Probability score", f"{score * 100:.1f}%")
st.markdown(f"*Strategic threshold: {data['model_threshold']}{data['note']}*")
st.subheader("Top 5 SHAP factors")
col_rank, col_name, col_interp, col_val = st.columns([0.5, 2, 3.5, 1.5])
col_rank.markdown("**#**")
col_name.markdown("**Feature**")
col_interp.markdown("**Interpretation**")
col_val.markdown("**Value**")
st.divider()
for rang, (facteur, details) in enumerate(facteurs.items()):
interpretation = details["interpretation"]
valeur = details["feature_value"]
decreases = "decreases" in interpretation.lower()
color = "#00c853" if decreases else "#d50000"
arrow = "↓" if decreases else "↑"
col_rank, col_name, col_interp, col_val = st.columns([0.5, 2, 3.5, 1.5])
col_rank.markdown(f"**{rang + 1}**")
col_name.markdown(f"`{facteur}`")
col_interp.markdown(f'<span style="color:{color}; font-weight:600">{arrow} {interpretation}</span>', unsafe_allow_html=True)
col_val.markdown(f"`{valeur}`")
# ─── Tab 1 : Manual form ──────────────────────────────────────────────────────
with tab1:
st.header("Enter employee data")
col1, col2, col3 = st.columns(3)
with col1:
st.subheader("Personal information")
genre = st.selectbox("Genre", ["M", "F"])
age = st.number_input("Âge", value=35)
statut_marital = st.selectbox("Statut marital", ["Célibataire", "Marié(e)", "Divorcé(e)"])
niveau_education = st.number_input("Niveau d'éducation", min_value=1, max_value=5, value=3)
domaine_etude = st.selectbox("Domaine d'étude", [
"Ressources Humaines", "Marketing", "Infra & Cloud", "Transformation Digitale", "Entrepreunariat"
])
ayant_enfants = st.selectbox("Ayant des enfants", ["Oui", "Non"])
distance_domicile = st.number_input("Distance domicile-travail (km)", min_value=1, value=10)
frequence_deplacement = st.selectbox("Fréquence de déplacement", ["Aucun", "Occasionnel", "Frequent"])
with col2:
st.subheader("Position and experience")
departement = st.selectbox("Département", ["Commercial", "Consulting", "Ressources Humaines"])
poste = st.selectbox("Poste", [
"Cadre Commercial", "Assistant de Direction", "Consultant",
"Tech Lead", "Manager", "Senior Manager",
"Représentant Commercial", "Directeur Technique", "Ressources Humaines"
])
revenu_mensuel = st.number_input("Revenu mensuel (€)", value=5000)
heure_supplementaires = st.selectbox("Heures supplémentaires", ["Oui", "Non"])
nb_experiences = st.number_input("Nombre d'expériences précédentes", value=2)
annees_experience = st.number_input("Années d'expérience totale", value=10)
annees_entreprise = st.number_input("Années dans l'entreprise", value=5)
annees_poste = st.number_input("Années dans le poste actuel", value=3)
annees_promotion = st.number_input("Années depuis la dernière promotion", value=1)
annees_manager = st.number_input("Années sous responsable actuel", value=2)
nb_formations = st.number_input("Nombre de formations suivies", value=2)
augmentation_num = st.number_input("Augmentation salaire précédente (%)", value=15)
augmentation = f"{augmentation_num} %"
with col3:
st.subheader("Satisfaction scores")
satisfaction_env = st.slider("Satisfaction environnement", 1, 4, 3)
satisfaction_travail = st.slider("Satisfaction nature du travail", 1, 4, 3)
satisfaction_equipe = st.slider("Satisfaction équipe", 1, 4, 3)
satisfaction_equilibre = st.slider("Satisfaction équilibre pro/perso", 1, 4, 3)
note_eval_prec = st.slider("Note évaluation précédente", 1, 4, 3)
note_eval_actuelle = st.slider("Note évaluation actuelle", 1, 4, 3)
niveau_hierarchique = st.number_input("Niveau hiérarchique", value=2)
nb_participation_pee = st.number_input("Participations PEE", value=3)
nb_employes_sous_resp = st.number_input("Employés sous responsabilité", value=0)
if st.button("🔮 Predict departure risk", type="primary"):
payload = {
"Genre": genre,
"Statut Marital": statut_marital,
"Département": departement,
"Poste": poste,
"Domaine d'étude": domaine_etude,
"Fréquence de déplacement": frequence_deplacement,
"Heures supplémentaires": heure_supplementaires,
"Âge": age,
"Revenu mensuel": revenu_mensuel,
"Nombre d'expériences précédentes": nb_experiences,
"Années d'expérience totale": annees_experience,
"Années dans l'entreprise": annees_entreprise,
"Années dans le poste actuel": annees_poste,
"Nombre de formations suivies": nb_formations,
"Distance domicile-travail": distance_domicile,
"Niveau d'éducation": niveau_education,
"Années depuis la dernière promotion": annees_promotion,
"Années sous responsable actuel": annees_manager,
"Satisfaction environnement": satisfaction_env,
"Note évaluation précédente": note_eval_prec,
"Satisfaction nature du travail": satisfaction_travail,
"Satisfaction équipe": satisfaction_equipe,
"Satisfaction équilibre pro/perso": satisfaction_equilibre,
"Note évaluation actuelle": note_eval_actuelle,
"Augmentation salaire précédente": augmentation
}
with st.spinner("Predicting..."):
try:
response = requests.post(f"{API_URL}/predict", json=payload)
if response.status_code == 200:
afficher_resultat(response.json())
else:
st.error(f"API error: {response.status_code}{response.text}")
except Exception as e:
st.error(f"Could not reach the API: {e}")
# ─── Tab 2 : Search by ID ─────────────────────────────────────────────────────
with tab2:
st.header("Search an employee by ID")
id_employee = st.number_input("Employee ID", min_value=1, value=1, step=1)
if st.button("🔍 Search and predict", type="primary"):
with st.spinner("Searching..."):
try:
response = requests.get(f"{API_URL}/predict/{id_employee}")
if response.status_code == 200:
afficher_resultat(response.json())
elif response.status_code == 404:
st.warning(f"⚠️ {response.json()['detail']}")
else:
st.error(f"API error: {response.status_code}")
except Exception as e:
st.error(f"Could not reach the API: {e}")