Public Access
Amélioration modules updater et sélection des IA suivant disponibilités
Build and Push Docker Image / build-and-push (push) Successful in 35s
Build and Push Docker Image / build-and-push (push) Successful in 35s
This commit is contained in:
1 parent
3553809df3
commit
d36cb07ab1
2 files changed
+95
-38
No files matched your search
@@ -1,16 +1,34 @@
|
|||||||
import os
|
import os
|
||||||
|
import json
|
||||||
import requests
|
import requests
|
||||||
from modules.logger import log_event
|
from modules.logger import log_event
|
||||||
|
|
||||||
def interroger_huggingface(prompt: str, modele_cible="mistralai/Mistral-7B-Instruct-v0.3"):
|
CATALOGUE_FILE = "/DATA/AppData/MULTI-IA-AETHAS38/catalogue_dynamique.json"
|
||||||
|
|
||||||
|
def interroger_huggingface(prompt: str, modele_cible=None):
|
||||||
"""
|
"""
|
||||||
Connecteur pour l'API Serverless gratuite de Hugging Face.
|
Connecteur pour l'API Serverless de Hugging Face.
|
||||||
S'intègre nativement dans la boucle de repli de ai_engine.py.
|
Sélectionne dynamiquement le modèle le plus populaire scanné par l'Updater.
|
||||||
"""
|
"""
|
||||||
api_key = os.getenv("HUGGINGFACE_API_KEY")
|
api_key = os.getenv("HUGGINGFACE_API_KEY")
|
||||||
if not api_key:
|
if not api_key:
|
||||||
raise Exception("Clé API HuggingFace manquante dans le .env")
|
raise Exception("Clé API HuggingFace manquante dans le .env")
|
||||||
|
|
||||||
|
# Extraction dynamique du meilleur modèle Hugging Face gratuit disponible
|
||||||
|
if not modele_cible:
|
||||||
|
try:
|
||||||
|
if os.path.exists(CATALOGUE_FILE):
|
||||||
|
with open(CATALOGUE_FILE, "r", encoding="utf-8") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
hf_models = [m.replace("huggingface/", "") for m in data.get("free_models", []) if m.startswith("huggingface/")]
|
||||||
|
if hf_models:
|
||||||
|
modele_cible = hf_models[0] # Modèle le plus téléchargé selon l'Updater
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not modele_cible:
|
||||||
|
modele_cible = "mistralai/Mistral-7B-Instruct-v0.3"
|
||||||
|
|
||||||
url = f"https://router.huggingface.co/hf-inference/models/{modele_cible}"
|
url = f"https://router.huggingface.co/hf-inference/models/{modele_cible}"
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {api_key}",
|
"Authorization": f"Bearer {api_key}",
|
||||||
@@ -33,10 +51,9 @@ def interroger_huggingface(prompt: str, modele_cible="mistralai/Mistral-7B-Instr
|
|||||||
data = resp.json()
|
data = resp.json()
|
||||||
if isinstance(data, list) and len(data) > 0 and "generated_text" in data[0]:
|
if isinstance(data, list) and len(data) > 0 and "generated_text" in data[0]:
|
||||||
texte = data[0]["generated_text"].strip()
|
texte = data[0]["generated_text"].strip()
|
||||||
# Renvoie la signature exacte attendue par ai_engine (texte, couleur, fournisseur, modele)
|
|
||||||
return texte, "#ffb000", "HuggingFace", modele_cible
|
return texte, "#ffb000", "HuggingFace", modele_cible
|
||||||
|
|
||||||
raise Exception(f"Erreur {resp.status_code} : {resp.text}")
|
raise Exception(f"Erreur {resp.status_code} : {resp.text}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log_event("WARNING", "HUGGINGFACE", f"Échec de la requête : {e}")
|
log_event("WARNING", "HUGGINGFACE", f"Échec de la requête pour {modele_cible} : {e}")
|
||||||
raise e
|
raise e
|
||||||
+73
-33
@@ -18,34 +18,88 @@ def verifier_cle_api():
|
|||||||
return cle
|
return cle
|
||||||
|
|
||||||
def obtenir_modele_dynamique(premium: bool, prompt: str = ""):
|
def obtenir_modele_dynamique(premium: bool, prompt: str = ""):
|
||||||
"""Charge le catalogue dynamiquement et adapte le modèle si la règle Éducation est détectée."""
|
"""Charge le catalogue dynamiquement pour un seul modèle optimal."""
|
||||||
est_education = "RÈGLE ÉDUCATION NATIONALE" in prompt
|
est_education = "RÈGLE ÉDUCATION NATIONALE" in prompt
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if os.path.exists(CATALOGUE_FILE):
|
if os.path.exists(CATALOGUE_FILE):
|
||||||
with open(CATALOGUE_FILE, "r", encoding="utf-8") as f:
|
with open(CATALOGUE_FILE, "r", encoding="utf-8") as f:
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
if premium:
|
|
||||||
paid_models = data.get("paid_models", [])
|
|
||||||
claude = [m for m in paid_models if "claude-3.5-sonnet" in m.lower()]
|
|
||||||
return claude[0] if claude else (paid_models[0] if paid_models else "anthropic/claude-3.5-sonnet")
|
|
||||||
else:
|
|
||||||
# En mode gratuit + Education, Mistral est le plus pointu en syntaxe française
|
|
||||||
if est_education:
|
|
||||||
return "mistralai/mistral-small-24b-instruct-2501:free"
|
|
||||||
|
|
||||||
free_models = data.get("free_models", [])
|
if premium:
|
||||||
priorites = [m for m in free_models if "gemma" in m.lower() or "nemotron" in m.lower()]
|
paid_models = data.get("paid_models", [])
|
||||||
return priorites[0] if priorites else (free_models[0] if free_models else "google/gemma-2-9b-it:free")
|
if not paid_models: return "anthropic/claude-3.5-sonnet"
|
||||||
|
claude = [m for m in paid_models if "claude-3.5-sonnet" in m.lower()]
|
||||||
|
return claude[0] if claude else paid_models[0]
|
||||||
|
else:
|
||||||
|
free_models = [m for m in data.get("free_models", []) if not m.startswith("huggingface/")]
|
||||||
|
if not free_models: return "google/gemma-2-9b-it:free"
|
||||||
|
|
||||||
|
if est_education:
|
||||||
|
mistral = [m for m in free_models if "mistral" in m.lower()]
|
||||||
|
return mistral[0] if mistral else free_models[0]
|
||||||
|
|
||||||
|
priorites = [m for m in free_models if "gemma" in m.lower() or "nemotron" in m.lower()]
|
||||||
|
return priorites[0] if priorites else free_models[0]
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if premium: return "anthropic/claude-3.5-sonnet"
|
return "anthropic/claude-3.5-sonnet" if premium else "google/gemma-2-9b-it:free"
|
||||||
return "mistralai/mistral-small-24b-instruct-2501:free" if est_education else "google/gemma-2-9b-it:free"
|
|
||||||
|
def obtenir_modeles_multi_dynamiques(premium: bool, prompt: str) -> list:
|
||||||
|
"""Détermine dynamiquement les modèles et leur nombre selon le sujet de la requête."""
|
||||||
|
try:
|
||||||
|
with open(CATALOGUE_FILE, "r", encoding="utf-8") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
except Exception:
|
||||||
|
data = {"free_models": [], "paid_models": []}
|
||||||
|
|
||||||
|
modeles_dispos = data.get("paid_models", []) if premium else data.get("free_models", [])
|
||||||
|
modeles_or = [m for m in modeles_dispos if not m.startswith("huggingface/")]
|
||||||
|
|
||||||
|
if not modeles_or:
|
||||||
|
return ["anthropic/claude-3.5-sonnet"] if premium else ["google/gemma-2-9b-it:free"]
|
||||||
|
|
||||||
|
# Analyse sémantique du sujet pour définir le nombre d'IA et la priorité
|
||||||
|
prompt_lower = prompt.lower()
|
||||||
|
nb_ia = 3 # Par défaut
|
||||||
|
|
||||||
|
if any(mot in prompt_lower for mot in ["code", "script", "python", "javascript", "html", "css", "erreur", "bug", "kubejs", "serveur"]):
|
||||||
|
nb_ia = 5
|
||||||
|
mots_cles = ["coder", "claude", "llama", "qwen", "deepseek"]
|
||||||
|
elif any(mot in prompt_lower for mot in ["loi", "juridique", "droit", "contrat", "urssaf", "légal"]):
|
||||||
|
nb_ia = 4
|
||||||
|
mots_cles = ["mistral", "claude", "llama", "mixtral"]
|
||||||
|
elif any(mot in prompt_lower for mot in ["traduis", "rédaction", "écris", "lettre", "mail", "éducation"]):
|
||||||
|
nb_ia = 2
|
||||||
|
mots_cles = ["mistral", "claude", "llama", "gemini", "gemma"]
|
||||||
|
else:
|
||||||
|
mots_cles = ["gemini", "llama", "mistral", "qwen", "gemma"]
|
||||||
|
|
||||||
|
modeles_selectionnes = []
|
||||||
|
|
||||||
|
# Étape 1 : Sélectionner les modèles qui matchent les mots-clés
|
||||||
|
for mc in mots_cles:
|
||||||
|
for m in modeles_or:
|
||||||
|
if mc in m.lower() and m not in modeles_selectionnes:
|
||||||
|
modeles_selectionnes.append(m)
|
||||||
|
if len(modeles_selectionnes) == nb_ia:
|
||||||
|
break
|
||||||
|
if len(modeles_selectionnes) == nb_ia:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Étape 2 : Compléter avec les autres modèles du catalogue si le nombre n'est pas atteint
|
||||||
|
for m in modeles_or:
|
||||||
|
if len(modeles_selectionnes) >= nb_ia:
|
||||||
|
break
|
||||||
|
if m not in modeles_selectionnes:
|
||||||
|
modeles_selectionnes.append(m)
|
||||||
|
|
||||||
|
return modeles_selectionnes
|
||||||
|
|
||||||
def interroger_openrouter(prompt: str, type_modele: str = "openrouter_chat", premium: bool = False, max_retries: int = 2, chat_id: str = None):
|
def interroger_openrouter(prompt: str, type_modele: str = "openrouter_chat", premium: bool = False, max_retries: int = 2, chat_id: str = None):
|
||||||
verifier_cle_api()
|
verifier_cle_api()
|
||||||
nom_modele_api = obtenir_modele_dynamique(premium, prompt) # On passe le prompt pour détecter le marqueur
|
nom_modele_api = obtenir_modele_dynamique(premium, prompt)
|
||||||
nom_affichage = f"OpenRouter ({nom_modele_api.split('/')[-1]})"
|
nom_affichage = f"OpenRouter ({nom_modele_api.split('/')[-1]})"
|
||||||
couleur = "#d97757" if premium else "#4a90e2"
|
couleur = "#d97757" if premium else "#4a90e2"
|
||||||
|
|
||||||
@@ -83,23 +137,9 @@ def interroger_openrouter_multi(prompt: str, type_modele: str = "openrouter_code
|
|||||||
verifier_cle_api()
|
verifier_cle_api()
|
||||||
extra_body_data = {"session_id": chat_id} if chat_id else {}
|
extra_body_data = {"session_id": chat_id} if chat_id else {}
|
||||||
|
|
||||||
# --- LA LISTE BLANCHE DES 5 MEILLEURS MODÈLES ---
|
# La liste s'adapte dynamiquement au nombre d'IA requis par le sujet et aux disponibilités
|
||||||
if premium:
|
modeles = obtenir_modeles_multi_dynamiques(premium, prompt)
|
||||||
modeles = [
|
log_event("INFO", "OPENROUTER_MULTI", f"Lancement Multi-IA avec {len(modeles)} modèles adaptatifs.")
|
||||||
"anthropic/claude-3.5-sonnet", # Le meilleur en code/logique
|
|
||||||
"openai/gpt-4o", # Ultra polyvalent
|
|
||||||
"google/gemini-1.5-pro", # Excellent contexte
|
|
||||||
"mistralai/mistral-large-2407", # Top pour le français
|
|
||||||
"meta-llama/llama-3.1-405b-instruct" # Le titan OpenSource
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
modeles = [
|
|
||||||
"google/gemma-2-9b-it:free",
|
|
||||||
"meta-llama/llama-3.1-8b-instruct:free",
|
|
||||||
"microsoft/phi-3-mini-128k-instruct:free",
|
|
||||||
"mistralai/mistral-nemo:free",
|
|
||||||
"qwen/qwen-2-7b-instruct:free"
|
|
||||||
]
|
|
||||||
|
|
||||||
reponses = []
|
reponses = []
|
||||||
for modele in modeles:
|
for modele in modeles:
|
||||||
@@ -115,7 +155,7 @@ def interroger_openrouter_multi(prompt: str, type_modele: str = "openrouter_code
|
|||||||
if contenu:
|
if contenu:
|
||||||
reponses.append({"modele": modele, "texte": contenu})
|
reponses.append({"modele": modele, "texte": contenu})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log_event("WARNING", "OPENROUTER_MULTI", f"Échec rapide pour {modele} : {e}")
|
log_event("WARNING", "OPENROUTER_MULTI", f"Échec pour {modele} : {e}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return reponses
|
return reponses
|
||||||
Reference in new issue
Block a user