feat: Intégration de l'API OpenRouter, suppression de Groq et mise à jour du README

This commit is contained in:
xavier committed 2026-08-18 13:08:18 +02:00
1 parent 909e2e995a
commit 317ecddc56
5 files changed
+130 -123

No files matched your search

+37 -69
View File
@@ -1,93 +1,61 @@
# Aethas38 - Multi-IA Orchestrateur (Minecraft-Tech Edition)
Plateforme SaaS d'IA modulaire : Orchestrateur local, routeur intelligent, sécurisé et facturable.
**Architecture réseau :** Déploiement via Docker derrière Nginx Proxy Manager (NPM) sur `https://ia.aethas38.duckdns.org`.
## 📜 Licence & Droits d'Utilisation (EULA)
Ce projet est distribué sous une licence "Source Available" propriétaire (EULA) rédigée par Xavier Fernandez (Aethas38).
* **Modifications & Partage :** Les utilisateurs sont autorisés à modifier et améliorer le code, à condition de partager ces améliorations avec la communauté.
* **Restrictions strictes :** Il est **strictement interdit** de modifier ou supprimer les crédits de l'auteur originel, de retirer le module de dons dédié au créateur, ou de désactiver la télémétrie de sécurité (notification d'installation avec IP/Nom admin envoyée à `admin@mail.aethas38.duckdns.org`). L'installation requiert l'acceptation explicite de ces termes.
## 📋 To-Do List (Roadmap)
### Phase 1 & 2 : Infrastructure & Backend de Base ✅
- [x] Installation Docker, Nginx, Pare-feu, Gitea/GitHub
- [x] Serveur Local Ollama (Qwen 3B) + FastHTML
- [x] Routeur Multi-IA (Groq, Gemini, Local) avec système de cascade et directives d'aiguillage strictes
- [x] Continuité de service : IA de secours (Fallback automatique sur Groq) en cas de panne d'une API primaire
- [x] Installation Docker, Nginx (NPM), Pare-feu, Gitea/GitHub
- [x] Serveur Local Ollama (Qwen 3B) + FastHTML (Adapté aux processeurs limités type AMD Phenom)
- [x] Routeur Multi-IA (OpenRouter, Gemini, Local) avec système de cascade et directives d'aiguillage strictes
- [x] Continuité de service : IA de secours automatique
### Phase 3 : Refonte UI & Expérience Utilisateur ✅
- [x] Thème "Minecraft-Tech" (Inspiré serveurs/redstone) compatible Mobile (Responsive)
- [x] Historique (Sidebar) avec Renommage, Épinglage, Suppression et Navigation isolée par session
- [x] Zone de saisie intelligente (Textarea auto-adaptatif, Drag & Drop avec pills/miniatures, Collage multi-fichiers jusqu'à 10)
- [x] Export modulaire et propre (PDF Pro avec fond blanc, DOC Word, TXT, JSON, et blocs de code en ZIP) avec nommage dynamique intelligent basé sur la requête utilisateur (ex: `frise_temporalite_minecraft.pdf`)
- [x] Boutons de partage direct (WhatsApp, Email) avec nettoyage automatique des balises HTML brutes
- [x] Script de nettoyage automatique : Suppression des discussions de > 365 jours
- [x] Export modulaire et propre (PDF, DOC, TXT, JSON, ZIP)
- [x] Boutons de partage direct (WhatsApp, Email)
- [x] Indicateur d'avancement dynamique (Loader Néon) pendant le traitement des IA
- [x] Architecture modulaire propre (Dossier `modules/` isolant Database, Scraper, AI Engine, Router et UI)
- [x] Architecture modulaire propre (Dossier `modules/`)
### Phase 4 : Gestion des Utilisateurs & Sécurité
- [ ] Céer un lien Paypal pour les dons des utilisateurs.
- [ ] Mettre en place une bibliothèque logiciel à installer avec le serveur (déporter tout ce qui peut l'être comme la création de pdf, docx, html, etc.)
- [ ] Choix entre l'utilisation de la version payante ou gratuite. Routage suivant le choix.
- [ ] Système de connexion sécurisé (Mots de passe cryptés)
- [ ] Fail2Ban (Blocage 15 mins après 5 erreurs)
- [ ] Intégration SMTP (`mail.aethas38.duckdns.org`) pour mot de passe oublié et notifications de thèmes spécifiques
- [ ] Gestion des rôles : Admin (Xavier, Céline), Famille (Anaëlle, Audric, Renan), Testeur (Nogapra) et Externes. Testeur juste accès à la partie gratuite.
- [ ] Prévoir un script automatique envoyant un mail sympathique aux utilisateurs lors de leur anniversaire.
### Phase 4 : Gestion des Utilisateurs & Sécurité Légale
- [ ] Créer un lien Paypal pour les dons des utilisateurs (Incluant un bouton de don inaltérable pour le créateur Aethas38).
- [ ] Mettre en place une bibliothèque logicielle autonome sur le serveur (création PDF, DOCX, etc.).
- [ ] Routage automatique (Gratuit vs Payant) sélectionné par l'utilisateur.
- [ ] Système de connexion sécurisé avec configuration du premier lancement (DOB depuis 1900, Email, Clés API). L'utilisateur Xavier a obligatoirement le rôle "Dieu tout puissant" (Admin global).
- [ ] Sécurité Légère : Fail2Ban, protection Bruteforce et DDoS. **Blocage total des accès VPN**.
- [ ] Conformité légale (RGPD) : Journalisation stricte des IP par client conservée 1 an.
- [ ] Multilinguisme : Adaptation automatique de la langue du site via la géolocalisation de l'IP.
### Phase 5 : Sécurité Financière & Facturation Exacte 💰
- [ ] Modèle Excel de calcul des coûts serveur (1x 1000W H24, Internet 60€/mois). Prendre en compte le tarif réglemanté de l'électricité en France et la consommation réel du serveur.
- [ ] Simulateur de coût avant requête : L'estimation doit être exacte pour éviter les défauts de paiement
- [ ] Gestion des comptes et provisions (CB) avec test du restant financier avant validation
- [ ] Règles d'exceptions Administrateurs & Famille (Pas de provision nécessaire, rattachés au master-compte Xavier/Céline)
- [ ] Majoration invisible de 15% appliquée automatiquement pour les comptes Externes
- [ ] Compteur en temps réel mis à jour après la requête basé sur le prix annoncé après traitement par les fournisseurs "Pay As You Go" (PAYG)
- [ ] Routage Conditionnel Payant : Utiliser *toutes* les IA en adéquation avec le thème de la requête
- [ ] Simulateur de coût avant requête : L'estimation doit être exacte pour éviter les défauts de paiement.
- [ ] Cryptage absolu de toutes les données sensibles et bancaires.
- [ ] Module de conversion des devises en temps réel (Taux du jour) pour un affichage transparent.
- [ ] **Utilisateurs Privilégiés (Zéro Marge) :** Xavier, Céline, Anaëlle, Renan et Audric. Autorisation de virements manuels pour la cagnotte.
- [ ] **Marge Commerciale :** Majoration automatique via la formule `Prix_Facture_HT = Cout_API_OpenRouter_HT / 0.85` (soit 15% de marge) pour les comptes externes, prenant en compte le statut auto-entrepreneur (TVA).
- [ ] Export comptable Excel (TCD) par utilisateur via Pandas/Openpyxl et archivage PDF automatisé.
### Phase 6 : Nouvelles Capacités IA (Spécialisations & Modèles) 🤖
*La mise en forme finale des retours est assurée par l'abonnement Gemini.*
*Note : L'infrastructure bascule sur OpenRouter pour palier aux décommissionnements constants des autres fournisseurs.*
| Domaine de tâche | Modèle / Moteur | Fournisseur / Hébergement | Rôle principal |
| :--- | :--- | :--- | :--- |
| **Orchestration & Tri** | Qwen 2.5 (3B/7B quantizé) | Local (GTX 1650 / Ollama) | Analyse l'intention, gère le chat rapide et route vers la bonne IA |
| **Prog. & Java 21** | Claude 3.5 Sonnet / Qwen Coder | Anthropic / OpenRouter | Correction bugs, KubeJS, modernisation de mods (Pay-as-you-go) |
| **Serveur / Logs** | Llama 3.3 (8B / 70B) | Groq API | Analyse crashs Prism Launcher, Bash, Docker (Gratuit / Rapide) |
| **Logique & Quêtes** | DeepSeek R1 (Distillé) | DeepSeek API / Gratuit | Structuration logique des modpacks et FTB Quests |
| **Images HD / Vidéo** | Gemini 2.0 Flash / FLUX.1 | Google AI Studio & Fal.ai | Analyse d'images/vidéos et génération d'assets 2K |
| **Bureautique** | À définir | À définir | Excel (Macros, formules complexes) |
| **Orchestration & Tri** | Qwen 2.5 (3B) | Local (GTX 1650 / Ollama) | Analyse l'intention, gère le chat rapide et route vers la bonne IA |
| **Bureautique & Code** | Llama 3.1 / Qwen 2.5 Coder | OpenRouter API (Gratuit) | Programmation, scripts, macros VBA, mathématiques |
| **Images HD / Fichiers** | Gemini 2.0 Flash / Pro | Google AI Studio | Analyse d'images/vidéos et documents joints |
### Phase 7 : RAG & Maintenance
- [ ] "RAG" : Base de données vectorielle (ChromaDB) pour permettre l'apprentissage et la mémorisation de l'IA locale
- [ ] Script de surveillance de l'espace disque du serveur. Affichage d'une barre d'état (statuts des disques, remplissage, utilisations pour Xavier)
- [ ] Création de logs centralisés consultables et téléchargeables par l'Admin
### Phase 8 : Déploiement Public & Configuration
- [ ] Assistant de configuration (Wizard) au premier lancement pour insérer les clés API, configurer le SMTP, etc.
- [ ] Liens de documentation intégrés pour créer ses propres clés API
- [ ] Hébergement sur Gitea/Github des versions "Install Initial" ou "Update" pour Docker
### Phase 7 & 8 : Maintenance & Déploiement
- [ ] Script de surveillance de l'espace disque du serveur (Beszel / Psutil) réservé à l'Admin.
- [ ] Sauvegarde automatique : Compression du site toutes les 6 heures vers GDrive (`25-BACKUP SITE`), 4 versions conservées.
- [ ] Hébergement sur Gitea/Github des versions "Install Initial" ou "Update" pour Docker. Licence identique sur les deux plateformes.
- [ ] Création d'un Wiki détaillé multilingue pour l'installation personnelle.
## 📷 Vidéosurveillance & Détection Intelligente
L'écosystème de vision par ordinateur appliqué à la sécurité s'articule autour de la détection d'objets en temps réel pour garantir des alertes immédiates[cite: 35].
### 1. Frigate NVR (Détection Locale & Temps Réel)
* **Rôle principal** : Solution standard incontournable pour analyser des flux vidéo RTSP 24h/24 en local, sans saturer le processeur et sans dépendre du cloud[cite: 35].
* **Matériel recommandé** : Ajout d'un accélérateur matériel **Google Coral TPU** (M.2 ou USB) pour encaisser le traitement lourd de l'IA sans impacter le CPU du serveur[cite: 35].
* **Modèles de détection** :
* **Modèle par défaut** : Basé sur MobileNet SSD, optimisé pour les Edge TPU, détectant les classes standard (personnes, voitures, chats, chiens)[cite: 35].
* **Modèles personnalisés (YOLO)** : Injection possible de modèles au format `.onnx` (issus de YOLOv5, v8 ou v11) pour des éléments spécifiques (colis, animaux précis)[cite: 35].
* **Frigate+** : Service payant d'annotation de faux positifs pour réentraîner un modèle sur-mesure ultra-précis pour le Coral TPU[cite: 35].
---
## 🏠 Home Assistant & Analyse Sémantique (LLM Multimodaux)
L'utilisation de Modèles de Langage Multimodaux (LMM) permet de comprendre en détail le contenu d'une scène et d'envoyer des notifications contextuelles riches[cite: 35].
### 1. Solutions Cloud (Précision Maximale)
* **Google Gemini (Flash / Pro)** : Choix populaire et redoutable doté de quotas gratuits généreux, capable de décrire une image avec une précision chirurgicale (ex. : « Un livreur dépose un colis étiqueté Amazon sur le paillasson »)[cite: 35].
* **OpenAI GPT-4o / GPT-4o-mini** : Alternative payante performante pour analyser le contexte d'une image et générer des notifications smartphone dynamiques[cite: 35].
### 2. Solutions Locales (Confidentialité / 100% Offline)
* **Qwen2-VL** : L'un des meilleurs modèles ouverts (open-weights) en vision pour analyser finement les détails d'une caméra de sécurité[cite: 35].
* **Llama 3.2 Vision** : Modèle rapide et idéal pour un déploiement local sur une machine dotée d'un GPU performant[cite: 35].
* **Moondream** : Modèle minuscule et ultrarapide conçu spécifiquement pour la vision sur des architectures modestes[cite: 35].
### 3. Architecture Hybride Recommandée
* **Niveau 1 (Sécurité & Réactivité - 0ms de latence cloud)** : Frigate couplé au Google Coral TPU surveille les flux en continu et déclenche instantanément des actions physiques (lumières, alarmes) via Home Assistant dès qu'un humain est détecté[cite: 35].
* **Niveau 2 (Confort & Notification - Analyse sémantique)** : Home Assistant capture une image (snapshot) et l'envoie à un LLM multimodal (Gemini pour le cloud ou Qwen2-VL en local) pour générer une notification push riche décrivant la situation[cite: 35].
*(Voir configuration Frigate locale et Google Coral TPU existante)*
+17 -14
View File
@@ -1,11 +1,8 @@
from modules.logger import log_event
from modules.ai_gemini import interroger_gemini
from modules.ai_groq import interroger_groq
from modules.ai_deepseek import interroger_deepseek
from modules.ai_mistral import interroger_mistral
from modules.ai_huggingface import interroger_huggingface
from modules.ai_cloudflare import interroger_cloudflare
from modules.ai_local import interroger_local_ollama
# Le nouveau module que nous allons créer à la prochaine étape
from modules.ai_openrouter import interroger_openrouter
SYSTEM_CONFIDENTIALITY_INSTRUCTION = (
"RÈGLE DE CONFIDENTIALITÉ ABSOLUE : Tu es un assistant intégré à la plateforme privée Aethas38. "
@@ -15,21 +12,27 @@ SYSTEM_CONFIDENTIALITY_INSTRUCTION = (
)
def executer_requete_ia(fournisseur, prompt):
"""Moteur central gérant les consignes de sécurité et la cascade intelligente."""
"""Moteur central gérant les consignes de sécurité et la cascade intelligente vers OpenRouter."""
prompt_securise = f"{SYSTEM_CONFIDENTIALITY_INSTRUCTION}\n\nRequête utilisateur :\n{prompt}"
# 🔄 Ordre de cascade intelligent défini par l'orchestrateur (repli automatique)
if fournisseur == "gemini": ordre_repli = [interroger_gemini, interroger_groq, interroger_mistral, interroger_deepseek, interroger_huggingface, interroger_cloudflare, interroger_local_ollama]
elif fournisseur == "groq": ordre_repli = [interroger_groq, interroger_mistral, interroger_deepseek, interroger_gemini, interroger_huggingface, interroger_cloudflare, interroger_local_ollama]
elif fournisseur == "deepseek": ordre_repli = [interroger_deepseek, interroger_gemini, interroger_groq, interroger_mistral, interroger_local_ollama]
elif fournisseur == "mistral": ordre_repli = [interroger_mistral, interroger_groq, interroger_gemini, interroger_huggingface, interroger_local_ollama]
elif fournisseur == "huggingface": ordre_repli = [interroger_huggingface, interroger_cloudflare, interroger_groq, interroger_gemini, interroger_local_ollama]
elif fournisseur == "cloudflare": ordre_repli = [interroger_cloudflare, interroger_huggingface, interroger_groq, interroger_gemini, interroger_local_ollama]
else: ordre_repli = [interroger_local_ollama, interroger_gemini, interroger_groq]
# 🔄 Ordre de cascade recentré sur OpenRouter (Gratuit), Gemini et le Local
if fournisseur == "gemini":
ordre_repli = [interroger_gemini, interroger_openrouter, interroger_local_ollama]
elif fournisseur == "openrouter_code":
ordre_repli = [interroger_openrouter, interroger_gemini, interroger_local_ollama]
elif fournisseur == "openrouter_chat":
ordre_repli = [interroger_openrouter, interroger_gemini, interroger_local_ollama]
else:
ordre_repli = [interroger_local_ollama, interroger_openrouter, interroger_gemini]
for fonction_api in ordre_repli:
try:
# Transfert du 'fournisseur' cible pour qu'OpenRouter sache s'il doit appeler un modèle Code ou Chat
if fonction_api.__name__ == 'interroger_openrouter':
texte, couleur, nom_fournisseur, nom_modele = fonction_api(prompt_securise, type_modele=fournisseur)
else:
texte, couleur, nom_fournisseur, nom_modele = fonction_api(prompt_securise)
if texte:
return texte, couleur, nom_fournisseur, nom_modele
except Exception as e:
+57 -30
View File
@@ -1,36 +1,63 @@
import os
import time
import openai
from openai import OpenAI
from modules.logger import log_event
def interroger_openrouter(prompt_securise):
"""Module dédié à OpenRouter.ai pour accéder à +100 modèles gratuitement."""
api_key = os.getenv("OPENROUTER_API_KEY")
if not api_key: raise Exception("Clé API OpenRouter manquante.")
# Client compatible OpenAI pointant vers l'agrégateur OpenRouter
client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key=api_key)
# Liste de modèles 100% gratuits et performants sur OpenRouter
modeles = [
"meta-llama/llama-3.1-8b-instruct:free",
"mistralai/mistral-7b-instruct:free",
"google/gemma-2-9b-it:free",
"microsoft/phi-3-mini-128k-instruct:free"
]
for modele in modeles:
try:
resp = client.chat.completions.create(
model=modele,
messages=[
{"role": "system", "content": "Réponds en français et en format Markdown."},
{"role": "user", "content": prompt_securise}
]
# Initialisation du client OpenRouter avec l'API compatible OpenAI
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.getenv("OPENROUTER_API_KEY", "VOTRE_CLE_ICI") # À définir dans le .env
)
if resp and resp.choices:
log_event("INFO", f"OPENROUTER-{modele}", "Succès de la requête.")
return resp.choices[0].message.content, "#8b5cf6", "OPENROUTER (Gratuit)", modele
except Exception as e:
log_event("WARNING", f"OPENROUTER-{modele}", f"Erreur: {e}")
raise Exception("Tous les modèles gratuits OpenRouter ont échoué.")
def interroger_openrouter(prompt, type_modele="openrouter_chat", max_retries=3):
"""
Interroge l'API OpenRouter avec gestion des erreurs 402 (Plafond) et 429 (Rate Limit).
Sélectionne un modèle gratuit selon l'intention (Chat ou Code).
"""
# Sélection des modèles 100% gratuits et performants sur OpenRouter
if type_modele == "openrouter_code":
nom_modele_api = "qwen/qwen-2.5-coder-32b-instruct:free"
nom_affichage = "OpenRouter (Qwen Coder - Gratuit)"
couleur = "#10a37f" # Vert émeraude
else:
nom_modele_api = "meta-llama/llama-3.1-8b-instruct:free"
nom_affichage = "OpenRouter (Llama 3.1 - Gratuit)"
couleur = "#4a90e2" # Bleu clair
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}]
)
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é. 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.")
except Exception as e:
log_event("ERROR", "OPENROUTER", f"Erreur inattendue : {e}")
raise e
return None, None, None, None
+8 -10
View File
@@ -33,26 +33,24 @@ async def handle_chat_request(request, session):
liste_fichiers_str = ', '.join(file_names) if file_names else 'Aucun fichier'
log_event("INFO", "SYSTEM", f"Requête reçue. Fichiers joints : {liste_fichiers_str}")
# L'IA Local (Qwen) orchestre la décision !
# L'IA Local (Qwen) orchestre la décision ! Focus sur l'efficience.
sec_prompt = f"""Tu es l'Orchestrateur système. Analyse la requête et choisis le meilleur fournisseur IA :
- "gemini" : (OBLIGATOIRE si fichiers joints), rédaction complexe, comparaisons ou images.
- "groq" : texte ultra-rapide.
- "deepseek" : code, mathématiques, logique complexe.
- "mistral" : rédaction française soignée.
- "huggingface" : modèles open-source.
- "cloudflare" : requêtes générales.
- "local" : questions basiques, salutations.
Renvoie STRICTEMENT un JSON : {{"intention": "Résumé...", "fournisseur": "gemini|groq|deepseek|mistral|huggingface|cloudflare|local"}}
- "gemini" : (OBLIGATOIRE si fichiers joints), rédaction complexe, comparaisons ou recherches web.
- "openrouter_chat" : requêtes générales, texte rapide, traduction, bureautique (Modèles gratuits).
- "openrouter_code" : programmation, scripts, mathématiques, logique (Modèles gratuits).
- "local" : salutations basiques, questions très simples.
Renvoie STRICTEMENT un JSON : {{"intention": "Résumé...", "fournisseur": "gemini|openrouter_chat|openrouter_code|local"}}
Requête : {prompt}"""
try:
# Qwen 2.5 3B reste le meilleur compromis VRAM/Efficience pour votre GTX 1650
texte_routeur, _, _, _ = interroger_local_ollama(sec_prompt, "qwen2.5:3b")
decision = nettoyer_decision_router(texte_routeur)
except Exception:
decision = {"intention": "Analyse de secours", "fournisseur": "gemini"}
intention = decision.get('intention', 'Analyse')
fournisseur = decision.get('fournisseur', 'gemini').lower()
fournisseur = decision.get('fournisseur', 'openrouter_chat').lower()
# Sécurité Absolue Fichiers -> Gemini (Fenêtre de contexte maximale)
if file_names:
+11
View File
@@ -0,0 +1,11 @@
python-fasthtml
openai
google-generativeai
psutil
pandas
openpyxl
reportlab
requests
beautifulsoup4
python-dotenv
uvicorn