chore: Serveur 100% stable, ports corrigés, prêt pour le RAG
Build and Push Docker Image / build-and-push (push) Successful in 1m50s

This commit is contained in:
xavier committed 2026-08-20 15:24:28 +02:00
1 parent 7125842853
commit ffe820b00f
20 files changed
+7772 -198

No files matched your search

+77 -54
View File
@@ -1,73 +1,96 @@
import os
import time
from dotenv import load_dotenv
import openai
from openai import OpenAI
from modules.logger import log_event
# Initialisation du client OpenRouter avec l'API compatible OpenAI
load_dotenv()
api_key_openrouter = os.getenv("OPENROUTER_API_KEY") or "sk-or-v1-cle-non-definie"
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.getenv("OPENROUTER_API_KEY", "VOTRE_CLE_ICI") # À définir dans le .env
api_key=api_key_openrouter
)
def interroger_openrouter(prompt, type_modele="openrouter_chat", premium=False, max_retries=3):
"""
Interroge l'API OpenRouter avec gestion des erreurs 402 (Plafond) et 429 (Rate Limit).
Bascule entre les modèles gratuits et premiums (VIP/Payant) selon le choix utilisateur.
"""
# Sélection dynamique des modèles selon l'abonnement
if premium:
if type_modele == "openrouter_code":
nom_modele_api = "anthropic/claude-3.5-sonnet"
nom_affichage = "OpenRouter (Claude 3.5 Sonnet - Premium)"
couleur = "#d97757" # Orange Anthropic
else:
nom_modele_api = "openai/gpt-4o-mini"
nom_affichage = "OpenRouter (GPT-4o Mini - Premium)"
couleur = "#10a37f" # Vert OpenAI
else:
if type_modele == "openrouter_code":
nom_modele_api = "qwen/qwen-2.5-coder-32b-instruct:free"
nom_affichage = "OpenRouter (Qwen Coder - Gratuit)"
couleur = "#4a90e2" # Bleu clair
else:
nom_modele_api = "meta-llama/llama-3.1-8b-instruct:free"
nom_affichage = "OpenRouter (Llama 3.1 - Gratuit)"
couleur = "#4a90e2" # Bleu clair
CATALOGUE_MODELES = {
"gratuit": {
"openrouter_chat": "google/gemma-4-31b-it:free",
"openrouter_code": "cohere/north-mini-code:free",
"openrouter_droit": "z-ai/glm-5.2:free"
},
"premium": {
"openrouter_chat": "openai/gpt-4o-mini",
"openrouter_code": "anthropic/claude-3.5-sonnet",
"openrouter_droit": "mistralai/mistral-large-2411"
}
}
def verifier_cle_api():
cle = os.getenv("OPENROUTER_API_KEY")
if not cle or cle == "sk-or-v1-cle-non-definie":
raise Exception("Clé OPENROUTER_API_KEY absente dans le fichier .env.")
return cle
def interroger_openrouter(prompt: str, type_modele: str = "openrouter_chat", premium: bool = False, max_retries: int = 2):
verifier_cle_api()
gamme = "premium" if premium else "gratuit"
nom_modele_api = CATALOGUE_MODELES[gamme].get(type_modele, CATALOGUE_MODELES[gamme]["openrouter_chat"])
nom_affichage = f"OpenRouter ({nom_modele_api.split('/')[-1]})"
couleur = "#d97757" if premium else "#4a90e2"
for tentative in range(max_retries):
try:
start_time = time.time()
response = client.chat.completions.create(
model=nom_modele_api,
messages=[{"role": "user", "content": prompt}]
messages=[{"role": "user", "content": prompt}],
extra_headers={
"HTTP-Referer": "https://aethas38.duckdns.org",
"X-Title": "Aethas38 Multi-IA"
},
timeout=20.0
)
texte = response.choices[0].message.content
return texte, couleur, "OpenRouter", nom_affichage
except openai.RateLimitError as e:
temps_attente = 2 ** tentative
log_event("WARNING", "OPENROUTER", f"Limite de taux atteinte (429). Essai {tentative + 1}/{max_retries}. Attente de {temps_attente}s...")
time.sleep(temps_attente)
if tentative == max_retries - 1:
log_event("ERROR", "OPENROUTER", "Échec définitif suite aux limites de taux (429).")
raise Exception("Service temporairement saturé sur OpenRouter. Veuillez réessayer.")
except openai.APIStatusError as e:
if e.status_code == 402:
log_event("CRITICAL", "OPENROUTER", "Erreur 402 : Fonds insuffisants ou limite de clé atteinte.")
raise Exception("Action requise : Limite de facturation atteinte sur OpenRouter.")
else:
log_event("ERROR", "OPENROUTER", f"Code {e.status_code} : {e.message}")
raise Exception(f"Erreur API OpenRouter : {e.status_code}")
except openai.APIConnectionError as e:
log_event("ERROR", "OPENROUTER", f"Erreur réseau : {e}")
raise Exception("Impossible de joindre les serveurs d'OpenRouter.")
usage = response.usage
tokens_in = usage.prompt_tokens if usage else 0
tokens_out = usage.completion_tokens if usage else 0
return texte, couleur, "OpenRouter", nom_affichage, tokens_in, tokens_out
except Exception as e:
log_event("ERROR", "OPENROUTER", f"Erreur inattendue : {e}")
raise e
return None, None, None, None
log_event("WARNING", "OPENROUTER", f"Tentative {tentative + 1} échouée pour {nom_modele_api} : {e}")
if tentative == max_retries - 1:
raise e
time.sleep(1)
return None, None, None, None, 0, 0
def interroger_openrouter_multi(prompt: str, type_modele: str = "openrouter_code", premium: bool = False) -> list:
verifier_cle_api()
if premium:
modeles = ["anthropic/claude-3.5-sonnet", "openai/gpt-4o-mini"]
else:
# Modèles gratuits réactifs sans blocage de quota
modeles = ["cohere/north-mini-code:free", "google/gemma-4-31b-it:free"]
reponses = []
for modele in modeles:
try:
res = client.chat.completions.create(
model=modele,
messages=[{"role": "user", "content": prompt}],
extra_headers={
"HTTP-Referer": "https://aethas38.duckdns.org",
"X-Title": "Aethas38 Multi-IA"
},
timeout=15.0
)
contenu = res.choices[0].message.content
if contenu:
reponses.append({"modele": modele, "texte": contenu})
except Exception as e:
log_event("WARNING", "OPENROUTER_MULTI", f"Échec rapide pour {modele} : {e}")
continue
return reponses