jamalinu commited on
Commit
1c57f07
·
verified ·
1 Parent(s): d12c6f1

Update src/engine.py

Browse files
Files changed (1) hide show
  1. src/engine.py +132 -26
src/engine.py CHANGED
@@ -1,42 +1,148 @@
1
  import spacy
2
  import nltk
 
3
  from nltk.sentiment.vader import SentimentIntensityAnalyzer
4
- from spacy.cli import download
5
 
6
  class DeepPragmaEngine:
 
 
 
 
 
 
 
 
 
7
  def __init__(self):
8
- # Configuración de NLTK
 
9
  try:
10
- nltk.data.find('sentiment/vader_lexicon.zip')
11
  except LookupError:
12
- nltk.download('vader_lexicon')
13
-
14
- # Configuración de SpaCy con autodescarga
15
- model_name = "en_core_web_sm"
 
 
 
16
  try:
17
- self.nlp = spacy.load(model_name)
18
  except OSError:
19
- print(f"Modelo {model_name} no encontrado. Descargando...")
20
- download(model_name)
21
- self.nlp = spacy.load(model_name)
22
-
 
 
23
  self.sia = SentimentIntensityAnalyzer()
24
- self.terminos_odio = ["stupid", "useless", "disease", "parasite"]
25
 
26
- def analizar(self, texto):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  doc = self.nlp(texto)
28
- score = self.sia.polarity_scores(texto)
29
-
30
- ataque = False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  for token in doc:
 
 
32
  if token.dep_ == "nsubj" and token.head.lemma_ == "be":
 
33
  for child in token.head.children:
34
- if child.dep_ in ["acomp", "attr"] and child.text.lower() in self.terminos_odio:
35
- ataque = True
36
-
37
- es_ironico = (score['pos'] > 0.3) and any(w in texto.lower() for w in ["always", "oh", "sure"])
38
-
39
- if ataque and es_ironico: return "Sarcastic Hate Speech"
40
- if ataque: return "Direct Hate Speech"
41
- if es_ironico: return "Sarcastic/Ironic (Non-Hateful)"
42
- return "Neutral"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import spacy
2
  import nltk
3
+
4
  from nltk.sentiment.vader import SentimentIntensityAnalyzer
5
+
6
 
7
  class DeepPragmaEngine:
8
+ """
9
+ Motor local de clasificación pragmática.
10
+ Detecta:
11
+ - Hate Speech directo
12
+ - Hate Speech sarcástico
13
+ - Ironía no ofensiva
14
+ - Neutral
15
+ """
16
+
17
  def __init__(self):
18
+
19
+ # Comprobación de recursos NLTK
20
  try:
21
+ nltk.data.find("sentiment/vader_lexicon")
22
  except LookupError:
23
+ raise RuntimeError(
24
+ "No se encontró vader_lexicon. "
25
+ "Instálalo durante el build con: "
26
+ "python -c \"import nltk; nltk.download('vader_lexicon')\""
27
+ )
28
+
29
+ # Carga del modelo spaCy
30
  try:
31
+ self.nlp = spacy.load("en_core_web_sm")
32
  except OSError:
33
+ raise RuntimeError(
34
+ "No se encontró el modelo en_core_web_sm. "
35
+ "Instálalo durante el build con: "
36
+ "python -m spacy download en_core_web_sm"
37
+ )
38
+
39
  self.sia = SentimentIntensityAnalyzer()
 
40
 
41
+ # Lista inicial de términos ofensivos
42
+ self.terminos_odio = {
43
+ "stupid",
44
+ "useless",
45
+ "disease",
46
+ "parasite"
47
+ }
48
+
49
+
50
+ def analizar(self, texto: str) -> str:
51
+ """
52
+ Analiza una frase y devuelve una categoría.
53
+ """
54
+
55
+ if not texto or not texto.strip():
56
+ return "Neutral"
57
+
58
+
59
+ texto = texto.strip()
60
+
61
  doc = self.nlp(texto)
62
+
63
+ sentimiento = self.sia.polarity_scores(texto)
64
+
65
+
66
+ ataque = self._detectar_ataque(doc)
67
+
68
+ ironia = self._detectar_ironia(
69
+ texto,
70
+ sentimiento
71
+ )
72
+
73
+
74
+ if ataque and ironia:
75
+ return "Sarcastic Hate Speech"
76
+
77
+ if ataque:
78
+ return "Direct Hate Speech"
79
+
80
+ if ironia:
81
+ return "Sarcastic/Ironic (Non-Hateful)"
82
+
83
+ return "Neutral"
84
+
85
+
86
+
87
+ def _detectar_ataque(self, doc) -> bool:
88
+ """
89
+ Detecta estructuras del tipo:
90
+
91
+ "They are parasites"
92
+ "You are useless"
93
+ """
94
+
95
  for token in doc:
96
+
97
+ # sujeto + verbo ser
98
  if token.dep_ == "nsubj" and token.head.lemma_ == "be":
99
+
100
  for child in token.head.children:
101
+
102
+ if (
103
+ child.dep_ in ["acomp", "attr"]
104
+ and child.text.lower() in self.terminos_odio
105
+ ):
106
+ return True
107
+
108
+ return False
109
+
110
+
111
+
112
+ def _detectar_ironia(
113
+ self,
114
+ texto: str,
115
+ sentimiento: dict
116
+ ) -> bool:
117
+ """
118
+ Heurística simple de ironía.
119
+
120
+ Ejemplos:
121
+ "Oh sure, they are always perfect"
122
+ """
123
+
124
+ marcadores_ironia = [
125
+ "always",
126
+ "oh",
127
+ "sure",
128
+ "yeah",
129
+ "right",
130
+ "obviously"
131
+ ]
132
+
133
+
134
+ tiene_marcador = any(
135
+ palabra in texto.lower()
136
+ for palabra in marcadores_ironia
137
+ )
138
+
139
+
140
+ sentimiento_positivo = (
141
+ sentimiento["pos"] > 0.3
142
+ )
143
+
144
+
145
+ return (
146
+ tiene_marcador
147
+ and sentimiento_positivo
148
+ )