File size: 5,122 Bytes
b16edf6
8ae2c7c
d39334c
 
17a8c89
562da15
 
d220394
 
 
33c462c
d39334c
562da15
81aa1d5
562da15
d220394
17a8c89
b16edf6
 
 
562da15
d220394
 
562da15
 
 
 
 
17a8c89
 
d220394
17a8c89
 
 
562da15
 
d220394
562da15
17a8c89
562da15
17a8c89
562da15
17a8c89
d220394
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
562da15
d220394
 
 
 
 
 
 
 
3d5efae
4ba974f
d220394
 
4ba974f
 
d220394
4ba974f
d220394
4ba974f
 
 
 
 
 
 
 
d220394
562da15
4ba974f
d220394
 
 
 
 
562da15
4ba974f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
caa40b5
d220394
 
 
 
01f2b02
 
d220394
 
 
01f2b02
 
 
 
 
 
 
d220394
01f2b02
 
3e8e0e4
bc8cb15
562da15
 
 
d220394
562da15
d220394
562da15
8ae2c7c
 
985d03e
b16edf6
2dcb03b
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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()