File size: 4,885 Bytes
5bdc1a3
 
 
 
b16edf6
8ae2c7c
d39334c
 
17a8c89
562da15
 
cbf9cd3
562da15
d39334c
562da15
5bdc1a3
562da15
5bdc1a3
17a8c89
b16edf6
 
 
 
562da15
b16edf6
cbf9cd3
 
3f84dd6
 
04ef942
 
 
b16edf6
8fb66b6
 
975e0b0
04ef942
17a8c89
cbf9cd3
3f84dd6
 
562da15
 
 
5bdc1a3
 
 
 
17a8c89
562da15
 
 
 
17a8c89
 
562da15
17a8c89
 
 
562da15
 
3f84dd6
562da15
17a8c89
562da15
17a8c89
562da15
17a8c89
562da15
 
5bdc1a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
985d03e
562da15
 
 
 
 
 
5bdc1a3
562da15
3f84dd6
b6f8f41
8fb66b6
b6f8f41
562da15
 
bc8cb15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32087ce
985d03e
b6f8f41
bc8cb15
562da15
 
 
 
 
 
 
8ae2c7c
 
985d03e
b16edf6
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




import accelerate
import gradio as gr
import joblib
import numpy as np
import requests
import torch
import os
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from langchain.memory import ConversationBufferMemory

# Configuración del modelo de lenguaje
MODEL_NAME = "mistralai/Mistral-7B-Instruct-v0.3"
device = "cuda" if torch.cuda.is_available() else "cpu"
HF_TOKEN = os.getenv("HF_TOKEN")  # Obtiene el token de la variable de entorno

# Verificación de 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, token=HF_TOKEN)
bnb_config = BitsAndBytesConfig(load_in_8bit=True)  # Cargar en 8-bit para reducir memoria

model = AutoModelForCausalLM.from_pretrained(
    MODEL_NAME,
    torch_dtype=torch.float16,  # Usa menos RAM que float32
    low_cpu_mem_usage=True,  # Reduce uso de memoria en CPU
    device_map={"": "cpu"},
    token=HF_TOKEN
)





# Memoria conversacional
memory = ConversationBufferMemory()

# Cargar modelo de la colmena
modelo_path = "modelo_colmena.pkl"
if os.path.exists(modelo_path):
    modelo_colmena = joblib.load(modelo_path)
else:
    modelo_colmena = None

# 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 con autenticación."""
    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"][-1]  # Último registro
            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 filtrar_datos_por_pregunta(mensaje, datos):
    """Filtra los datos de la colmena según la pregunta del usuario."""
    if "temperatura" in mensaje:
        return f"🌡 Temperatura interior: {datos['temperaturaInterior']}°C, exterior: {datos['temperatura_exterior']}°C."
    elif "humedad" in mensaje:
        return f"💧 Humedad interior: {datos['humedadInterior']}%, exterior: {datos['humedad_exterior']}%."
    elif "co2" in mensaje:
        return f"🌿 CO2: {datos['co2']} ppm."
    elif "ventilador" in mensaje:
        estado = "ENCENDIDO" if int(datos['ver_ventilador']) == 1 else "APAGADO"
        return f"🔄 Ventilador: {estado}."
    elif "calefactor" in mensaje:
        estado = "ENCENDIDO" if int(datos['ver_calefactor']) == 1 else "APAGADO"
        return f"🔥 Calefactor: {estado}."
    elif "ultrasonido" in mensaje:
        estado = "ENCENDIDO" if int(datos['ver_ultrasonido']) == 1 else "APAGADO"
        return f"🔊 Ultrasonido: {estado}."
    else:
        return "🤖 No entiendo la pregunta. Pregunta sobre temperatura, humedad, CO2, ventilador, calefactor o ultrasonido."

def conversar_con_colmena(mensaje):
    """Genera una respuesta combinando el modelo de lenguaje con los datos de la colmena."""
    datos = obtener_datos_colmena()
    if "error" in datos:
        return datos["error"]
    
    datos_relevantes = filtrar_datos_por_pregunta(mensaje.lower(), datos)
    
    contexto = f"Datos actuales de la colmena: {datos_relevantes}\nUsuario: {mensaje}\nColmena:"
    inputs = tokenizer(contexto, return_tensors="pt").to(device)

    print(f"🔄 Enviando entrada al modelo: {contexto}")  # 👈 Agrega este print para ver el contexto en consola
    
    with torch.no_grad():
    output = model.generate(
        **inputs,
        max_length=150,  # Reduce el tamaño máximo para evitar que se quede colgado
        do_sample=True,   # Sampling activado para más variabilidad
        top_k=50,         # Controla la aleatoriedad para evitar salidas vacías
        temperature=0.7,  # Ajusta la creatividad de la respuesta
        pad_token_id=tokenizer.eos_token_id  # Evita errores de padding
    )  # ✅ Paréntesis correctamente cerrado

# Decodificar la salida del modelo
respuesta = tokenizer.decode(output[0], skip_special_tokens=True).strip()

# Imprimir la respuesta generada para depuración
print(f"✅ Respuesta generada por la IA: '{respuesta}'")  # 👈 Para ver si está vacío

# Manejo de respuestas vacías
if not respuesta:
    return "🤖 No pude generar una respuesta. Inténtalo de nuevo con otra pregunta."



iface = gr.Interface(
    fn=conversar_con_colmena,
    inputs="text",
    outputs="text",
    title="🐝 Chat con la Colmena",
    description="Habla con la colmena en tiempo real sobre su estado."
)

iface.launch()