Files
Effi/scripts/comfyui-unload-monitor.py
T
Folzo 7439033edd fix: Corriger script ComfyUI monitor et service systemd
- Corriger extraction VRAM via API correcte
- Ajouter gestion signaux propre
- Ajouter TimeoutStopSec pour arrêt propre
- Ajouter service restart Beszel au réveil
2026-04-12 12:08:27 +02:00

153 lines
5.4 KiB
Python
Executable File

#!/usr/bin/env python3
# ComfyUI Model Unloader - Décharge les modèles après inactivité
# Usage: python3 comfyui-unload-monitor.py [--interval 60] [--timeout 300]
import requests
import time
import argparse
import logging
import sys
import signal
import os
from datetime import datetime
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
DEFAULT_INTERVAL = 60
DEFAULT_TIMEOUT = 300
COMFYUI_URL = "http://localhost:8188"
class ComfyUIUnloadMonitor:
def __init__(self, interval=DEFAULT_INTERVAL, timeout=DEFAULT_TIMEOUT):
self.interval = interval
self.timeout = timeout
self.last_activity = datetime.now()
self.running = True
self.models_loaded = False
self.unload_timer = None
signal.signal(signal.SIGINT, self.signal_handler)
signal.signal(signal.SIGTERM, self.signal_handler)
def signal_handler(self, signum, frame):
logger.info("Signal reçu, arrêt propre...")
self.running = False
sys.exit(0)
def get_vram_usage(self):
try:
response = requests.get(f"{COMFYUI_URL}/system_stats", timeout=10)
if response.status_code == 200:
data = response.json()
devices = data.get("devices", [])
if devices:
vram_total = devices[0].get("vram_total", 0)
vram_free = devices[0].get("vram_free", 0)
vram_used = vram_total - vram_free
return vram_used, vram_total
except Exception as e:
logger.warning(f"Erreur获取VRAM: {e}")
return None, None
def check_recent_history(self):
try:
response = requests.get(f"{COMFYU_URL}/history?max_items=1", timeout=10)
if response.status_code == 200:
history = response.json()
if history:
last_item = list(history.values())[0]
if "last_node" in last_item:
prompt_time = last_item.get("prompt_time", 0)
if prompt_time:
last_run = datetime.fromtimestamp(prompt_time)
self.last_activity = last_run
return True
except Exception as e:
pass
return False
def unload_models(self):
logger.info("🔄 Déchargement des modèles ComfyUI...")
try:
response = requests.post(
f"{COMFYUI_URL}/internal/model/unload",
timeout=30
)
if response.status_code in [200, 404]:
logger.info("✅ Déchargement envoyé")
return True
except Exception as e:
logger.warning(f"Erreur déchargement: {e}")
try:
workflow = {
"3": {
"inputs": {"value": "unload"},
"class_type": "UnloadAllModelsNode"
}
}
response = requests.post(
f"{COMFYUI_URL}/prompt",
json={"prompt": workflow},
timeout=30
)
if response.status_code == 200:
logger.info("✅ Workflow déchargement envoyé")
return True
except Exception as e:
logger.error(f"Erreur workflow: {e}")
return False
def run(self):
logger.info(f"🚀 ComfyUI Unload Monitor démarré")
logger.info(f" Vérification: {self.interval}s | Timeout: {self.timeout}s")
while self.running:
try:
vram_used, vram_total = self.get_vram_usage()
if vram_used is not None and vram_total is not None:
vram_gb = vram_used / (1024**3)
vram_total_gb = vram_total / (1024**3)
vram_percent = (vram_used / vram_total) * 100 if vram_total > 0 else 0
self.check_recent_history()
idle_seconds = (datetime.now() - self.last_activity).total_seconds()
logger.info(f"VRAM: {vram_gb:.2f}GB/{vram_total_gb:.2f}GB ({vram_percent:.1f}%) | Idle: {idle_seconds:.0f}s")
if vram_percent > 5 and idle_seconds >= self.timeout:
logger.info(f"⏰ Inactivité ({idle_seconds:.0f}s >= {self.timeout}s) - Déchargement...")
self.unload_models()
self.last_activity = datetime.now()
time.sleep(self.interval)
except Exception as e:
logger.error(f"Erreur: {e}")
time.sleep(self.interval)
logger.info("👋 Monitor arrêté")
sys.exit(0)
def main():
parser = argparse.ArgumentParser(description="ComfyUI Model Unload Monitor")
parser.add_argument("--interval", type=int, default=DEFAULT_INTERVAL)
parser.add_argument("--timeout", type=int, default=DEFAULT_TIMEOUT)
parser.add_argument("--debug", action="store_true")
args = parser.parse_args()
if args.debug:
logging.getLogger().setLevel(logging.DEBUG)
monitor = ComfyUIUnloadMonitor(interval=args.interval, timeout=args.timeout)
monitor.run()
if __name__ == "__main__":
main()