# executives/ui.py import gradio as gr import asyncio from main import NexusAgenticSystem # Initialisation du noyau dur nexus = NexusAgenticSystem() async def interaction_nexus(message, history): if not nexus.llm_en_ligne: await nexus.prechauffer_cerveau() # 1. RECONSTITUTION DE LA MÉMOIRE (Blindage Multi-Versions Gradio) ticket_complet = "" transcript_llm = "" for msg in history: # Compatibilité Gradio 5+ (Format Liste de Dictionnaires) if isinstance(msg, dict): role = msg.get("role", "") content = msg.get("content", "") if role == "user": ticket_complet += f"{content} " transcript_llm += f"Client: {content}\n" elif role == "assistant": transcript_llm += f"Régulateur: {content}\n" # Compatibilité Gradio 4 (Ancien Format Liste de Tuples) elif isinstance(msg, (list, tuple)) and len(msg) == 2: u, b = msg if u: ticket_complet += f"{u} " transcript_llm += f"Client: {u}\n" if b: transcript_llm += f"Régulateur: {b}\n" # Ajout du message courant ticket_complet += message transcript_llm += f"Client: {message}" # 2. ANALYSE GLOBALE VIA LE MODÈLE ML (Sur l'ensemble des faits) domaine, score, friction = nexus.evaluator.evaluer_ticket(ticket_complet) # 3. VÉRIFICATION DYNAMIQUE DE LA LOCALISATION localisation_obtenue = nexus.verifier_presence_localisation(ticket_complet) # 4. GESTION DE L'ÉTAT (State Management réel) session_state = { "domaine_verrouille": domaine, "score_verrouille": score, "localisation_obtenue": localisation_obtenue, "frustration_count": 0 } # 5. COUPE-CIRCUIT D'AGRESSIVITÉ OU ABANDON mots_frustration = ["bordel", "foutre", "con", "merde", "putain", "répéter", "fin au ticket", "stop", "quitter", "q"] if any(mot in message.lower() for mot in mots_frustration): niveau = "🔴 CRITIQUE" if score >= 8 else "🟠 HAUTE" if score >= 5 else "🟢 BASSE" nexus.logger.log(ticket_complet, domaine, [], score, statut="CLOTURE_FORCEE") return f"⚠️ RUPTURE DE LIAISON DÉTECTÉE. TICKET CLOS D'URGENCE.\nDomaine : {domaine}\nNiveau Alerte : {niveau}\nTransmission immédiate aux unités de terrain." # 6. DÉCISION DE ROUTAGE if friction != "COMPLET" or not localisation_obtenue: statut, question_bot = await nexus.generer_question_bot( transcript=transcript_llm, texte_utilisateur=message, domaine=domaine, score_actuel=score, state=session_state ) if statut == "COMPLET": niveau = "🔴 CRITIQUE" if score >= 8 else "🟠 HAUTE" if score >= 5 else "🟢 BASSE" nexus.logger.log(ticket_complet, domaine, [], score, statut="CLOS") return f"✅ TICKET CLOS ET TRANSMIS.\nDomaine : {domaine}\nNiveau Alerte : {niveau}\nLes unités sont en route." return f"🚨 [Unités: {domaine} | Urgence: {score}/10]\nNEXUS: {question_bot}" else: niveau = "🔴 CRITIQUE" if score >= 8 else "🟠 HAUTE" if score >= 5 else "🟢 BASSE" nexus.logger.log(ticket_complet, domaine, [], score, statut="CLOS") return f"✅ TICKET COMPLET ET TRANSMIS.\nDomaine : {domaine}\nNiveau Alerte : {niveau}\nLes unités sont en route." # Définition de l'interface graphique app = gr.ChatInterface( fn=interaction_nexus, title="NEXUS Prime - Centre de Commandement", description="Entrez la situation d'urgence. Moteur hybride tactique (Scikit-Learn + Ollama / Gemma 4).", fill_height=True ) if __name__ == "__main__": app.launch(server_name="0.0.0.0", server_port=7860, share=True)