iagofp commited on
Commit
469eaab
·
1 Parent(s): dcecd37

Uso API de HF para aligerar carga

Browse files
backend/services/analisis_sentimientos.py CHANGED
@@ -1,9 +1,11 @@
1
  """
2
  Este archivo contiene la logica del analisis de sentimientos de los textos introducidos por los usuarios.
3
- Carga el modelo pysentimiento/robertuito-emotion-analysis localmente via transformers.
4
  """
5
 
6
- from config import EMOTION_MAP, NEGATIVE_EMOTIONS, POSITIVE_EMOTIONS, HF_EMOTION_MODEL
 
 
7
 
8
 
9
  AROUSAL_BY_MODEL_LABEL = {
@@ -55,9 +57,38 @@ def mapeo_emocion_valencia(emocion: str) -> str:
55
 
56
  _pipeline_emociones = None
57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
  def crear_clasificador_emociones():
60
- """Carga el pipeline de emociones de pysentimiento (se descarga la primera vez)."""
 
 
 
 
 
61
  global _pipeline_emociones
62
  if _pipeline_emociones is None:
63
  try:
@@ -67,32 +98,35 @@ def crear_clasificador_emociones():
67
  model=HF_EMOTION_MODEL,
68
  top_k=None,
69
  )
 
70
  except Exception as exc:
71
- print(f"Aviso: no se pudo cargar el modelo de emociones ({exc}). Se usara neutral.")
72
- _pipeline_emociones = None
73
  return _pipeline_emociones
74
 
75
 
76
  def analizar_texto(modelo, texto: str) -> tuple[list[dict], str, str]:
77
  """
78
- Analiza un texto usando el pipeline local de transformers.
 
79
 
80
  Returns:
81
  - resultado: lista de {"label": ..., "score": ...} ordenada de mayor a menor.
82
  - emocion_dominante: emocion con mayor score en español.
83
  - valencia: "positivo", "negativo" o "neutro".
84
  """
85
- clf = modelo if modelo is not None else crear_clasificador_emociones()
86
 
87
- try:
88
- if clf is not None:
89
- raw = clf(texto)[0]
90
- resultado = sorted(raw, key=lambda x: x["score"], reverse=True)
91
- else:
 
 
 
 
 
92
  resultado = [{"label": "others", "score": 1.0}]
93
- except Exception as exc:
94
- print(f"Aviso: fallo analisis de emociones ({exc}). Se usa neutral.")
95
- resultado = [{"label": "others", "score": 1.0}]
96
 
97
  dominant_model = resultado[0]["label"] if resultado else "others"
98
  dominant_es = EMOTION_MAP.get(dominant_model, "neutral")
 
1
  """
2
  Este archivo contiene la logica del analisis de sentimientos de los textos introducidos por los usuarios.
3
+ Intenta usar la Inference API de HuggingFace; si falla, carga el modelo localmente via transformers.
4
  """
5
 
6
+ import requests as http_requests
7
+
8
+ from config import EMOTION_MAP, NEGATIVE_EMOTIONS, POSITIVE_EMOTIONS, HF_EMOTION_MODEL, HF_TOKEN
9
 
10
 
11
  AROUSAL_BY_MODEL_LABEL = {
 
57
 
58
  _pipeline_emociones = None
59
 
60
+ _HF_INFERENCE_API_URL = f"https://router.huggingface.co/hf-inference/models/{HF_EMOTION_MODEL}"
61
+
62
+
63
+ def _analizar_via_api(texto: str) -> list[dict] | None:
64
+ """Llama a la Inference API de HuggingFace. Devuelve la lista de scores o None si falla."""
65
+ if not HF_TOKEN:
66
+ return None
67
+ try:
68
+ res = http_requests.post(
69
+ _HF_INFERENCE_API_URL,
70
+ headers={"Authorization": f"Bearer {HF_TOKEN}"},
71
+ json={"inputs": texto},
72
+ timeout=15,
73
+ )
74
+ res.raise_for_status()
75
+ data = res.json()
76
+ # La API devuelve [[{label, score}, ...]] para clasificacion
77
+ raw = data[0] if isinstance(data, list) and data and isinstance(data[0], list) else data
78
+ if isinstance(raw, list) and raw and "label" in raw[0]:
79
+ return sorted(raw, key=lambda x: x["score"], reverse=True)
80
+ except Exception as exc:
81
+ print(f"Aviso: fallo Inference API de emociones ({exc}). Se prueba modelo local.")
82
+ return None
83
+
84
 
85
  def crear_clasificador_emociones():
86
+ """Devuelve None — la carga local se hace bajo demanda en analizar_texto si la API falla."""
87
+ return None
88
+
89
+
90
+ def _obtener_pipeline_local():
91
+ """Carga el pipeline local de transformers la primera vez que se necesita."""
92
  global _pipeline_emociones
93
  if _pipeline_emociones is None:
94
  try:
 
98
  model=HF_EMOTION_MODEL,
99
  top_k=None,
100
  )
101
+ print("Modelo de emociones cargado localmente.")
102
  except Exception as exc:
103
+ print(f"Aviso: no se pudo cargar el modelo local de emociones ({exc}). Se usara neutral.")
 
104
  return _pipeline_emociones
105
 
106
 
107
  def analizar_texto(modelo, texto: str) -> tuple[list[dict], str, str]:
108
  """
109
+ Analiza un texto. Primero intenta la Inference API de HuggingFace;
110
+ si falla, usa el modelo local via transformers como fallback.
111
 
112
  Returns:
113
  - resultado: lista de {"label": ..., "score": ...} ordenada de mayor a menor.
114
  - emocion_dominante: emocion con mayor score en español.
115
  - valencia: "positivo", "negativo" o "neutro".
116
  """
117
+ resultado = _analizar_via_api(texto)
118
 
119
+ if resultado is None:
120
+ clf = modelo if modelo is not None else _obtener_pipeline_local()
121
+ try:
122
+ if clf is not None:
123
+ raw = clf(texto)[0]
124
+ resultado = sorted(raw, key=lambda x: x["score"], reverse=True)
125
+ else:
126
+ resultado = [{"label": "others", "score": 1.0}]
127
+ except Exception as exc:
128
+ print(f"Aviso: fallo analisis de emociones local ({exc}). Se usa neutral.")
129
  resultado = [{"label": "others", "score": 1.0}]
 
 
 
130
 
131
  dominant_model = resultado[0]["label"] if resultado else "others"
132
  dominant_es = EMOTION_MAP.get(dominant_model, "neutral")
requirements.txt CHANGED
@@ -1,27 +1,5 @@
1
- # Backend (API)
2
- Flask==3.0.2
3
- flask-cors==4.0.0
4
- requests==2.31.0
5
- python-dotenv==1.0.0
6
-
7
- # Modelo de emociones local (robertuito)
8
- transformers>=4.40.0
9
- torch>=2.1.0
10
-
11
- #Seguridad
12
- werkzeug>=2.3.0
13
-
14
- # Usadas en los Jupyter Notebooks
15
- deep-translator==1.11.4
16
- nltk==3.8.1
17
- textblob==0.17.1
18
- datasets==2.14.6
19
- jupyter==1.0.0
20
- ipykernel==6.27.1
21
-
22
- # Analisis de datos y visualización
23
- pandas==2.1.4
24
- numpy==1.24.3
25
- matplotlib==3.8.3
26
- seaborn==0.13.1
27
-
 
1
+ flask>=3.0.0
2
+ flask-cors>=4.0.0
3
+ requests>=2.31.0
4
+ werkzeug>=3.1.0
5
+ python-dotenv>=1.0.0