fatmata commited on
Commit
958763c
·
verified ·
1 Parent(s): a34cb00

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -89
app.py CHANGED
@@ -1,115 +1,99 @@
1
  import gradio as gr
2
- from transformers import AutoTokenizer, AutoModelForCausalLM, AutoModelForSequenceClassification
3
- import torch
4
- import torch.nn.functional as F
5
- from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
6
- from mtranslate import translate
7
- from langdetect import detect
8
- from duckduckgo_search import DDGS
9
- import re
10
-
11
- # === Nettoyage texte ===
12
- def clean_response(text):
13
- text = re.sub(r'<[^>]+>', '', text)
14
- text = re.split(r'</(Bot|name|opinion|User|[a-zA-Z]*)>', text)[0]
15
- text = re.sub(r'^\s*[,.:;-]*', '', text)
16
- text = re.sub(r'^\s*(Psyche|Therapist|Bot|Assistant|AI):?\s*', '', text)
17
- text = re.sub(r'\([^)]*\)', '', text)
18
- text = re.sub(r'\[.*?\]', '', text)
19
- text = re.sub(r'[:;=8][-~]?[)D(\\/*|]', '', text)
20
- text = re.sub(r'\s{2,}', ' ', text).strip()
21
- sentences = re.split(r'(?<=[.!?])\s+', text)
22
- return " ".join(sentences[:2]).strip()
23
-
24
- # === Charger modèles ===
25
- MODEL_PATH = "fatmata/gpt-psybot"
26
- tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, use_fast=False)
27
- model = AutoModelForCausalLM.from_pretrained(MODEL_PATH)
28
-
29
- BERT_MODEL_NAME = "fatmata/bert_model"
30
- bert_tokenizer = AutoTokenizer.from_pretrained(BERT_MODEL_NAME)
31
- bert_model = AutoModelForSequenceClassification.from_pretrained(BERT_MODEL_NAME)
32
-
33
- CLASSIFIER_PATH = "fatmata/mini_bert"
34
- model_c = AutoModelForSequenceClassification.from_pretrained(CLASSIFIER_PATH)
35
- tokenizer_c = AutoTokenizer.from_pretrained(CLASSIFIER_PATH)
36
-
37
- # === Analyse émotion ===
38
- analyzer = SentimentIntensityAnalyzer()
39
- GOEMOTIONS_LABELS = ["admiration","anger","approval","autre","curiosity",
40
- "disapproval","gratitude","joy","love","neutral","sadness"]
41
- UNACCEPTABLE_EMOTIONS = {"anger"}
42
 
43
  def detect_language(text):
44
- try:
45
- detected_lang = detect(text)
46
- return detected_lang if detected_lang in ["fr", "en", "ar"] else "en"
47
- except:
48
- return "en"
49
 
50
- def search_duckduckgo(query, max_results=3):
 
 
51
  try:
52
- search_results = list(DDGS().text(query, max_results=max_results))
53
- return [result["body"] for result in search_results if "body" in result] or ["Pas trouvé."]
54
- except Exception as e:
55
- return [f"Erreur recherche : {str(e)}"]
56
-
57
- def generate_response(user_input):
58
- prompt = f"User: {user_input}\nBot:"
59
- inputs = tokenizer(prompt, return_tensors="pt")
60
- output = model.generate(
61
- input_ids=inputs["input_ids"],
62
- max_new_tokens=150,
63
- pad_token_id=tokenizer.eos_token_id,
64
- eos_token_id=tokenizer.eos_token_id,
65
- do_sample=True,
66
- temperature=0.7,
67
- top_k=50,
68
- top_p=0.9,
69
- repetition_penalty=1.2
70
- )
71
- generated_text = tokenizer.decode(output[0], skip_special_tokens=True)
72
- return clean_response(generated_text.split("Bot:")[-1].strip())
73
-
74
- def classify_emotion(text):
75
- sentiment_scores = analyzer.polarity_scores(text)
76
- compound = sentiment_scores['compound'] * 100
77
- inputs = bert_tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=256)
78
- with torch.no_grad():
79
- logits = bert_model(**inputs).logits
80
- probs = F.softmax(logits, dim=-1).squeeze().cpu().numpy()
81
- top_emotion_index = probs.argmax()
82
- top_emotion = GOEMOTIONS_LABELS[top_emotion_index]
83
- return compound, top_emotion in UNACCEPTABLE_EMOTIONS, top_emotion
84
 
85
  def predict(text):
86
- inputs = tokenizer_c(text, return_tensors="pt", padding=True, truncation=True, max_length=512)
87
- with torch.no_grad():
88
- outputs = model_c(**inputs)
89
- logits = outputs.logits
90
- return "recherche" if torch.argmax(logits, dim=-1).item() == 1 else "GPT"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  def classify_and_respond(text):
 
93
  original_lang = detect_language(text)
94
  text_en = translate(text, "en")
