Spaces:
Sleeping
Sleeping
| import pandas as pd | |
| import numpy as np | |
| import xgboost as xgb | |
| import json | |
| import os | |
| import boto3 | |
| # --- 1. CHARGEMENT DES CONFIGURATIONS --- | |
| # On récupère la liste des colonnes depuis le Secret | |
| FEATURES = json.loads(os.getenv("MODEL_FEATURES", "[]")) | |
| def load_from_s3(file_name): | |
| """Charge un dictionnaire JSON depuis S3""" | |
| try: | |
| s3 = boto3.client( | |
| 's3', | |
| aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"), | |
| aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"), | |
| region_name=os.getenv("AWS_REGION") | |
| ) | |
| # Le nom du bucket vient de ton secret, ou on le force ici s'il est mal configuré | |
| bucket = os.getenv("AWS_BUCKET_NAME", "projet-economie") | |
| # LA CLÉ RÉELLE (ne doit pas contenir le nom du bucket au début) | |
| key = f"models/{file_name}" | |
| print(f"🔍 Tentative S3 : Bucket={bucket} | Key={key}") | |
| response = s3.get_object(Bucket=bucket, Key=key) | |
| return json.loads(response['Body'].read().decode('utf-8')) | |
| except Exception as e: | |
| print(f"❌ ÉCHEC S3 sur {file_name} : {e}") | |
| return {} | |
| # Chargement (les variables seront enfin remplies !) | |
| DEP_RISK_MAP = load_from_s3("mapping_dep_risk.json") | |
| APE_SECTION_MAP = load_from_s3("mapping_ape_section.json") | |
| # --- 2. CALCULS --- | |
| def get_sigma(model): | |
| try: | |
| config = json.loads(model.save_config()) | |
| def find_key(obj, key): | |
| if isinstance(obj, dict): | |
| for k, v in obj.items(): | |
| if k == key: return v | |
| res = find_key(v, key) | |
| if res is not None: return res | |
| elif isinstance(obj, list): | |
| for item in obj: | |
| res = find_key(item, key) | |
| if res is not None: return res | |
| return None | |
| scale = find_key(config, 'aft_loss_distribution_scale') | |
| return float(scale) if scale else 0.8 | |
| except: | |
| return 0.8 | |
| def calculate_survival_risk(mu, horizon, s): | |
| z = (np.log(horizon) - mu) / s | |
| z = np.clip(z, -50, 50) | |
| return round((1 / (1 + np.exp(-z))) * 100, 2) | |
| def map_statut_expert(p2): | |
| if p2 > 20: return '🔴 CRITIQUE' | |
| if p2 > 10: return '🟠 VIGILANCE' | |
| if p2 > 5: return '🟡 OBSERVATION' | |
| return '🟢 SAIN' | |
| # --- 3. PRÉPARATION DES DONNÉES --- | |
| def prepare_input(data): | |
| # Création du DF avec les colonnes du Secret | |
| df = pd.DataFrame(0.0, index=[0], columns=FEATURES) | |
| # Remplissage des variables | |
| # On utilise .loc[0, col] pour être sûr de ne pas créer de nouvelles colonnes | |
| if 'age_au_diagnostic' in df.columns: | |
| df.loc[0, 'age_au_diagnostic'] = float(data.get('age_estime', 0)) | |
| if 'Tranche_effectif_num' in df.columns: | |
| df.loc[0, 'Tranche_effectif_num'] = float(data.get('Tranche_effectif_num', 0)) | |
| if 'is_ess' in df.columns: | |
| df.loc[0, 'is_ess'] = int(data.get('is_ess', 0)) | |
| # Risque départemental | |
| code_dep = str(data.get('code_departement', '')).strip().upper() | |
| if 'risque_departemental' in df.columns: | |
| df.loc[0, 'risque_departemental'] = float(DEP_RISK_MAP.get(code_dep, 0.05)) | |
| # Mapping APE | |
| code_ape = str(data.get('code_ape', '')).zfill(2) | |
| section_name = APE_SECTION_MAP.get(code_ape) | |
| if section_name: | |
| col_ape = f"APE_{section_name}" | |
| if col_ape in df.columns: | |
| df.loc[0, col_ape] = 1.0 | |
| elif 'APE_Autres_Secteurs' in df.columns: | |
| df.loc[0, 'APE_Autres_Secteurs'] = 1.0 | |
| # Mapping CJ | |
| cj_prefix = str(data.get('categorie_juridique', ''))[:4] | |
| col_cj = f"CJ_{cj_prefix}" | |
| if col_cj in df.columns: | |
| df.loc[0, col_cj] = 1.0 | |
| # LOG DE DEBUG (Visible dans les logs HF) | |
| print(f"DEBUG: Age envoyé={data.get('age_estime')} | Valeur dans DF={df['age_au_diagnostic'].iloc[0]}") | |
| return xgb.DMatrix(df) |