#!/usr/bin/env python3 """ Interface pour le réseau bayésien d'évaluation d'autonomie Utilise pgmpy et pyAgrum pour charger et analyser le réseau BIF """ import sys import os from typing import Dict, List, Optional, Tuple import pandas as pd import numpy as np # Import des bibliothèques pour les réseaux bayésiens try: from pgmpy.readwrite import BIFReader from pgmpy.inference import VariableElimination from pgmpy.models import BayesianNetwork PGMPY_AVAILABLE = True except ImportError: PGMPY_AVAILABLE = False print("Warning: pgmpy not installed. Some features will be limited.") try: import pyAgrum as gum PYAGRUM_AVAILABLE = True except ImportError: PYAGRUM_AVAILABLE = False print("Warning: pyAgrum not installed. Some features will be limited.") # Pour l'interface graphique try: import streamlit as st import plotly.graph_objects as go import plotly.express as px STREAMLIT_AVAILABLE = True except ImportError: STREAMLIT_AVAILABLE = False class AutonomyBayesianNetwork: """Classe principale pour gérer le réseau bayésien d'autonomie""" def __init__(self, bif_file: str = "autonomy_functional_complete.bif"): self.bif_file = bif_file self.pgmpy_model = None self.pyagrum_model = None self.inference_engine = None # Variables catégorisées (réseau complet fonctionnel - 12 variables) self.non_actionable_vars = ['Age', 'Sex', 'Education_Level'] self.actionable_vars = ['Physical_Activity', 'BMI_Category', 'Smoking_Status', 'Social_Support', 'Social_Engagement'] self.intermediate_vars = ['Physical_Frailty', 'Cognitive_Function', 'Depression'] self.outcome_vars = ['Global_Autonomy'] self.load_network() def load_network(self): """Charge le réseau depuis le fichier BIF""" # Debug: Vérifier l'environnement debug_messages = [] debug_messages.append(f"🔍 Debug - Chargement réseau:") debug_messages.append(f" - Fichier BIF: {self.bif_file}") debug_messages.append(f" - Répertoire courant: {os.getcwd()}") debug_messages.append(f" - Fichier existe: {os.path.exists(self.bif_file)}") debug_messages.append(f" - pgmpy disponible: {PGMPY_AVAILABLE}") debug_messages.append(f" - pyagrum disponible: {PYAGRUM_AVAILABLE}") if os.path.exists(self.bif_file): try: with open(self.bif_file, 'r') as f: content_preview = f.read(200) debug_messages.append(f" - Aperçu fichier: {content_preview[:100]}...") except Exception as e: debug_messages.append(f" - Erreur lecture fichier: {e}") else: debug_messages.append(f" - ❌ Fichier {self.bif_file} non trouvé!") # Sauvegarder les messages de debug pour Streamlit self.debug_messages = debug_messages # Aussi les imprimer for msg in debug_messages: print(msg) if PGMPY_AVAILABLE and os.path.exists(self.bif_file): try: reader = BIFReader(self.bif_file) self.pgmpy_model = reader.get_model() self.inference_engine = VariableElimination(self.pgmpy_model) success_msg = f"✓ Réseau chargé avec pgmpy depuis {self.bif_file}" nodes_msg = f" - {len(list(self.pgmpy_model.nodes()))} nœuds, {len(list(self.pgmpy_model.edges()))} arcs" print(success_msg) print(nodes_msg) self.debug_messages.extend([success_msg, nodes_msg]) except Exception as e: error_msg = f"❌ Erreur pgmpy: {e}" print(error_msg) self.debug_messages.append(error_msg) if PYAGRUM_AVAILABLE and os.path.exists(self.bif_file): try: self.pyagrum_model = gum.loadBN(self.bif_file) success_msg = f"✓ Réseau chargé avec pyAgrum depuis {self.bif_file}" print(success_msg) self.debug_messages.append(success_msg) except Exception as e: error_msg = f"❌ Erreur pyAgrum: {e}" print(error_msg) self.debug_messages.append(error_msg) # Vérification finale if self.pgmpy_model is None and self.pyagrum_model is None: final_msg = "❌ Aucun modèle chargé!" print(final_msg) self.debug_messages.append(final_msg) # Suggestions de diagnostic if not PGMPY_AVAILABLE: suggestion = "💡 pgmpy non disponible - vérifiez requirements.txt et installation" print(suggestion) self.debug_messages.append(suggestion) if not PYAGRUM_AVAILABLE: suggestion = "💡 pyAgrum non disponible - installation optionnelle" print(suggestion) self.debug_messages.append(suggestion) def get_network_structure(self) -> Dict: """Retourne la structure du réseau""" structure = { 'nodes': [], 'edges': [], 'categories': {} } # Prioriser pgmpy_model car il est plus fiable if self.pgmpy_model: for node in self.pgmpy_model.nodes(): category = self._get_variable_category(node) structure['nodes'].append({ 'name': node, 'category': category }) structure['categories'][node] = category structure['edges'] = list(self.pgmpy_model.edges()) elif self.pyagrum_model and PYAGRUM_AVAILABLE: for node in self.pyagrum_model.names(): category = self._get_variable_category(node) structure['nodes'].append({ 'name': node, 'category': category, 'domain': list(self.pyagrum_model.variable(node).labels()) }) structure['categories'][node] = category for arc in self.pyagrum_model.arcs(): parent = self.pyagrum_model.variable(arc[0]).name() child = self.pyagrum_model.variable(arc[1]).name() structure['edges'].append((parent, child)) return structure def _get_variable_category(self, var_name: str) -> str: """Détermine la catégorie d'une variable""" if var_name in self.non_actionable_vars: return 'non_actionable' elif var_name in self.actionable_vars: return 'actionable' elif var_name in self.intermediate_vars: return 'intermediate' elif var_name in self.outcome_vars: return 'outcome' else: return 'unknown' def perform_inference_pgmpy(self, evidence: Dict, query_vars: List[str]) -> pd.DataFrame: """Effectue l'inférence avec pgmpy""" if not self.inference_engine: return pd.DataFrame() try: result = self.inference_engine.query(variables=query_vars, evidence=evidence) # Convertir en DataFrame data = [] for var in query_vars: if hasattr(result, 'values'): # Si c'est un seul facteur probs = result.values if var in result.variables: var_idx = result.variables.index(var) states = result.state_names[var] if len(result.variables) == 1: # Cas simple: une seule variable for i, state in enumerate(states): data.append({ 'Variable': var, 'State': state, 'Probability': probs[i] }) else: # Cas multiple: marginaliser marg_factor = result.marginalize([v for v in result.variables if v != var], inplace=False) for i, state in enumerate(states): data.append({ 'Variable': var, 'State': state, 'Probability': marg_factor.values[i] }) return pd.DataFrame(data) except Exception as e: print(f"Erreur d'inférence pgmpy: {e}") return pd.DataFrame() def perform_inference_pyagrum(self, evidence: Dict, query_vars: List[str]) -> pd.DataFrame: """Effectue l'inférence avec pyAgrum ou pgmpy en fallback""" # Essayer d'abord pyAgrum if self.pyagrum_model and PYAGRUM_AVAILABLE: try: ie = gum.LazyPropagation(self.pyagrum_model) # Définir l'évidence for var, value in evidence.items(): if var in self.pyagrum_model.names(): var_idx = self.pyagrum_model.idFromName(var) labels = self.pyagrum_model.variable(var_idx).labels() if value in labels: ie.setEvidence({var: value}) ie.makeInference() # Collecter les résultats data = [] for var in query_vars: if var in self.pyagrum_model.names(): posterior = ie.posterior(var) var_idx = self.pyagrum_model.idFromName(var) labels = self.pyagrum_model.variable(var_idx).labels() for i, label in enumerate(labels): data.append({ 'Variable': var, 'State': label, 'Probability': posterior[i] }) return pd.DataFrame(data) except Exception as e: print(f"Erreur d'inférence pyAgrum: {e}") # Fallback vers pgmpy if self.inference_engine: return self.perform_inference_pgmpy(evidence, query_vars) return pd.DataFrame() def analyze_intervention(self, intervention: Dict, target: str = 'Global_Autonomy') -> Dict: """Analyse l'impact d'une intervention sur l'autonomie""" results = { 'baseline': None, 'intervention': None, 'improvement': None } # Calcul baseline (sans intervention) baseline = self.perform_inference_pgmpy({}, [target]) if not baseline.empty: results['baseline'] = baseline # Calcul avec intervention intervention_result = self.perform_inference_pgmpy(intervention, [target]) if not intervention_result.empty: results['intervention'] = intervention_result # Calculer l'amélioration if results['baseline'] is not None and results['intervention'] is not None: baseline_autonomous = results['baseline'][ results['baseline']['State'] == 'autonomous']['Probability'].values intervention_autonomous = results['intervention'][ results['intervention']['State'] == 'autonomous']['Probability'].values if len(baseline_autonomous) > 0 and len(intervention_autonomous) > 0: results['improvement'] = { 'absolute': intervention_autonomous[0] - baseline_autonomous[0], 'relative': ((intervention_autonomous[0] - baseline_autonomous[0]) / baseline_autonomous[0] * 100) } return results def get_most_influential_factors(self, target: str = 'Global_Autonomy', n_top: int = 5) -> List[Tuple[str, float]]: """Identifie les facteurs les plus influents sur une variable cible""" influences = [] # Variables et leurs valeurs possibles (adaptées au réseau complet) variable_states = { 'Physical_Activity': ['sedentary', 'low', 'moderate', 'high'], 'BMI_Category': ['underweight_normal', 'overweight', 'obese_mild', 'obese_severe'], 'Smoking_Status': ['never', 'former', 'current'], 'Social_Support': ['poor', 'moderate', 'good'], 'Social_Engagement': ['low', 'moderate', 'high'] } if self.inference_engine: for var in self.actionable_vars: if var in variable_states: states = variable_states[var] if len(states) >= 2: # Comparer le meilleur et le pire état best_case = self.perform_inference_pgmpy( {var: states[-1]}, [target]) # Dernier état (généralement le meilleur) worst_case = self.perform_inference_pgmpy( {var: states[0]}, [target]) # Premier état (généralement le pire) if not best_case.empty and not worst_case.empty: best_prob = best_case[ best_case['State'] == 'autonomous']['Probability'].values worst_prob = worst_case[ worst_case['State'] == 'autonomous']['Probability'].values if len(best_prob) > 0 and len(worst_prob) > 0: influence = abs(best_prob[0] - worst_prob[0]) influences.append((var, influence)) # Trier par influence décroissante influences.sort(key=lambda x: x[1], reverse=True) return influences[:n_top] def generate_recommendations(self, patient_profile: Dict) -> List[Dict]: """Génère des recommandations personnalisées""" recommendations = [] # Analyser l'état actuel current_state = self.perform_inference_pgmpy( patient_profile, ['Global_Autonomy']) if current_state.empty: return recommendations current_autonomy_prob = current_state[ current_state['State'] == 'autonomous']['Probability'].values if len(current_autonomy_prob) == 0: return recommendations current_autonomy_prob = current_autonomy_prob[0] # Variables et leurs meilleures valeurs best_states = { 'Physical_Activity': 'high', 'BMI_Category': 'underweight_normal', 'Smoking_Status': 'never', 'Social_Support': 'good', 'Social_Engagement': 'high' } # Tester différentes interventions for var in self.actionable_vars: if var not in patient_profile and var in best_states: best_state = best_states[var] test_profile = patient_profile.copy() test_profile[var] = best_state new_state = self.perform_inference_pgmpy( test_profile, ['Global_Autonomy']) if not new_state.empty: new_autonomy_prob = new_state[ new_state['State'] == 'autonomous']['Probability'].values if len(new_autonomy_prob) > 0: improvement = new_autonomy_prob[0] - current_autonomy_prob if improvement > 0.01: # Amélioration significative # Créer des recommandations personnalisées rec_text = self._create_recommendation_text(var, best_state) recommendations.append({ 'variable': var, 'recommendation': rec_text, 'expected_improvement': improvement * 100, 'priority': 'high' if improvement > 0.1 else 'medium' }) # Trier par amélioration attendue recommendations.sort(key=lambda x: x['expected_improvement'], reverse=True) return recommendations[:5] # Top 5 recommandations def _create_recommendation_text(self, variable: str, state: str) -> str: """Crée un texte de recommandation personnalisé""" recommendations = { 'Physical_Activity': { 'high': "Pratiquer une activité physique intense (sport, course) au moins 150 min/semaine" }, 'BMI_Category': { 'underweight_normal': "Maintenir un poids corporel normal (IMC 18.5-24.9)" }, 'Smoking_Status': { 'never': "Éviter complètement le tabagisme ou arrêter de fumer" }, 'Social_Support': { 'good': "Développer un réseau de soutien social fort (famille, amis, communauté)" }, 'Social_Engagement': { 'high': "Participer activement à des activités sociales et communautaires" } } if variable in recommendations and state in recommendations[variable]: return recommendations[variable][state] else: return f"Améliorer {variable} vers {state}" class BayesianNetworkCLI: """Interface en ligne de commande pour le réseau bayésien""" def __init__(self): self.network = AutonomyBayesianNetwork() def run(self): """Lance l'interface CLI""" print("\n" + "="*60) print("Interface Réseau Bayésien - Évaluation d'Autonomie") print("="*60) while True: print("\nOptions disponibles:") print("1. Afficher la structure du réseau") print("2. Effectuer une inférence") print("3. Analyser une intervention") print("4. Identifier les facteurs influents") print("5. Générer des recommandations") print("6. Quitter") choice = input("\nVotre choix (1-6): ") if choice == '1': self.show_network_structure() elif choice == '2': self.perform_inference() elif choice == '3': self.analyze_intervention() elif choice == '4': self.identify_influential_factors() elif choice == '5': self.generate_recommendations() elif choice == '6': print("\nAu revoir!") break else: print("Choix invalide. Veuillez réessayer.") def show_network_structure(self): """Affiche la structure du réseau""" structure = self.network.get_network_structure() print("\n" + "-"*40) print("STRUCTURE DU RÉSEAU") print("-"*40) print(f"\nNombre de noeuds: {len(structure['nodes'])}") print(f"Nombre d'arcs: {len(structure['edges'])}") print("\nVariables par catégorie:") categories = {} for node in structure['nodes']: cat = node['category'] if cat not in categories: categories[cat] = [] categories[cat].append(node['name']) for cat, vars in categories.items(): print(f"\n{cat.upper()}:") for var in vars: print(f" - {var}") def perform_inference(self): """Effectue une inférence""" print("\n" + "-"*40) print("INFÉRENCE BAYÉSIENNE") print("-"*40) evidence = {} print("\nEntrez l'évidence (laissez vide pour terminer):") while True: var = input("Variable: ") if not var: break value = input(f"Valeur pour {var}: ") if value: evidence[var] = value query_vars = input("\nVariables à inférer (séparées par virgule): ").split(',') query_vars = [v.strip() for v in query_vars if v.strip()] if not query_vars: query_vars = ['Global_Autonomy'] print(f"\nInférence avec évidence: {evidence}") print(f"Variables requêtées: {query_vars}") result = self.network.perform_inference_pgmpy(evidence, query_vars) if not result.empty: print("\nRésultats:") print(result.to_string(index=False)) else: print("\nAucun résultat disponible.") def analyze_intervention(self): """Analyse une intervention""" print("\n" + "-"*40) print("ANALYSE D'INTERVENTION") print("-"*40) intervention = {} print("\nDéfinir l'intervention:") for var in self.network.actionable_vars: value = input(f"{var} (laissez vide pour ignorer): ") if value: intervention[var] = value if not intervention: print("Aucune intervention définie.") return print(f"\nAnalyse de l'intervention: {intervention}") results = self.network.analyze_intervention(intervention) if results['improvement']: print(f"\nAmélioration absolue: {results['improvement']['absolute']:.2%}") print(f"Amélioration relative: {results['improvement']['relative']:.1f}%") if results['baseline'] is not None: print("\nÉtat de base:") print(results['baseline'][results['baseline']['Variable'] == 'Global_Autonomy'].to_string(index=False)) if results['intervention'] is not None: print("\nAprès intervention:") print(results['intervention'][results['intervention']['Variable'] == 'Global_Autonomy'].to_string(index=False)) def identify_influential_factors(self): """Identifie les facteurs les plus influents""" print("\n" + "-"*40) print("FACTEURS INFLUENTS") print("-"*40) target = input("\nVariable cible (défaut: Global_Autonomy): ") or 'Global_Autonomy' n_top = int(input("Nombre de facteurs à afficher (défaut: 5): ") or 5) factors = self.network.get_most_influential_factors(target, n_top) if factors: print(f"\nTop {n_top} facteurs influençant {target}:") for i, (factor, influence) in enumerate(factors, 1): print(f"{i}. {factor}: {influence:.2%} d'influence") else: print("Aucun facteur influent trouvé.") def generate_recommendations(self): """Génère des recommandations personnalisées""" print("\n" + "-"*40) print("RECOMMANDATIONS PERSONNALISÉES") print("-"*40) profile = {} print("\nProfil du patient:") # Variables non-actionnables essentielles age = input("Age (age_60_69/age_70_79/age_80_89/age_90_plus): ") if age: profile['Age'] = age sex = input("Sexe (male/female): ") if sex: profile['Sex'] = sex # Variables actionnables actuelles print("\nÉtat actuel (laissez vide si inconnu):") for var in ['Physical_Activity', 'BMI_Category', 'Smoking_Status']: value = input(f"{var}: ") if value: profile[var] = value if not profile: print("Profil insuffisant pour générer des recommandations.") return print(f"\nGénération de recommandations pour: {profile}") recommendations = self.network.generate_recommendations(profile) if recommendations: print("\nRecommandations prioritaires:") for i, rec in enumerate(recommendations, 1): print(f"\n{i}. {rec['recommendation']}") print(f" Amélioration attendue: +{rec['expected_improvement']:.1f}%") print(f" Priorité: {rec['priority']}") else: print("\nAucune recommandation significative identifiée.") def create_streamlit_app(): """Crée une application Streamlit pour l'interface web""" if not STREAMLIT_AVAILABLE: print("Streamlit n'est pas installé. Interface web non disponible.") return st.set_page_config( page_title="Réseau Bayésien - Autonomie", page_icon="🧠", layout="wide" ) st.title("🧠 Réseau Bayésien pour l'Évaluation d'Autonomie") st.markdown("---") # Initialiser le réseau if 'network' not in st.session_state: st.session_state.network = AutonomyBayesianNetwork() network = st.session_state.network # Sidebar pour la navigation st.sidebar.title("Navigation") page = st.sidebar.selectbox( "Choisir une page", ["Structure du Réseau", "Inférence", "Analyse d'Intervention", "Facteurs Influents", "Recommandations"] ) if page == "Structure du Réseau": st.header("📊 Structure du Réseau Bayésien") structure = network.get_network_structure() col1, col2, col3 = st.columns(3) with col1: st.metric("Nombre de noeuds", len(structure['nodes'])) with col2: st.metric("Nombre d'arcs", len(structure['edges'])) with col3: st.metric("Variables actionnables", len(network.actionable_vars)) # Afficher les variables par catégorie st.subheader("Variables par catégorie") categories = {} for node in structure['nodes']: cat = node['category'] if cat not in categories: categories[cat] = [] categories[cat].append(node['name']) for cat in ['non_actionable', 'actionable', 'intermediate', 'outcome']: if cat in categories: with st.expander(f"{cat.replace('_', ' ').title()} ({len(categories[cat])} variables)"): for var in categories[cat]: st.write(f"• {var}") elif page == "Inférence": st.header("🔍 Inférence Bayésienne") col1, col2 = st.columns(2) with col1: st.subheader("Évidence") evidence = {} # Variables non-actionnables age = st.selectbox("Age", ["", "age_60_69", "age_70_79", "age_80_89", "age_90_plus"]) if age: evidence['Age'] = age sex = st.selectbox("Sexe", ["", "male", "female"]) if sex: evidence['Sex'] = sex # Variables actionnables activity = st.selectbox("Activité Physique", ["", "sedentary", "low", "moderate", "high"]) if activity: evidence['Physical_Activity'] = activity bmi = st.selectbox("Catégorie IMC", ["", "underweight", "normal", "overweight", "obese_class1", "obese_class2"]) if bmi: evidence['BMI_Category'] = bmi with col2: st.subheader("Variables à inférer") query_vars = st.multiselect( "Sélectionner les variables", network.outcome_vars + network.intermediate_vars, default=['Global_Autonomy'] ) if st.button("Effectuer l'inférence"): if query_vars: result = network.perform_inference_pgmpy(evidence, query_vars) if not result.empty: st.subheader("Résultats") for var in query_vars: var_data = result[result['Variable'] == var] if not var_data.empty: fig = px.bar(var_data, x='State', y='Probability', title=f"Distribution de probabilité pour {var}") st.plotly_chart(fig) else: st.error("Aucun résultat disponible") elif page == "Analyse d'Intervention": st.header("💊 Analyse d'Intervention") st.subheader("Définir l'intervention") intervention = {} col1, col2 = st.columns(2) with col1: for var in network.actionable_vars[:4]: value = st.selectbox(f"{var}", ["Non modifié"] + ["Option 1", "Option 2", "Option 3"]) if value != "Non modifié": intervention[var] = value with col2: for var in network.actionable_vars[4:]: value = st.selectbox(f"{var}", ["Non modifié"] + ["Option 1", "Option 2", "Option 3"]) if value != "Non modifié": intervention[var] = value if st.button("Analyser l'intervention"): if intervention: results = network.analyze_intervention(intervention) if results['improvement']: col1, col2 = st.columns(2) with col1: st.metric("Amélioration absolue", f"{results['improvement']['absolute']:.2%}") with col2: st.metric("Amélioration relative", f"{results['improvement']['relative']:.1f}%") # Graphique comparatif if results['baseline'] is not None and results['intervention'] is not None: baseline_data = results['baseline'][ results['baseline']['Variable'] == 'Global_Autonomy'] intervention_data = results['intervention'][ results['intervention']['Variable'] == 'Global_Autonomy'] comparison = pd.DataFrame({ 'State': baseline_data['State'].values, 'Baseline': baseline_data['Probability'].values, 'Intervention': intervention_data['Probability'].values }) fig = go.Figure() fig.add_trace(go.Bar(name='Baseline', x=comparison['State'], y=comparison['Baseline'])) fig.add_trace(go.Bar(name='Intervention', x=comparison['State'], y=comparison['Intervention'])) fig.update_layout(title="Comparaison Baseline vs Intervention", barmode='group') st.plotly_chart(fig) elif page == "Facteurs Influents": st.header("📈 Facteurs les Plus Influents") target = st.selectbox("Variable cible", network.outcome_vars, index=network.outcome_vars.index('Global_Autonomy')) n_top = st.slider("Nombre de facteurs", 3, 10, 5) if st.button("Identifier les facteurs"): factors = network.get_most_influential_factors(target, n_top) if factors: # Créer un graphique à barres df_factors = pd.DataFrame(factors, columns=['Facteur', 'Influence']) df_factors['Influence'] = df_factors['Influence'] * 100 fig = px.bar(df_factors, x='Influence', y='Facteur', orientation='h', title=f"Top {n_top} facteurs influençant {target}", labels={'Influence': 'Influence (%)'}) st.plotly_chart(fig) # Tableau détaillé st.subheader("Détails") for i, (factor, influence) in enumerate(factors, 1): st.write(f"{i}. **{factor}**: {influence:.2%} d'influence") elif page == "Recommandations": st.header("📋 Recommandations Personnalisées") st.subheader("Profil du Patient") profile = {} col1, col2 = st.columns(2) with col1: age = st.selectbox("Age", ["age_60_69", "age_70_79", "age_80_89", "age_90_plus"]) profile['Age'] = age sex = st.selectbox("Sexe", ["male", "female"]) profile['Sex'] = sex activity = st.selectbox("Activité Physique actuelle", ["sedentary", "low", "moderate", "high"]) profile['Physical_Activity'] = activity with col2: bmi = st.selectbox("Catégorie IMC actuelle", ["underweight", "normal", "overweight", "obese_class1", "obese_class2"]) profile['BMI_Category'] = bmi smoking = st.selectbox("Statut tabagique", ["never", "former", "current"]) profile['Smoking_Status'] = smoking if st.button("Générer les recommandations"): with st.spinner("Analyse en cours..."): recommendations = network.generate_recommendations(profile) if recommendations: st.success("Recommandations générées avec succès!") for i, rec in enumerate(recommendations, 1): priority_color = { 'high': '🔴', 'medium': '🟡', 'low': '🟢' }.get(rec['priority'], '⚪') with st.container(): col1, col2 = st.columns([3, 1]) with col1: st.write(f"{priority_color} **{rec['recommendation']}**") with col2: st.metric("Amélioration", f"+{rec['expected_improvement']:.1f}%") else: st.info("Aucune recommandation significative identifiée.") def main(): """Fonction principale""" if len(sys.argv) > 1 and sys.argv[1] == 'web': # Lancer l'interface web if STREAMLIT_AVAILABLE: create_streamlit_app() else: print("Streamlit n'est pas installé. Installez-le avec: pip install streamlit") print("Lancement de l'interface CLI à la place...") cli = BayesianNetworkCLI() cli.run() else: # Lancer l'interface CLI cli = BayesianNetworkCLI() cli.run() if __name__ == "__main__": main()