Spaces:
Running
Running
| import gradio as gr | |
| import re | |
| import emoji | |
| import spacy | |
| import torch | |
| from transformers import AutoModelForSequenceClassification, AutoTokenizer | |
| from collections import Counter | |
| # --- 1. CONFIGURACIÓN --- | |
| MODEL_ID = "c-armor/finetuned_emotions" | |
| DEVICE = "cpu" # Usamos CPU | |
| EMOTION_LABELS = ["alegria", "tristeza", "ira", "miedo", "sorpresa", "asco"] | |
| UMBRALES = { | |
| "alegria": 0.50, | |
| "tristeza": 0.50, | |
| "ira": 0.50, | |
| "miedo": 0.30, | |
| "sorpresa": 0.30, | |
| "asco": 0.30 # <--- Coincide con entrenamiento | |
| } | |
| # --- 2. CARGAR MODELOS (Se cargan UNA VEZ al iniciar el Space) --- | |
| print("Cargando modelo spaCy...") | |
| NLP = spacy.load("es_core_news_md") | |
| STOP_WORDS = NLP.Defaults.stop_words | |
| print("spaCy cargado y STOP_WORDS listas") | |
| print(f"Cargando modelo BETO desde {MODEL_ID}...") | |
| TOKENIZER = AutoTokenizer.from_pretrained("dccuchile/bert-base-spanish-wwm-cased", use_fast=False) | |
| MODEL = AutoModelForSequenceClassification.from_pretrained(MODEL_ID) | |
| MODEL.to(DEVICE) | |
| MODEL.eval() | |
| print(f"BETO cargado exitosamente en {DEVICE}") | |
| # --- 3. FUNCIONES DE PREPROCESAMIENTO--- | |
| def preprocesar_texto(texto: str) -> str: | |
| if not isinstance(texto, str): return "" | |
| texto = texto.lower() | |
| texto = emoji.demojize(texto, language="es") | |
| texto = re.sub(r"https://?://\S+|www\.\S+", "", texto) | |
| texto = re.sub(r"[^a-záéíóúüñ_.,!?¿¡]", " ", texto) | |
| texto = re.sub(r"\s{2,}", " ", texto).strip() | |
| return texto | |
| def lematizar_texto_para_lista(texto: str): | |
| """Lematiza el texto y devuelve una LISTA (para nube de palabras)""" | |
| with NLP.disable_pipes("parser", "ner"): | |
| doc = NLP(texto) | |
| return [token.lemma_ for token in doc if token.text.strip()] | |
| # --- 4. FUNCIÓN API 1: ANÁLISIS DE EMOCIONES --- | |
| def analizar_emociones(texto: str): | |
| if not texto or not isinstance(texto, str) or len(texto.strip()) < 3: | |
| return {"error": "texto_invalido"} | |
| try: | |
| texto_limpio = preprocesar_texto(texto) | |
| # Pasamos directo el texto_limpio al tokenizer | |
| inputs = TOKENIZER(texto_limpio, padding=True, truncation=True, max_length=128, return_tensors="pt").to(DEVICE) | |
| with torch.no_grad(): | |
| outputs = MODEL(**inputs) | |
| logits = outputs.logits | |
| probabilidades = torch.sigmoid(logits).cpu().numpy()[0] | |
| emociones_detectadas = [] | |
| probabilidades_dict = {} | |
| for i, emocion in enumerate(EMOTION_LABELS): | |
| prob = float(probabilidades[i]) | |
| umbral = UMBRALES[emocion] | |
| probabilidades_dict[emocion] = round(prob, 4) | |
| if prob >= umbral: | |
| emociones_detectadas.append(emocion) | |
| if not emociones_detectadas: | |
| emociones_detectadas = ["neutro"] | |
| return {"emociones": emociones_detectadas, "probabilidades": probabilidades_dict} | |
| except Exception as e: | |
| print(f"Error en predicción de emociones: {e}") | |
| return {"error": "error_prediccion"} | |
| # --- 5. FUNCIÓN API 2: FRECUENCIA DE PALABRAS --- | |
| def generar_frecuencia_palabras(texto: str): | |
| """Calcula las 50 palabras más frecuentes (devuelve una lista de listas)""" | |
| if not texto or not isinstance(texto, str) or not texto.strip(): | |
| return [] | |
| try: | |
| lemmas = lematizar_texto_para_lista(preprocesar_texto(texto)) | |
| # Usa las STOP_WORDS globales | |
| important_words = [lem for lem in lemmas if lem not in STOP_WORDS and lem.isalpha() and len(lem) > 2] | |
| word_counts = Counter(important_words) | |
| # Devuelve el formato que tu frontend espera (lista de [palabra, conteo]) | |
| return word_counts.most_common(50) | |
| except Exception as e: | |
| print(f"Error en frecuencia de palabras: {e}") | |
| return [] | |
| # --- 6. LANZAR AMBAS APIS USANDO GR.BLOCKS --- | |
| with gr.Blocks() as demo: | |
| # --- Interfaz/API para Emociones --- | |
| with gr.Tab("Análisis de Emociones"): | |
| gr.Interface( | |
| fn=analizar_emociones, | |
| inputs=gr.Textbox(lines=5, label="Texto a Analizar"), | |
| outputs="json", | |
| api_name="predict_emotions" # <-- API endpoint 1 | |
| ) | |
| # --- Interfaz/API para Frecuencia de Palabras --- | |
| with gr.Tab("Frecuencia de Palabras"): | |
| gr.Interface( | |
| fn=generar_frecuencia_palabras, | |
| inputs=gr.Textbox(lines=5, label="Texto completo"), | |
| outputs="json", | |
| api_name="predict_frequency" # <-- API endpoint 2 | |
| ) | |
| demo.launch() |