|
|
|
|
|
|
|
|
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() |
|
|
|
|
|
|
|
|
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() |
|
|
|
|
|
|
|
|
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" |
|
|
] |
|
|
} |
|
|
|
|
|
|
|
|
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() |
|
|
|
|
|
|
|
|
if self.detect_problem_keywords(user_input, lang): |
|
|
return None |
|
|
|
|
|
|
|
|
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] |
|
|
|
|
|
|
|
|
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]) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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] |
|
|
|
|
|
|
|
|
emotional_response = self.get_emotional_response(user_input, lang) |
|
|
if emotional_response: |
|
|
return emotional_response |
|
|
|
|
|
|
|
|
contextual_response = self.get_contextual_response(user_input, lang) |
|
|
if contextual_response: |
|
|
return contextual_response |
|
|
|
|
|
|
|
|
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: |
|
|
responses = [f"{time_greetings['de']}{name_part}! 👋", f"Hallo{name_part}! Wie geht es Ihnen? 😊"] |
|
|
|
|
|
return random.choice(responses) |
|
|
|
|
|
|
|
|
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]) |
|
|
|
|
|
|
|
|
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é""" |
|
|
|
|
|
self.conversation_history.append({"user": user_input, "timestamp": datetime.now()}) |
|
|
|
|
|
lang = self.detect_language(user_input) |
|
|
|
|
|
|
|
|
if self.detect_problem_keywords(user_input, lang): |
|
|
print(f"[DEBUG] Problème détecté, transmission au modèle MT5...") |
|
|
|
|
|
|
|
|
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:" |
|
|
] |
|
|
} |
|
|
|
|
|
|
|
|
model_response = call_mt5_model(user_input) |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
print(f"[DEBUG] Question générale, utilisation du modèle MT5...") |
|
|
|
|
|
|
|
|
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:", ""] |
|
|
} |
|
|
|
|
|
|
|
|
model_response = call_mt5_model(user_input) |
|
|
|
|
|
|
|
|
prefix = random.choice(general_prefixes[lang]) |
|
|
if prefix and random.random() < 0.3: |
|
|
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" |
|
|
|
|
|
|
|
|
def create_chatbot(): |
|
|
"""Crée une nouvelle instance du chatbot""" |
|
|
return HumanChatbot() |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
bot = create_chatbot() |
|
|
|
|
|
|
|
|
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")) |
|
|
|
|
|
|
|
|
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")) |
|
|
|
|
|
|
|
|
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 !")) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_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 |
|
|
|
|
|
|
|
|
if _global_chatbot is None: |
|
|
_global_chatbot = HumanChatbot() |
|
|
|
|
|
|
|
|
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() |
|
|
|