Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,133 +1,95 @@
|
|
1 |
import gradio as gr
|
2 |
import joblib
|
3 |
import numpy as np
|
4 |
-
import os
|
5 |
import requests
|
6 |
-
import
|
7 |
-
import
|
8 |
-
from
|
9 |
-
from
|
10 |
|
11 |
-
# Configuración
|
12 |
-
|
13 |
-
|
14 |
-
PASSWORD = "velutina"
|
15 |
|
16 |
-
|
17 |
-
|
|
|
18 |
|
19 |
-
#
|
|
|
|
|
|
|
|
|
20 |
if os.path.exists(modelo_path):
|
21 |
-
|
22 |
else:
|
23 |
-
|
24 |
|
25 |
-
#
|
26 |
-
|
27 |
-
|
|
|
28 |
|
29 |
def obtener_datos_colmena():
|
30 |
-
"""Obtiene los datos de Node-RED con autenticación."""
|
31 |
try:
|
32 |
respuesta = requests.get(NODE_RED_URL, auth=(USERNAME, PASSWORD), timeout=5)
|
33 |
if respuesta.status_code == 200:
|
34 |
-
|
|
|
|
|
|
|
35 |
else:
|
36 |
-
|
37 |
-
return None
|
38 |
except Exception as e:
|
39 |
-
|
40 |
-
return None
|
41 |
-
|
42 |
-
def entrenar_nuevo_modelo(datos):
|
43 |
-
"""Entrena un nuevo modelo con los datos recibidos."""
|
44 |
-
global modelo
|
45 |
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
""
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
ultimo_registro = datos["data"][-1]
|
64 |
-
if "timestamp" in ultimo_registro:
|
65 |
-
timestamp_actual = ultimo_registro["timestamp"]
|
66 |
-
if timestamp_actual != ultimo_timestamp:
|
67 |
-
print(f"📌 Nuevos datos detectados: {timestamp_actual}")
|
68 |
-
entrenar_nuevo_modelo(ultimo_registro)
|
69 |
-
datos_recientes = ultimo_registro
|
70 |
-
ultimo_timestamp = timestamp_actual
|
71 |
-
else:
|
72 |
-
print("⏳ No hay datos nuevos, esperando la próxima consulta...")
|
73 |
-
else:
|
74 |
-
print(f"❌ No se encontró 'timestamp' en el último registro: {ultimo_registro}")
|
75 |
-
else:
|
76 |
-
print("❌ No hay datos válidos en la API de Node-RED.")
|
77 |
-
time.sleep(3600)
|
78 |
-
|
79 |
-
def predecir(temp, humedad, peso, co2, vco, frecuencia, voltaje, temp_ext, humedad_ext, ver_tempSelect):
|
80 |
-
valores = [temp, humedad, peso, co2, vco, frecuencia, voltaje, temp_ext, humedad_ext, ver_tempSelect]
|
81 |
-
valores_limpios = [0 if v is None or np.isnan(v) else v for v in valores]
|
82 |
-
entrada = np.array([valores_limpios])
|
83 |
-
prediccion = modelo.predict(entrada)[0]
|
84 |
-
mensaje = f"🔹 Ultrasonido: {'ENCENDER' if prediccion[0] == 1 else 'APAGAR'}\n"
|
85 |
-
mensaje += f"🔹 Calefactor: {'ENCENDER' if prediccion[1] == 1 else 'APAGAR'}\n"
|
86 |
-
mensaje += f"🔹 Ventilador: {'ENCENDER' if prediccion[2] == 1 else 'APAGAR'}"
|
87 |
-
return mensaje
|
88 |
-
|
89 |
-
def chat_ia(mensaje_usuario):
|
90 |
-
"""Responde preguntas sobre la colmena basándose en los últimos datos disponibles."""
|
91 |
-
global datos_recientes
|
92 |
-
if datos_recientes is None:
|
93 |
-
return "No hay datos recientes disponibles. Esperando actualización de Node-RED."
|
94 |
-
|
95 |
-
mensaje_usuario = mensaje_usuario.lower()
|
96 |
-
if "temperatura" in mensaje_usuario:
|
97 |
-
return f"🌡 La temperatura interior es {datos_recientes['temperaturaInterior']}°C y la exterior {datos_recientes['temperatura_exterior']}°C."
|
98 |
-
elif "humedad" in mensaje_usuario:
|
99 |
-
return f"💧 La humedad interior es {datos_recientes['humedadInterior']}% y la exterior {datos_recientes['humedad_exterior']}%."
|
100 |
-
elif "co2" in mensaje_usuario:
|
101 |
-
return f"🌿 El nivel de CO2 es {datos_recientes['co2']} ppm."
|
102 |
-
elif "ventilador" in mensaje_usuario:
|
103 |
-
estado = "ENCENDIDO" if int(datos_recientes['ver_ventilador']) == 1 else "APAGADO"
|
104 |
-
return f"🔄 El ventilador está {estado}."
|
105 |
-
elif "calefactor" in mensaje_usuario:
|
106 |
-
estado = "ENCENDIDO" if int(datos_recientes['ver_calefactor']) == 1 else "APAGADO"
|
107 |
-
return f"🔥 El calefactor está {estado}."
|
108 |
-
elif "ultrasonido" in mensaje_usuario:
|
109 |
-
estado = "ENCENDIDO" if int(datos_recientes['ver_ultrasonido']) == 1 else "APAGADO"
|
110 |
-
return f"🔊 El ultrasonido está {estado}."
|
111 |
else:
|
112 |
return "🤖 No entiendo la pregunta. Puedes preguntar sobre temperatura, humedad, CO2, ventilador, calefactor o ultrasonido."
|
113 |
|
114 |
-
|
115 |
-
|
116 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
gr.Interface(fn=chat_ia,
|
126 |
-
inputs="text",
|
127 |
-
outputs="text",
|
128 |
-
title="💬 Chat con la IA de la Colmena",
|
129 |
-
description="Haz preguntas sobre el estado de la colmena y la IA responderá basándose en los datos más recientes.")
|
130 |
-
], title="🐝 Colmena Inteligente")
|
131 |
|
132 |
iface.launch()
|
133 |
|
|
|
1 |
import gradio as gr
|
2 |
import joblib
|
3 |
import numpy as np
|
|
|
4 |
import requests
|
5 |
+
import torch
|
6 |
+
import os
|
7 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
8 |
+
from langchain.memory import ConversationBufferMemory
|
9 |
|
10 |
+
# Configuración del modelo de lenguaje
|
11 |
+
MODEL_NAME = "mistralai/Mistral-7B-Instruct" # Puedes cambiar a LLaMA 2
|
12 |
+
device = "cuda" if torch.cuda.is_available() else "cpu"
|
|
|
13 |
|
14 |
+
print("🔄 Cargando modelo de lenguaje...")
|
15 |
+
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
|
16 |
+
model = AutoModelForCausalLM.from_pretrained(MODEL_NAME).to(device)
|
17 |
|
18 |
+
# Configuración de memoria conversacional con límite de contexto
|
19 |
+
memory = ConversationBufferMemory(max_human_messages=10, max_ai_messages=10)
|
20 |
+
|
21 |
+
# Cargar modelo de la colmena
|
22 |
+
modelo_path = "modelo_colmena.pkl"
|
23 |
if os.path.exists(modelo_path):
|
24 |
+
modelo_colmena = joblib.load(modelo_path)
|
25 |
else:
|
26 |
+
modelo_colmena = None
|
27 |
|
28 |
+
# API de Node-RED
|
29 |
+
NODE_RED_URL = "https://appairedecolmena.es/colmena1/datos"
|
30 |
+
USERNAME = "user"
|
31 |
+
PASSWORD = "velutina"
|
32 |
|
33 |
def obtener_datos_colmena():
|
34 |
+
"""Obtiene los datos más recientes de Node-RED con autenticación."""
|
35 |
try:
|
36 |
respuesta = requests.get(NODE_RED_URL, auth=(USERNAME, PASSWORD), timeout=5)
|
37 |
if respuesta.status_code == 200:
|
38 |
+
datos = respuesta.json()
|
39 |
+
if "data" in datos and isinstance(datos["data"], list) and datos["data"]:
|
40 |
+
return datos["data"][-1] # Devuelve solo el último registro
|
41 |
+
return {"error": "No hay datos recientes en Node-RED."}
|
42 |
else:
|
43 |
+
return {"error": f"Error en la API: {respuesta.status_code}"}
|
|
|
44 |
except Exception as e:
|
45 |
+
return {"error": str(e)}
|
|
|
|
|
|
|
|
|
|
|
46 |
|
47 |
+
def filtrar_datos_por_pregunta(mensaje, datos):
|
48 |
+
"""Filtra los datos de la colmena según la pregunta del usuario."""
|
49 |
+
if "temperatura" in mensaje:
|
50 |
+
return f"🌡 Temperatura interior: {datos['temperaturaInterior']}°C, exterior: {datos['temperatura_exterior']}°C."
|
51 |
+
elif "humedad" in mensaje:
|
52 |
+
return f"💧 Humedad interior: {datos['humedadInterior']}%, exterior: {datos['humedad_exterior']}%."
|
53 |
+
elif "co2" in mensaje:
|
54 |
+
return f"🌿 CO2: {datos['co2']} ppm."
|
55 |
+
elif "ventilador" in mensaje:
|
56 |
+
estado = "ENCENDIDO" if int(datos['ver_ventilador']) == 1 else "APAGADO"
|
57 |
+
return f"🔄 Ventilador: {estado}."
|
58 |
+
elif "calefactor" in mensaje:
|
59 |
+
estado = "ENCENDIDO" if int(datos['ver_calefactor']) == 1 else "APAGADO"
|
60 |
+
return f"🔥 Calefactor: {estado}."
|
61 |
+
elif "ultrasonido" in mensaje:
|
62 |
+
estado = "ENCENDIDO" if int(datos['ver_ultrasonido']) == 1 else "APAGADO"
|
63 |
+
return f"🔊 Ultrasonido: {estado}."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
else:
|
65 |
return "🤖 No entiendo la pregunta. Puedes preguntar sobre temperatura, humedad, CO2, ventilador, calefactor o ultrasonido."
|
66 |
|
67 |
+
def conversar_con_colmena(mensaje):
|
68 |
+
"""Genera una respuesta combinando el modelo de lenguaje con los datos de la colmena."""
|
69 |
+
datos = obtener_datos_colmena()
|
70 |
+
if "error" in datos:
|
71 |
+
return datos["error"]
|
72 |
+
|
73 |
+
datos_relevantes = filtrar_datos_por_pregunta(mensaje.lower(), datos)
|
74 |
+
|
75 |
+
contexto = f"Datos actuales de la colmena: {datos_relevantes}\nUsuario: {mensaje}\nColmena:"
|
76 |
+
inputs = tokenizer(contexto, return_tensors="pt").to(device)
|
77 |
+
|
78 |
+
with torch.no_grad():
|
79 |
+
output = model.generate(**inputs, max_length=150) # Limitar longitud
|
80 |
+
|
81 |
+
respuesta = tokenizer.decode(output[0], skip_special_tokens=True)
|
82 |
+
memory.save_context({"input": mensaje}, {"output": respuesta})
|
83 |
+
|
84 |
+
return respuesta
|
85 |
|
86 |
+
iface = gr.Interface(
|
87 |
+
fn=conversar_con_colmena,
|
88 |
+
inputs="text",
|
89 |
+
outputs="text",
|
90 |
+
title="🐝 Chat con la Colmena",
|
91 |
+
description="Habla con la colmena en tiempo real sobre su estado."
|
92 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
iface.launch()
|
95 |
|