maj auto 1

This commit is contained in:
xavier committed 2026-08-18 09:41:42 +02:00
1 parent e6cd509ffd
commit 950a0034aa
11 files changed
+223 -67

No files matched your search

+31 -30
View File
@@ -5,8 +5,10 @@ from fasthtml.common import *
from modules.database import load_history, save_history
from modules.scraper import rechercher_sur_google, extraire_contenu_urls
from modules.router import nettoyer_decision_router
from modules.ai_engine import local_client, interroger_gemini_cascade, appeler_groq_api
from modules.ai_local import interroger_local_ollama
from modules.ai_engine import executer_requete_ia
from modules.ui_components import render_user_msg, render_ai_msg, render_sidebar
from modules.logger import log_event
async def handle_chat_request(request, session):
start_time = time.time()
@@ -19,6 +21,7 @@ async def handle_chat_request(request, session):
history = load_history()
# Extraction éphémère en RAM
file_summary = []
file_names = []
for f in files[:10]:
@@ -28,22 +31,33 @@ async def handle_chat_request(request, session):
file_summary.append(f"\n--- Fichier: {f.filename} ---\n{content.decode('utf-8', errors='ignore')}")
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}")
sec_prompt = f"""Tu es l'Aiguilleur système.
RÈGLES STRICTES DE ROUTAGE :
1. "gemini" : OBLIGATOIRE si des fichiers sont joints à analyser (ex: {liste_fichiers_str}), ou pour des requêtes de rédaction complexe, comparaisons, ou recherche web.
2. "groq" : Pour le code, la programmation, l'architecture système ou les mathématiques.
3. "local" : UNIQUEMENT pour les salutations, blagues ou questions très simples sans fichiers. NE JAMAIS utiliser pour analyser des documents.
Renvoie STRICTEMENT un JSON : {{"intention": "Résumé de l'intention...", "fournisseur": "gemini|groq|local"}}
# L'IA Local (Qwen) orchestre la décision !
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"}}
Requête : {prompt}"""
router_res = local_client.chat.completions.create(model="qwen2.5:3b", messages=[{"role": "system", "content": "JSON uniquement."}, {"role": "user", "content": sec_prompt}], temperature=0.1)
decision = nettoyer_decision_router(router_res.choices[0].message.content)
intention, fournisseur = decision.get('intention', 'Analyse'), decision.get('fournisseur', 'gemini').lower()
try:
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()
# Sécurité Absolue Fichiers -> Gemini (Fenêtre de contexte maximale)
if file_names:
fournisseur = "gemini"
intention += " (Forcé Gemini via Sécurité)"
intention += " (Forcé Gemini via Sécurité Fichiers)"
urls = re.findall(r'https?://[^\s]+', prompt)
mots_cles = ["cherche", "recherche", "sur internet", "sur le web", "sur le net", "va sur", "trouve", "site", "donne", "historique", "version"]
@@ -54,25 +68,10 @@ async def handle_chat_request(request, session):
full_prompt = prompt + ("\n" + "\n".join(file_summary) if file_summary else "")
if web_text:
full_prompt += f"\n\n[Contexte web extrait :\n{web_text}\nUtilise ces informations pour répondre précisément.]"
full_prompt += f"\n\n[Contexte web extrait :\n{web_text}\nUtilise ces informations pour répondre.]"
if fournisseur == "gemini":
try:
reponse, modele = interroger_gemini_cascade(full_prompt)
couleur, fournisseur_nom = "#3b82f6", "GOOGLE GEMINI"
except Exception:
reponse, couleur, fournisseur_nom, modele = appeler_groq_api(full_prompt)
fournisseur_nom, intention = "GROQ (Secours)", intention + " (Secours)"
elif fournisseur == "groq":
try:
reponse, couleur, fournisseur_nom, modele = appeler_groq_api(full_prompt)
except Exception as e:
reponse, modele = interroger_gemini_cascade(full_prompt)
couleur, fournisseur_nom = "#3b82f6", "GOOGLE GEMINI"
intention += " (Secours suite Erreur Groq)"
else:
res_local = local_client.chat.completions.create(model="qwen2.5:3b", messages=[{"role": "system", "content": "Réponds en français."}, {"role": "user", "content": full_prompt}])
reponse, couleur, fournisseur_nom, modele = res_local.choices[0].message.content, "#10b981", "SERVEUR LOCAL", "qwen2.5:3b"
# Délégation de l'exécution au Moteur d'IA (Cascade)
reponse, couleur, fournisseur_nom, modele = executer_requete_ia(fournisseur, full_prompt)
if chat_id not in history:
history[chat_id] = {"title": (prompt[:30] if prompt else "Discussion") + "...", "pinned": False, "timestamp": time.time(), "messages": []}
@@ -88,7 +87,9 @@ async def handle_chat_request(request, session):
history[chat_id]['messages'].append({"role": "ai", "content": reponse, "intention": intention, "fournisseur": fournisseur_nom, "modele": modele, "couleur": couleur, "execution_time": execution_time})
save_history(history)
log_event("INFO", fournisseur_nom, f"Réponse générée en {execution_time}s.")
return render_user_msg(display_msg), render_ai_msg(reponse, intention, fournisseur_nom, modele, couleur, execution_time), Script("renderMarkdown();"), render_sidebar()
except Exception as e:
return Div(f"Erreur : {e}", style="color:red; background:#300; padding:15px; border-radius:10px;")
log_event("CRITICAL", "SYSTEM", f"Erreur critique dans handle_chat_request: {e}")
return Div(f"Erreur système : {e}", style="color:red; background:#300; padding:15px; border-radius:10px;")