Public Access
124 lines
4.7 KiB
Python
124 lines
4.7 KiB
Python
import os
|
|
import json
|
|
import requests
|
|
import threading
|
|
import time
|
|
from modules.logger import log_event
|
|
|
|
CATALOGUE_FILE = "/DATA/AppData/MULTI-IA-AETHAS38/catalogue_dynamique.json"
|
|
LOCK_FILE = "/DATA/AppData/MULTI-IA-AETHAS38/updater_lock.txt"
|
|
|
|
def recuperer_modeles_hf():
|
|
"""
|
|
Récupère les modèles populaires de Hugging Face (Texte, Image, Vidéo).
|
|
Les identifiants sont préfixés par 'huggingface/' pour le routage Multi-IA.
|
|
"""
|
|
api_key = os.getenv("HUGGINGFACE_API_KEY")
|
|
headers = {"Authorization": f"Bearer {api_key}"} if api_key else {}
|
|
|
|
# Catégories et nombre limite de modèles à récupérer pour garantir les plus fiables
|
|
categories = {
|
|
"text-generation": 20, # 20 LLMs texte
|
|
"text-to-image": 5, # 5 Générateurs d'images
|
|
"text-to-video": 2 # 2 Générateurs vidéo
|
|
}
|
|
|
|
hf_models = []
|
|
for tag, limit in categories.items():
|
|
url = "https://huggingface.co/api/models"
|
|
params = {
|
|
"pipeline_tag": tag,
|
|
"sort": "downloads",
|
|
"direction": -1,
|
|
"limit": limit
|
|
}
|
|
try:
|
|
resp = requests.get(url, headers=headers, params=params, timeout=15)
|
|
if resp.status_code == 200:
|
|
for m in resp.json():
|
|
# Formatage identifiable pour l'orchestrateur
|
|
hf_models.append(f"huggingface/{m['id']}")
|
|
except Exception as e:
|
|
log_event("WARNING", "UPDATER", f"Erreur de récupération HF pour {tag}: {e}")
|
|
|
|
return hf_models
|
|
|
|
def _do_update():
|
|
# --- SYSTÈME ANTI-SPAM (VERROU INTER-PROCESSUS) ---
|
|
now = time.time()
|
|
try:
|
|
if os.path.exists(LOCK_FILE):
|
|
with open(LOCK_FILE, "r") as f:
|
|
last_update = float(f.read().strip())
|
|
# Si la dernière MAJ date de moins d'une heure (3600 sec), on annule l'exécution de ce thread
|
|
if now - last_update < 3600:
|
|
return
|
|
except Exception:
|
|
pass # En cas d'erreur de lecture, on force la MAJ
|
|
|
|
# On pose le verrou avec le timestamp actuel pour bloquer les autres workers
|
|
try:
|
|
os.makedirs(os.path.dirname(LOCK_FILE), exist_ok=True)
|
|
with open(LOCK_FILE, "w") as f:
|
|
f.write(str(now))
|
|
except Exception as e:
|
|
log_event("WARNING", "UPDATER", f"Impossible d'écrire le verrou : {e}")
|
|
# --- FIN DU SYSTÈME ANTI-SPAM ---
|
|
|
|
ollama_host = os.getenv("OLLAMA_HOST", "http://192.168.1.20:11434")
|
|
try:
|
|
# MAJ locale Abliterated
|
|
resp_local = requests.post(
|
|
f"{ollama_host}/api/pull",
|
|
json={"name": "richardyoung/llama-3.2-3b-instruct-abliterated"},
|
|
timeout=300
|
|
)
|
|
if resp_local.status_code == 200:
|
|
log_event("INFO", "UPDATER", "Modèle local Abliterated vérifié/mis à jour.")
|
|
|
|
# MAJ DU CATALOGUE COMPLET OPENROUTER
|
|
resp_or = requests.get("https://openrouter.ai/api/v1/models", timeout=30)
|
|
modeles_gratuits = []
|
|
modeles_payants = []
|
|
|
|
if resp_or.status_code == 200:
|
|
data = resp_or.json().get("data", [])
|
|
for m in data:
|
|
pricing = m.get("pricing", {})
|
|
|
|
# S'il est 100% gratuit
|
|
if pricing.get("prompt") == "0" and pricing.get("completion") == "0":
|
|
if "nvidia/nemotron" not in m["id"].lower(): # On garde l'exclusion sécurité
|
|
modeles_gratuits.append(m["id"])
|
|
else:
|
|
# Intégration de TOUS les modèles payants
|
|
modeles_payants.append(m["id"])
|
|
else:
|
|
log_event("WARNING", "UPDATER", "Échec de récupération du catalogue OpenRouter.")
|
|
|
|
# MAJ DU CATALOGUE HUGGING FACE
|
|
hf_gratuits = recuperer_modeles_hf()
|
|
modeles_gratuits.extend(hf_gratuits)
|
|
|
|
with open(CATALOGUE_FILE, "w", encoding="utf-8") as f:
|
|
json.dump({"free_models": modeles_gratuits, "paid_models": modeles_payants}, f)
|
|
|
|
log_event("INFO", "UPDATER", f"Catalogue Global mis à jour : {len(modeles_gratuits)} gratuits (dont {len(hf_gratuits)} HF), {len(modeles_payants)} payants détectés.")
|
|
|
|
except Exception as e:
|
|
log_event("ERROR", "UPDATER", f"Erreur lors de la MAJ auto : {e}")
|
|
|
|
def trigger_update_now():
|
|
# Force la mise à jour en supprimant le verrou au préalable
|
|
if os.path.exists(LOCK_FILE):
|
|
try: os.remove(LOCK_FILE)
|
|
except: pass
|
|
threading.Thread(target=_do_update, daemon=True).start()
|
|
|
|
def update_models_background():
|
|
# Boucle de fond
|
|
while True:
|
|
_do_update()
|
|
time.sleep(7200) # Attente 2 heures
|
|
|
|
threading.Thread(target=update_models_background, daemon=True).start() |