|
|
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 |
|
|
|
|
|
|
|
|
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): |
|
|
|
|
|
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 |
|
|
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, {} |
|
|
|
|
|
|
|
|
USER_CPU_LOAD_MIN = 1 |
|
|
USER_CPU_LOAD_MAX = 4 |
|
|
|
|
|
|
|
|
def run_simulation(load_min, load_max): |
|
|
|
|
|
global USER_CPU_LOAD_MIN, USER_CPU_LOAD_MAX |
|
|
USER_CPU_LOAD_MIN = load_min |
|
|
USER_CPU_LOAD_MAX = load_max |
|
|
|
|
|
|
|
|
env = DataCenterEnv() |
|
|
|
|
|
|
|
|
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." |
|
|
|
|
|
|
|
|
obs, _ = env.reset() |
|
|
done = False |
|
|
|
|
|
while not done: |
|
|
if model: |
|
|
action, _ = model.predict(obs) |
|
|
else: |
|
|
action = env.action_space.sample() |
|
|
|
|
|
obs, reward, done, truncated, info = env.step(action) |
|
|
|
|
|
|
|
|
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5)) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
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]) |
|
|
|
|
|
|
|
|
demo.launch() |