mt5-support-tickets / chatbot.py
abidne's picture
Upload 3 files
4c40701 verified
# 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()