IAColmenas / app.py
XA-vito's picture
Update app.py
01f2b02 verified
raw
history blame
5.12 kB
import accelerate
import gradio as gr
import joblib
import numpy as np
import requests
import torch
import os
import json
import matplotlib.pyplot as plt
from io import BytesIO
from transformers import AutoModelForCausalLM, AutoTokenizer
# Configuración del modelo de lenguaje
MODEL_NAME = "PlanTL-GOB-ES/roberta-base-bne"
device = "cuda" if torch.cuda.is_available() else "cpu"
HF_TOKEN = os.getenv("HF_TOKEN")
if not HF_TOKEN:
raise ValueError("❌ ERROR: No se encontró HF_TOKEN. Asegúrate de definirlo en las variables de entorno.")
print("🔄 Cargando modelo de lenguaje...")
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
model = AutoModelForCausalLM.from_pretrained(MODEL_NAME).to(device)
# API de Node-RED
NODE_RED_URL = "https://appairedecolmena.es/colmena1/datos"
USERNAME = "user"
PASSWORD = "velutina"
def obtener_datos_colmena():
"""Obtiene los datos más recientes de Node-RED."""
try:
respuesta = requests.get(NODE_RED_URL, auth=(USERNAME, PASSWORD), timeout=5)
if respuesta.status_code == 200:
datos = respuesta.json()
if "data" in datos and isinstance(datos["data"], list) and datos["data"]:
return datos["data"]
return {"error": "No hay datos recientes en Node-RED."}
else:
return {"error": f"Error en la API: {respuesta.status_code}"}
except Exception as e:
return {"error": str(e)}
def analizar_tendencia(datos, variable):
"""Analiza la tendencia de una variable específica."""
valores = [float(d[variable]) for d in datos if variable in d]
timestamps = [d["timestamp"] for d in datos if variable in d]
promedio = np.mean(valores)
maximo = np.max(valores)
minimo = np.min(valores)
respuesta = f"📊 **Análisis de {variable}:**\n"
respuesta += f"- Promedio: {promedio:.2f}\n"
respuesta += f"- Máximo: {maximo:.2f}\n"
respuesta += f"- Mínimo: {minimo:.2f}\n"
return respuesta, valores, timestamps
def generar_grafico(valores, timestamps, variable):
"""Genera un gráfico de la variable analizada."""
plt.figure(figsize=(10, 5))
plt.plot(timestamps, valores, marker='o', linestyle='-')
plt.xlabel("Tiempo")
plt.ylabel(variable)
plt.title(f"Tendencia de {variable}")
plt.xticks(rotation=45)
plt.grid()
buf = BytesIO()
plt.savefig(buf, format="png")
buf.seek(0)
return buf
def interpretar_instruccion(mensaje, datos):
"""Interpreta la consulta del usuario y ejecuta el análisis solicitado."""
mensaje = mensaje.lower()
# Ampliamos el mapeo con más sinónimos
variable_map = {
"temperatura": "temperaturaInterior",
"calor": "temperaturaInterior",
"frío": "temperaturaInterior",
"humedad": "humedadInterior",
"seco": "humedadInterior",
"co2": "co2",
"carbono": "co2",
"peso": "peso",
"colmena": "peso",
"ventilación": "ver_ventilador",
"ventilador": "ver_ventilador",
"calefactor": "ver_calefactor",
"vco": "vco",
"frecuencia": "frecuencia"
}
# Buscar la variable en el mensaje del usuario
for key, var in variable_map.items():
if key in mensaje:
respuesta, valores, timestamps = analizar_tendencia(datos, var)
grafico = generar_grafico(valores, timestamps, var)
return respuesta, grafico
# Si no encuentra una coincidencia, usa el modelo de lenguaje para interpretar la consulta
print("🤖 No se detectó una variable directamente. Usando IA para interpretar...")
contexto = f"Usuario: {mensaje}\nColmena:"
inputs = tokenizer(contexto, return_tensors="pt").to(device)
with torch.no_grad():
output = model.generate(
**inputs,
max_length=150,
do_sample=True,
top_k=50,
temperature=0.7,
pad_token_id=tokenizer.eos_token_id
)
respuesta_ia = tokenizer.decode(output[0], skip_special_tokens=True).strip()
return respuesta_ia, None # Si la IA responde, no genera imagen
def conversar_con_colmena(mensaje):
"""Genera una respuesta combinando el modelo de lenguaje con análisis de datos."""
datos = obtener_datos_colmena()
if "error" in datos:
return datos["error"], None # Retorna un string y `None` para evitar error en la imagen
resultado = interpretar_instruccion(mensaje, datos)
if isinstance(resultado, tuple):
texto, grafico = resultado
if grafico:
# Convierte BytesIO en una imagen para Gradio
from PIL import Image
img = Image.open(grafico)
return texto, img
else:
return texto, None
else:
return resultado, None # Asegurar que siempre haya dos valores de retorno
iface = gr.Interface(
fn=conversar_con_colmena,
inputs="text",
outputs=["text", "image"],
title="🐝 Chat con la Colmena",
description="Consulta el estado de la colmena y pide análisis de datos."
)
iface.launch()