File size: 4,567 Bytes
500985a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import gradio as gr
import gymnasium as gym
from gymnasium import spaces
import numpy as np
import matplotlib.pyplot as plt
from stable_baselines3 import PPO

# --- 1. DEFINIMOS EL ENTORNO (Igual que en Colab) ---
class DataCenterEnv(gym.Env):
    def __init__(self):
        super(DataCenterEnv, self).__init__()
        self.action_space = spaces.Discrete(5)
        self.observation_space = spaces.Box(low=0, high=100, shape=(1,), dtype=np.float32)
        self.state = 20
        self.max_steps = 100
        self.current_step = 0
        self.temps = []
        self.energies = []

    def reset(self, seed=None, options=None):
        super().reset(seed=seed)
        self.state = 20 + np.random.rand()
        self.current_step = 0
        self.temps = [self.state]
        self.energies = []
        return np.array([self.state], dtype=np.float32), {}

    def step(self, action):
        # Usamos variables globales para simular la carga que el usuario elija en la web
        global USER_CPU_LOAD_MIN, USER_CPU_LOAD_MAX
        cpu_load = np.random.uniform(USER_CPU_LOAD_MIN, USER_CPU_LOAD_MAX)
        
        cooling_effect = action * 2.5  # Potencia industrial
        energy_cost = action ** 2
        
        self.state = self.state + cpu_load - cooling_effect
        self.state = np.clip(self.state, 10, 100)
        self.current_step += 1
        
        reward = 0
        if 37 <= self.state <= 60: reward += 5
        else: reward -= 2
        if self.state > 80: reward -= 50
        reward -= (energy_cost * 0.1)
        
        terminated = False
        if self.current_step >= self.max_steps: terminated = True
        
        self.temps.append(self.state)
        self.energies.append(energy_cost)
            
        return np.array([self.state], dtype=np.float32), reward, terminated, False, {}

# Variables globales para controlar la dificultad desde la web
USER_CPU_LOAD_MIN = 1
USER_CPU_LOAD_MAX = 4

# --- 2. FUNCIÓN DE SIMULACIÓN (Lo que hace la web) ---
def run_simulation(load_min, load_max):
    # Actualizamos las variables globales con lo que el usuario eligió
    global USER_CPU_LOAD_MIN, USER_CPU_LOAD_MAX
    USER_CPU_LOAD_MIN = load_min
    USER_CPU_LOAD_MAX = load_max

    # 1. Crear entorno y Cargar Modelo
    env = DataCenterEnv()
    
    # INTENTA CARGAR TU MODELO. Si no lo encuentra, usa uno aleatorio (para que no falle la demo)
    try:
        model = PPO.load("agente_aire_acondicionado.zip", env=env)
        msg = "✅ Modelo Inteligente Cargado Correctamente."
    except:
        model = None
        msg = "⚠️ ADVERTENCIA: No se encontró 'agente_aire_acondicionado.zip'. Usando acciones aleatorias."

    # 2. Correr la simulación
    obs, _ = env.reset()
    done = False
    
    while not done:
        if model:
            action, _ = model.predict(obs)
        else:
            action = env.action_space.sample() # Fallback aleatorio
            
        obs, reward, done, truncated, info = env.step(action)

    # 3. Generar Gráficos
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
    
    # Gráfico Temperatura
    ax1.plot(env.temps, color="red", label="Temperatura")
    ax1.axhline(y=37, color='green', linestyle='--', label="Mínimo (37°C)")
    ax1.axhline(y=60, color='green', linestyle='--', label="Máximo (60°C)")
    ax1.set_title("Control de Temperatura")
    ax1.set_ylabel("°C")
    ax1.set_ylim(10, 90)
    ax1.legend()
    ax1.grid(True)
    
    # Gráfico Energía
    ax2.plot(env.energies, color="blue", label="Energía")
    ax2.set_title("Consumo de Energía")
    ax2.set_ylabel("Watts")
    ax2.grid(True)
    
    plt.tight_layout()
    return fig, msg

# --- 3. INTERFAZ GRÁFICA (Gradio) ---
with gr.Blocks() as demo:
    gr.Markdown("# ❄️ AI Cooling System Optimization Agent")
    gr.Markdown("Este agente de Aprendizaje por Refuerzo (RL) controla el aire acondicionado de un servidor para ahorrar energía sin que se sobrecaliente.")
    
    with gr.Row():
        with gr.Column():
            gr.Markdown("### Configuración de Carga")
            s_min = gr.Slider(1, 10, value=1, label="Carga Mínima de CPU (Calor)")
            s_max = gr.Slider(1, 10, value=4, label="Carga Máxima de CPU (Calor)")
            btn = gr.Button("🚀 Ejecutar Simulación")
            status = gr.Textbox(label="Estado del Agente")
        
        with gr.Column():
            plot = gr.Plot(label="Resultados en Tiempo Real")

    btn.click(fn=run_simulation, inputs=[s_min, s_max], outputs=[plot, status])

# Lanzar la app
demo.launch()