# chatbot_enhanced.py import random import re from datetime import datetime from model_mt5 import call_mt5_model class HumanChatbot: def __init__(self): self.conversation_history = [] self.user_name = None self.context = {} def get_time_greeting(self): """Retourne un salut adapté à l'heure""" hour = datetime.now().hour if 5 <= hour < 12: return {"fr": "Bonjour", "en": "Good morning", "es": "Buenos días", "de": "Guten Morgen"} elif 12 <= hour < 18: return {"fr": "Bonjour", "en": "Good afternoon", "es": "Buenas tardes", "de": "Guten Tag"} else: return {"fr": "Bonsoir", "en": "Good evening", "es": "Buenas noches", "de": "Guten Abend"} def detect_language(self, text): """Détecte la langue principale du texte""" text_lower = text.lower() # Mots clés par langue lang_indicators = { "fr": ["bonjour", "salut", "merci", "comment", "ça", "va", "oui", "non", "je", "tu", "vous"], "en": ["hello", "hi", "thank", "how", "are", "you", "yes", "no", "i", "you", "the"], "es": ["hola", "gracias", "cómo", "estás", "sí", "no", "yo", "tú", "el", "la"], "de": ["hallo", "danke", "wie", "geht", "ja", "nein", "ich", "du", "der", "die"] } scores = {} for lang, words in lang_indicators.items(): scores[lang] = sum(1 for word in words if word in text_lower) return max(scores, key=scores.get) if max(scores.values()) > 0 else "fr" def extract_user_name(self, text): """Extrait le nom de l'utilisateur""" patterns = [ r"je m'appelle (\w+)", r"mon nom est (\w+)", r"i'?m (\w+)", r"my name is (\w+)", r"me llamo (\w+)", r"ich heiße (\w+)" ] for pattern in patterns: match = re.search(pattern, text.lower()) if match: return match.group(1).capitalize() return None def get_emotional_response(self, user_input, lang): """Génère une réponse émotionnelle selon le contexte""" input_lower = user_input.lower() # Détection d'émotions emotions = { "happy": { "keywords": ["content", "heureux", "joie", "super", "génial", "happy", "great", "awesome", "feliz", "genial"], "responses": { "fr": ["C'est formidable ! 😊", "Je suis ravi de l'entendre ! 🎉", "Ça me fait plaisir ! ✨"], "en": ["That's wonderful! 😊", "I'm so happy to hear that! 🎉", "That's great news! ✨"], "es": ["¡Qué maravilloso! 😊", "¡Me alegra escuchar eso! 🎉", "¡Qué buena noticia! ✨"], "de": ["Das ist wunderbar! 😊", "Das freut mich sehr! 🎉", "Tolle Neuigkeiten! ✨"] } }, "sad": { "keywords": ["triste", "mal", "difficile", "problème", "sad", "bad", "difficult", "problem", "triste", "mal", "schwierig"], "responses": { "fr": ["Je suis désolé de l'entendre... 😔", "Ça doit être difficile pour vous.", "Je comprends votre situation."], "en": ["I'm sorry to hear that... 😔", "That must be difficult for you.", "I understand your situation."], "es": ["Lamento escuchar eso... 😔", "Debe ser difícil para ti.", "Entiendo tu situación."], "de": ["Das tut mir leid zu hören... 😔", "Das muss schwierig für Sie sein.", "Ich verstehe Ihre Situation."] } }, "confused": { "keywords": ["comprends pas", "confus", "don't understand", "confused", "no entiendo", "verstehe nicht"], "responses": { "fr": ["Pas de souci, je vais essayer d'être plus clair.", "Laissez-moi reformuler ça.", "Je peux vous expliquer autrement."], "en": ["No worries, let me try to be clearer.", "Let me rephrase that.", "I can explain it differently."], "es": ["No te preocupes, intentaré ser más claro.", "Déjame reformular eso.", "Puedo explicarlo de otra manera."], "de": ["Kein Problem, ich versuche klarer zu sein.", "Lassen Sie mich das umformulieren.", "Ich kann es anders erklären."] } } } for emotion, data in emotions.items(): if any(keyword in input_lower for keyword in data["keywords"]): return random.choice(data["responses"][lang]) return None def detect_problem_keywords(self, user_input, lang): """Détecte si l'utilisateur présente un problème technique ou demande de l'aide""" input_lower = user_input.lower() problem_keywords = { "fr": [ "problème", "pb", "erreur", "bug", "panne", "défaut", "dysfonctionnement", "ça marche pas", "ne fonctionne pas", "ne marche pas", "cassé", "bloqué", "aide", "aider", "comment", "comment faire", "solution", "résoudre", "pourquoi", "expliquer", "expliquez", "que faire", "urgent", "besoin d'aide" ], "en": [ "problem", "issue", "error", "bug", "broken", "not working", "doesn't work", "help", "how to", "how do", "solution", "solve", "fix", "explain", "why", "what to do", "urgent", "need help", "trouble", "difficulty" ], "es": [ "problema", "error", "fallo", "no funciona", "roto", "bloqueado", "ayuda", "ayudar", "cómo", "solución", "resolver", "explicar", "por qué", "qué hacer", "urgente", "necesito ayuda" ], "de": [ "problem", "fehler", "bug", "kaputt", "funktioniert nicht", "geht nicht", "hilfe", "helfen", "wie", "lösung", "lösen", "erklären", "warum", "was tun", "dringend", "brauche hilfe" ] } # Vérifier si le message contient des mots-clés de problème keywords = problem_keywords.get(lang, problem_keywords["fr"]) return any(keyword in input_lower for keyword in keywords) def get_contextual_response(self, user_input, lang): """Génère une réponse contextuelle""" input_lower = user_input.lower() # NOUVEAU: Détection de problèmes - transmettre directement au modèle if self.detect_problem_keywords(user_input, lang): return None # Retourner None pour passer au modèle MT5 # Questions sur le chatbot if any(word in input_lower for word in ["qui es-tu", "what are you", "quién eres", "wer bist du"]): responses = { "fr": "Je suis votre assistant virtuel ! Je suis là pour discuter et vous aider du mieux que je peux. 🤖", "en": "I'm your virtual assistant! I'm here to chat and help you as best I can. 🤖", "es": "¡Soy tu asistente virtual! Estoy aquí para charlar y ayudarte lo mejor que pueda. 🤖", "de": "Ich bin Ihr virtueller Assistent! Ich bin hier, um zu plaudern und Ihnen zu helfen, so gut ich kann. 🤖" } return responses[lang] # Questions sur l'humeur if any(word in input_lower for word in ["comment tu vas", "how are you", "cómo estás", "wie geht es dir"]): responses = { "fr": ["Je vais bien, merci ! Et vous ? 😊", "Ça va très bien ! Comment allez-vous ?", "Parfait, merci de demander ! Et vous ?"], "en": ["I'm doing well, thanks! How about you? 😊", "I'm great! How are you doing?", "Perfect, thanks for asking! And you?"], "es": ["¡Estoy bien, gracias! ¿Y tú? 😊", "¡Muy bien! ¿Cómo estás?", "¡Perfecto, gracias por preguntar! ¿Y tú?"], "de": ["Mir geht es gut, danke! Und Ihnen? 😊", "Mir geht es sehr gut! Wie geht es Ihnen?", "Perfekt, danke der Nachfrage! Und Ihnen?"] } return random.choice(responses[lang]) # Expressions de politesse if any(word in input_lower for word in ["s'il vous plaît", "please", "por favor", "bitte"]): responses = { "fr": "Bien sûr, avec plaisir ! 😊", "en": "Of course, with pleasure! 😊", "es": "¡Por supuesto, con mucho gusto! 😊", "de": "Natürlich, gerne! 😊" } return responses[lang] return None def get_rule_based_response(self, user_input): """Version améliorée des réponses basées sur des règles""" input_lower = user_input.lower() lang = self.detect_language(user_input) # Extraction du nom si présent name = self.extract_user_name(user_input) if name: self.user_name = name responses = { "fr": f"Ravi de faire votre connaissance, {name} ! 😊", "en": f"Nice to meet you, {name}! 😊", "es": f"¡Encantado de conocerte, {name}! 😊", "de": f"Schön Sie kennenzulernen, {name}! 😊" } return responses[lang] # Réponse émotionnelle emotional_response = self.get_emotional_response(user_input, lang) if emotional_response: return emotional_response # Réponse contextuelle contextual_response = self.get_contextual_response(user_input, lang) if contextual_response: return contextual_response # Salutations avec variation greetings = { "fr": ["bonjour", "salut", "bonsoir", "coucou", "hey"], "en": ["hello", "hi", "good morning", "good evening", "hey"], "es": ["hola", "buenos días", "buenas tardes", "hey"], "de": ["hallo", "guten tag", "guten morgen", "hey"] } for language, keywords in greetings.items(): if any(word in input_lower for word in keywords): time_greetings = self.get_time_greeting() name_part = f" {self.user_name}" if self.user_name else "" if language == "fr": responses = [f"{time_greetings['fr']}{name_part} ! 👋", f"Salut{name_part} ! Comment allez-vous ? 😊"] elif language == "en": responses = [f"{time_greetings['en']}{name_part}! 👋", f"Hi{name_part}! How are you doing? 😊"] elif language == "es": responses = [f"¡{time_greetings['es']}{name_part}! 👋", f"¡Hola{name_part}! ¿Cómo estás? 😊"] else: # de responses = [f"{time_greetings['de']}{name_part}! 👋", f"Hallo{name_part}! Wie geht es Ihnen? 😊"] return random.choice(responses) # Remerciements avec variation thanks = { "fr": ["merci", "merci beaucoup"], "en": ["thank you", "thanks", "thank you very much"], "es": ["gracias", "muchas gracias"], "de": ["danke", "vielen dank"] } for language, keywords in thanks.items(): if any(word in input_lower for word in keywords): responses = { "fr": ["De rien ! 😊", "Avec plaisir !", "C'est tout naturel !", "Je vous en prie !"], "en": ["You're welcome! 😊", "My pleasure!", "No problem!", "Anytime!"], "es": ["¡De nada! 😊", "¡Con mucho gusto!", "¡No hay problema!", "¡Cuando quieras!"], "de": ["Gern geschehen! 😊", "Gerne!", "Kein Problem!", "Jederzeit!"] } return random.choice(responses[language]) # Adieux avec variation farewell = { "fr": ["au revoir", "à bientôt", "salut", "bye", "ciao"], "en": ["goodbye", "see you", "bye", "farewell", "take care"], "es": ["adiós", "hasta luego", "bye", "ciao", "cuídate"], "de": ["tschüss", "auf wiedersehen", "bye", "ciao", "mach's gut"] } for language, keywords in farewell.items(): if any(word in input_lower for word in keywords): name_part = f" {self.user_name}" if self.user_name else "" responses = { "fr": [f"Au revoir{name_part} ! 👋", f"À bientôt{name_part} ! 😊", "Passez une excellente journée ! ✨"], "en": [f"Goodbye{name_part}! 👋", f"See you later{name_part}! 😊", "Have a wonderful day! ✨"], "es": [f"¡Adiós{name_part}! 👋", f"¡Hasta luego{name_part}! 😊", "¡Que tengas un día maravilloso! ✨"], "de": [f"Auf Wiedersehen{name_part}! 👋", f"Bis bald{name_part}! 😊", "Haben Sie einen wunderbaren Tag! ✨"] } return random.choice(responses[language]) return None def get_bot_response(self, user_input): """Fonction principale du chatbot amélioré""" # Ajouter à l'historique self.conversation_history.append({"user": user_input, "timestamp": datetime.now()}) lang = self.detect_language(user_input) # PRIORITÉ 1: Vérifier si c'est un problème technique - directement au modèle MT5 if self.detect_problem_keywords(user_input, lang): print(f"[DEBUG] Problème détecté, transmission au modèle MT5...") # Préfixes pour introduire la réponse du modèle problem_prefixes = { "fr": [ "Je comprends votre problème. Laissez-moi vous aider :", "Voici ce que je peux vous proposer :", "D'après votre description, voici ma recommandation :", "Je vais analyser votre problème :" ], "en": [ "I understand your problem. Let me help you:", "Here's what I can suggest:", "Based on your description, here's my recommendation:", "Let me analyze your problem:" ], "es": [ "Entiendo tu problema. Déjame ayudarte:", "Esto es lo que puedo sugerir:", "Basándome en tu descripción, esta es mi recomendación:", "Voy a analizar tu problema:" ], "de": [ "Ich verstehe Ihr Problem. Lassen Sie mich Ihnen helfen:", "Hier ist was ich vorschlagen kann:", "Basierend auf Ihrer Beschreibung, hier ist meine Empfehlung:", "Ich werde Ihr Problem analysieren:" ] } # Obtenir la réponse du modèle MT5 model_response = call_mt5_model(user_input) # Ajouter un préfixe approprié prefix = random.choice(problem_prefixes[lang]) final_response = f"{prefix}\n\n{model_response}" self.conversation_history.append({"bot": final_response, "timestamp": datetime.now()}) return final_response # PRIORITÉ 2: Essayer les réponses basées sur des règles (salutations, politesse, etc.) rule_response = self.get_rule_based_response(user_input) if rule_response: self.conversation_history.append({"bot": rule_response, "timestamp": datetime.now()}) return rule_response # PRIORITÉ 3: Questions générales - utiliser le modèle mT5 avec préfixe conversationnel print(f"[DEBUG] Question générale, utilisation du modèle MT5...") # Préfixes pour rendre la réponse plus naturelle general_prefixes = { "fr": ["Hmm, laissez-moi réfléchir...", "Intéressant !", "Bonne question !", "Voici ce que je pense :", ""], "en": ["Hmm, let me think...", "Interesting!", "Good question!", "Here's what I think:", ""], "es": ["Hmm, déjame pensar...", "¡Interesante!", "¡Buena pregunta!", "Esto es lo que pienso:", ""], "de": ["Hmm, lass mich nachdenken...", "Interessant!", "Gute Frage!", "Das denke ich:", ""] } # Obtenir la réponse du modèle model_response = call_mt5_model(user_input) # Ajouter un préfixe occasionnel pour plus de naturel prefix = random.choice(general_prefixes[lang]) if prefix and random.random() < 0.3: # 30% de chance d'ajouter un préfixe final_response = f"{prefix} {model_response}" else: final_response = model_response self.conversation_history.append({"bot": final_response, "timestamp": datetime.now()}) return final_response def get_conversation_summary(self): """Retourne un résumé de la conversation""" if not self.conversation_history: return "Aucune conversation en cours." user_messages = len([msg for msg in self.conversation_history if "user" in msg]) bot_messages = len([msg for msg in self.conversation_history if "bot" in msg]) return f"Conversation: {user_messages} messages utilisateur, {bot_messages} réponses du bot" # Utilisation def create_chatbot(): """Crée une nouvelle instance du chatbot""" return HumanChatbot() # Exemple d'utilisation avec détection de problèmes if __name__ == "__main__": bot = create_chatbot() # Test des salutations print("=== Test Salutations ===") print("User: Bonjour !") print("Bot:", bot.get_bot_response("Bonjour !")) print("\nUser: Je m'appelle Marie") print("Bot:", bot.get_bot_response("Je m'appelle Marie")) # Test des problèmes - vont directement au modèle MT5 print("\n=== Test Problèmes (vont au modèle MT5) ===") print("User: J'ai un problème avec mon ordinateur") print("Bot:", bot.get_bot_response("J'ai un problème avec mon ordinateur")) print("\nUser: Comment résoudre une erreur 404 ?") print("Bot:", bot.get_bot_response("Comment résoudre une erreur 404 ?")) print("\nUser: Mon logiciel ne fonctionne pas, que faire ?") print("Bot:", bot.get_bot_response("Mon logiciel ne fonctionne pas, que faire ?")) print("\nUser: I need help with my code") print("Bot:", bot.get_bot_response("I need help with my code")) # Test des questions générales print("\n=== Test Questions Générales ===") print("User: Comment allez-vous ?") print("Bot:", bot.get_bot_response("Comment allez-vous ?")) print("\nUser: Merci beaucoup !") print("Bot:", bot.get_bot_response("Merci beaucoup !")) print("\nUser: Au revoir !") print("Bot:", bot.get_bot_response("Au revoir !")) # Ajoutez ces lignes à la fin de votre chatbot.py pour maintenir la compatibilité # Instance globale pour la compatibilité avec l'ancien code _global_chatbot = None def get_bot_response(user_input): """ Fonction wrapper pour maintenir la compatibilité avec l'ancien code Utilise une instance globale du chatbot """ global _global_chatbot # Créer l'instance si elle n'existe pas if _global_chatbot is None: _global_chatbot = HumanChatbot() # Retourner la réponse return _global_chatbot.get_bot_response(user_input) def reset_chatbot(): """Réinitialise le chatbot global""" global _global_chatbot _global_chatbot = None def get_chatbot_stats(): """Retourne les statistiques du chatbot global""" global _global_chatbot if _global_chatbot is None: return "Aucune conversation en cours." return _global_chatbot.get_conversation_summary()