Spaces:
Running
Running
| 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}") | |