95
 
 
96
  category = predict(text_en)
 
 
97
  if category == "recherche":
 
98
  response = search_duckduckgo(text_en)
99
- return "\n".join([translate(r, original_lang) for r in response])
 
 
 
 
 
100
 
101
  compound, is_unacceptable, emotion = classify_emotion(text_en)
102
- if is_unacceptable and abs(compound) > 50:
103
- return translate("Je ressens beaucoup de tension dans votre message.", original_lang)
104
 
 
 
 
 
 
 
 
 
 
 
105
  gpt_response = generate_response(text_en)
106
- return translate(gpt_response, original_lang)
 
 
 
 
 
 
 
107
 
108
- # === Interface Gradio ===
109
  iface = gr.Interface(
110
  fn=classify_and_respond,
111
  inputs=gr.Textbox(lines=2, placeholder="Écris ton message..."),
112
- outputs="text",
113
  title="PsyBot",
114
  description="Chatbot psychologue multilingue basé sur GPT + BERT + MiniBERT"
115
  )
 
1
  import gradio as gr
2
+ import random
3
+ from textblob import TextBlob
4
+
5
+ # ========= Fonctions utilitaires =========
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  def detect_language(text):
8
+ """Détecte la langue du texte"""
9
+ blob = TextBlob(text)
10
+ return blob.detect_language()
 
 
11
 
12
+ def translate(text, target_lang="en"):
13
+ """Traduit le texte vers target_lang"""
14
+ blob = TextBlob(text)
15
  try:
16
+ return str(blob.translate(to=target_lang))
17
+ except Exception:
18
+ return text # si la traduction échoue, on garde le texte original
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  def predict(text):
21
+ """Détection simple de l'intention (recherche ou discussion)"""
22
+ keywords = ["cherche", "recherche", "trouve", "information", "wikipedia", "google"]
23
+ if any(word in text.lower() for word in keywords):
24
+ return "recherche"
25
+ return "discussion"
26
+
27
+ def search_duckduckgo(query):
28
+ """Simule une recherche (à remplacer par vrai moteur si besoin)"""
29
+ return [f"Résultat fictif pour : {query}"]
30
+
31
+ def classify_emotion(text):
32
+ """Détection simple des émotions (fake, à remplacer par vrai modèle)"""
33
+ emotions = ["joy", "sadness", "anger", "fear", "neutral"]
34
+ emotion = random.choice(emotions)
35
+ compound = random.randint(-100, 100)
36
+ is_unacceptable = "!" in text or "stupide" in text.lower()
37
+ return compound, is_unacceptable, emotion
38
+
39
+ def generate_response(text):
40
+ """Réponse GPT fictive (à remplacer par ton modèle GPT)"""
41
+ responses = [
42
+ "Je comprends ce que tu ressens.",
43
+ "Peux-tu m’en dire plus ?",
44
+ "Ça a l’air difficile, je suis là pour t’écouter.",
45
+ "Merci de partager ça avec moi."
46
+ ]
47
+ return random.choice(responses)
48
+
49
+ # ========= Fonction principale =========
50
 
51
  def classify_and_respond(text):
52
+ """Pipeline complet : détection intention → émotion → réponse"""
53
  original_lang = detect_language(text)
54
  text_en = translate(text, "en")
55
 
56
+ steps = []
57
  category = predict(text_en)
58
+ steps.append("Intention détectée")
59
+
60
  if category == "recherche":
61
+ steps.append("Recherche externe")
62
  response = search_duckduckgo(text_en)
63
+ return {
64
+ "response": "\n".join([translate(r, original_lang) for r in response]),
65
+ "response_type": "recherche",
66
+ "emotions": None,
67
+ "steps": steps
68
+ }
69
 
70
  compound, is_unacceptable, emotion = classify_emotion(text_en)
71
+ steps.append(f"Émotion détectée : {emotion}")
 
72
 
73
+ if is_unacceptable and abs(compound) > 50:
74
+ steps.append("Message non acceptable")
75
+ return {
76
+ "response": translate("Je ressens beaucoup de tension dans votre message.", original_lang),
77
+ "response_type": "non acceptable",
78
+ "emotions": emotion,
79
+ "steps": steps
80
+ }
81
+
82
+ steps.append("Génération GPT")
83
  gpt_response = generate_response(text_en)
84
+ return {
85
+ "response": translate(gpt_response, original_lang),
86
+ "response_type": "gpt",
87
+ "emotions": emotion,
88
+ "steps": steps
89
+ }
90
+
91
+ # ========= Interface Gradio =========
92
 
 
93
  iface = gr.Interface(
94
  fn=classify_and_respond,
95
  inputs=gr.Textbox(lines=2, placeholder="Écris ton message..."),
96
+ outputs="json", # 🔴 renvoie un JSON structuré pour le frontend
97
  title="PsyBot",
98
  description="Chatbot psychologue multilingue basé sur GPT + BERT + MiniBERT"
99
  )