Public Access
feat: Intégration de l'API OpenRouter, suppression de Groq et mise à jour du README
This commit is contained in:
1 parent
909e2e995a
commit
317ecddc56
5 files changed
+130
-123
No files matched your search
@@ -1,93 +1,61 @@
|
|||||||
# Aethas38 - Multi-IA Orchestrateur (Minecraft-Tech Edition)
|
# Aethas38 - Multi-IA Orchestrateur (Minecraft-Tech Edition)
|
||||||
|
|
||||||
Plateforme SaaS d'IA modulaire : Orchestrateur local, routeur intelligent, sécurisé et facturable.
|
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)
|
## 📋 To-Do List (Roadmap)
|
||||||
|
|
||||||
### Phase 1 & 2 : Infrastructure & Backend de Base ✅
|
### Phase 1 & 2 : Infrastructure & Backend de Base ✅
|
||||||
- [x] Installation Docker, Nginx, Pare-feu, Gitea/GitHub
|
- [x] Installation Docker, Nginx (NPM), Pare-feu, Gitea/GitHub
|
||||||
- [x] Serveur Local Ollama (Qwen 3B) + FastHTML
|
- [x] Serveur Local Ollama (Qwen 3B) + FastHTML (Adapté aux processeurs limités type AMD Phenom)
|
||||||
- [x] Routeur Multi-IA (Groq, Gemini, Local) avec système de cascade et directives d'aiguillage strictes
|
- [x] Routeur Multi-IA (OpenRouter, 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] Continuité de service : IA de secours automatique
|
||||||
|
|
||||||
### Phase 3 : Refonte UI & Expérience Utilisateur ✅
|
### Phase 3 : Refonte UI & Expérience Utilisateur ✅
|
||||||
- [x] Thème "Minecraft-Tech" (Inspiré serveurs/redstone) compatible Mobile (Responsive)
|
- [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] 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] 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] Export modulaire et propre (PDF, DOC, TXT, JSON, ZIP)
|
||||||
- [x] Boutons de partage direct (WhatsApp, Email) avec nettoyage automatique des balises HTML brutes
|
- [x] Boutons de partage direct (WhatsApp, Email)
|
||||||
- [x] Script de nettoyage automatique : Suppression des discussions de > 365 jours
|
|
||||||
- [x] Indicateur d'avancement dynamique (Loader Néon) pendant le traitement des IA
|
- [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é
|
### Phase 4 : Gestion des Utilisateurs & Sécurité Légale
|
||||||
- [ ] Céer un lien Paypal pour les dons des utilisateurs.
|
- [ ] 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 logiciel à installer avec le serveur (déporter tout ce qui peut l'être comme la création de pdf, docx, html, etc.)
|
- [ ] Mettre en place une bibliothèque logicielle autonome sur le serveur (création PDF, DOCX, etc.).
|
||||||
- [ ] Choix entre l'utilisation de la version payante ou gratuite. Routage suivant le choix.
|
- [ ] Routage automatique (Gratuit vs Payant) sélectionné par l'utilisateur.
|
||||||
- [ ] Système de connexion sécurisé (Mots de passe cryptés)
|
- [ ] 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).
|
||||||
- [ ] Fail2Ban (Blocage 15 mins après 5 erreurs)
|
- [ ] Sécurité Légère : Fail2Ban, protection Bruteforce et DDoS. **Blocage total des accès VPN**.
|
||||||
- [ ] Intégration SMTP (`mail.aethas38.duckdns.org`) pour mot de passe oublié et notifications de thèmes spécifiques
|
- [ ] Conformité légale (RGPD) : Journalisation stricte des IP par client conservée 1 an.
|
||||||
- [ ] Gestion des rôles : Admin (Xavier, Céline), Famille (Anaëlle, Audric, Renan), Testeur (Nogapra) et Externes. Testeur juste accès à la partie gratuite.
|
- [ ] Multilinguisme : Adaptation automatique de la langue du site via la géolocalisation de l'IP.
|
||||||
- [ ] Prévoir un script automatique envoyant un mail sympathique aux utilisateurs lors de leur anniversaire.
|
|
||||||
|
|
||||||
### Phase 5 : Sécurité Financière & Facturation Exacte 💰
|
### 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.
|
||||||
- [ ] 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.
|
||||||
- [ ] Gestion des comptes et provisions (CB) avec test du restant financier avant validation
|
- [ ] Module de conversion des devises en temps réel (Taux du jour) pour un affichage transparent.
|
||||||
- [ ] Règles d'exceptions Administrateurs & Famille (Pas de provision nécessaire, rattachés au master-compte Xavier/Céline)
|
- [ ] **Utilisateurs Privilégiés (Zéro Marge) :** Xavier, Céline, Anaëlle, Renan et Audric. Autorisation de virements manuels pour la cagnotte.
|
||||||
- [ ] Majoration invisible de 15% appliquée automatiquement pour les comptes Externes
|
- [ ] **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).
|
||||||
- [ ] 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)
|
- [ ] Export comptable Excel (TCD) par utilisateur via Pandas/Openpyxl et archivage PDF automatisé.
|
||||||
- [ ] Routage Conditionnel Payant : Utiliser *toutes* les IA en adéquation avec le thème de la requête
|
|
||||||
|
|
||||||
### Phase 6 : Nouvelles Capacités IA (Spécialisations & Modèles) 🤖
|
### 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 |
|
| 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 |
|
| **Orchestration & Tri** | Qwen 2.5 (3B) | 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) |
|
| **Bureautique & Code** | Llama 3.1 / Qwen 2.5 Coder | OpenRouter API (Gratuit) | Programmation, scripts, macros VBA, mathématiques |
|
||||||
| **Serveur / Logs** | Llama 3.3 (8B / 70B) | Groq API | Analyse crashs Prism Launcher, Bash, Docker (Gratuit / Rapide) |
|
| **Images HD / Fichiers** | Gemini 2.0 Flash / Pro | Google AI Studio | Analyse d'images/vidéos et documents joints |
|
||||||
| **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) |
|
|
||||||
|
|
||||||
### Phase 7 : RAG & Maintenance
|
### Phase 7 & 8 : Maintenance & Déploiement
|
||||||
- [ ] "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 (Beszel / Psutil) réservé à l'Admin.
|
||||||
- [ ] Script de surveillance de l'espace disque du serveur. Affichage d'une barre d'état (statuts des disques, remplissage, utilisations pour Xavier)
|
- [ ] Sauvegarde automatique : Compression du site toutes les 6 heures vers GDrive (`25-BACKUP SITE`), 4 versions conservées.
|
||||||
- [ ] Création de logs centralisés consultables et téléchargeables par l'Admin
|
- [ ] 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.
|
||||||
### 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
|
|
||||||
|
|
||||||
## 📷 Vidéosurveillance & Détection Intelligente
|
## 📷 Vidéosurveillance & Détection Intelligente
|
||||||
|
*(Voir configuration Frigate locale et Google Coral TPU existante)*
|
||||||
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].
|
|
||||||
+17
-14
@@ -1,11 +1,8 @@
|
|||||||
from modules.logger import log_event
|
from modules.logger import log_event
|
||||||
from modules.ai_gemini import interroger_gemini
|
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
|
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 = (
|
SYSTEM_CONFIDENTIALITY_INSTRUCTION = (
|
||||||
"RÈGLE DE CONFIDENTIALITÉ ABSOLUE : Tu es un assistant intégré à la plateforme privée Aethas38. "
|
"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):
|
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}"
|
prompt_securise = f"{SYSTEM_CONFIDENTIALITY_INSTRUCTION}\n\nRequête utilisateur :\n{prompt}"
|
||||||
|
|
||||||
# 🔄 Ordre de cascade intelligent défini par l'orchestrateur (repli automatique)
|
# 🔄 Ordre de cascade recentré sur OpenRouter (Gratuit), Gemini et le Local
|
||||||
if fournisseur == "gemini": ordre_repli = [interroger_gemini, interroger_groq, interroger_mistral, interroger_deepseek, interroger_huggingface, interroger_cloudflare, interroger_local_ollama]
|
if fournisseur == "gemini":
|
||||||
elif fournisseur == "groq": ordre_repli = [interroger_groq, interroger_mistral, interroger_deepseek, interroger_gemini, interroger_huggingface, interroger_cloudflare, interroger_local_ollama]
|
ordre_repli = [interroger_gemini, interroger_openrouter, interroger_local_ollama]
|
||||||
elif fournisseur == "deepseek": ordre_repli = [interroger_deepseek, interroger_gemini, interroger_groq, interroger_mistral, interroger_local_ollama]
|
elif fournisseur == "openrouter_code":
|
||||||
elif fournisseur == "mistral": ordre_repli = [interroger_mistral, interroger_groq, interroger_gemini, interroger_huggingface, interroger_local_ollama]
|
ordre_repli = [interroger_openrouter, interroger_gemini, interroger_local_ollama]
|
||||||
elif fournisseur == "huggingface": ordre_repli = [interroger_huggingface, interroger_cloudflare, interroger_groq, interroger_gemini, interroger_local_ollama]
|
elif fournisseur == "openrouter_chat":
|
||||||
elif fournisseur == "cloudflare": ordre_repli = [interroger_cloudflare, interroger_huggingface, interroger_groq, interroger_gemini, interroger_local_ollama]
|
ordre_repli = [interroger_openrouter, interroger_gemini, interroger_local_ollama]
|
||||||
else: ordre_repli = [interroger_local_ollama, interroger_gemini, interroger_groq]
|
else:
|
||||||
|
ordre_repli = [interroger_local_ollama, interroger_openrouter, interroger_gemini]
|
||||||
|
|
||||||
for fonction_api in ordre_repli:
|
for fonction_api in ordre_repli:
|
||||||
try:
|
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)
|
texte, couleur, nom_fournisseur, nom_modele = fonction_api(prompt_securise)
|
||||||
|
|
||||||
if texte:
|
if texte:
|
||||||
return texte, couleur, nom_fournisseur, nom_modele
|
return texte, couleur, nom_fournisseur, nom_modele
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
+57
-30
@@ -1,36 +1,63 @@
|
|||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
import openai
|
||||||
from openai import OpenAI
|
from openai import OpenAI
|
||||||
from modules.logger import log_event
|
from modules.logger import log_event
|
||||||
|
|
||||||
def interroger_openrouter(prompt_securise):
|
# Initialisation du client OpenRouter avec l'API compatible OpenAI
|
||||||
"""Module dédié à OpenRouter.ai pour accéder à +100 modèles gratuitement."""
|
client = OpenAI(
|
||||||
api_key = os.getenv("OPENROUTER_API_KEY")
|
base_url="https://openrouter.ai/api/v1",
|
||||||
if not api_key: raise Exception("Clé API OpenRouter manquante.")
|
api_key=os.getenv("OPENROUTER_API_KEY", "VOTRE_CLE_ICI") # À définir dans le .env
|
||||||
|
|
||||||
# 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}
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
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
@@ -33,26 +33,24 @@ async def handle_chat_request(request, session):
|
|||||||
liste_fichiers_str = ', '.join(file_names) if file_names else 'Aucun fichier'
|
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}")
|
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 :
|
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.
|
- "gemini" : (OBLIGATOIRE si fichiers joints), rédaction complexe, comparaisons ou recherches web.
|
||||||
- "groq" : texte ultra-rapide.
|
- "openrouter_chat" : requêtes générales, texte rapide, traduction, bureautique (Modèles gratuits).
|
||||||
- "deepseek" : code, mathématiques, logique complexe.
|
- "openrouter_code" : programmation, scripts, mathématiques, logique (Modèles gratuits).
|
||||||
- "mistral" : rédaction française soignée.
|
- "local" : salutations basiques, questions très simples.
|
||||||
- "huggingface" : modèles open-source.
|
Renvoie STRICTEMENT un JSON : {{"intention": "Résumé...", "fournisseur": "gemini|openrouter_chat|openrouter_code|local"}}
|
||||||
- "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"}}
|
|
||||||
Requête : {prompt}"""
|
Requête : {prompt}"""
|
||||||
|
|
||||||
try:
|
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")
|
texte_routeur, _, _, _ = interroger_local_ollama(sec_prompt, "qwen2.5:3b")
|
||||||
decision = nettoyer_decision_router(texte_routeur)
|
decision = nettoyer_decision_router(texte_routeur)
|
||||||
except Exception:
|
except Exception:
|
||||||
decision = {"intention": "Analyse de secours", "fournisseur": "gemini"}
|
decision = {"intention": "Analyse de secours", "fournisseur": "gemini"}
|
||||||
|
|
||||||
intention = decision.get('intention', 'Analyse')
|
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)
|
# Sécurité Absolue Fichiers -> Gemini (Fenêtre de contexte maximale)
|
||||||
if file_names:
|
if file_names:
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
python-fasthtml
|
||||||
|
openai
|
||||||
|
google-generativeai
|
||||||
|
psutil
|
||||||
|
pandas
|
||||||
|
openpyxl
|
||||||
|
reportlab
|
||||||
|
requests
|
||||||
|
beautifulsoup4
|
||||||
|
python-dotenv
|
||||||
|
uvicorn
|
||||||
Reference in new issue
Block a user