import uuid import time import re 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.ui_components import render_user_msg, render_ai_msg, render_sidebar async def handle_chat_request(request, session): try: form = await request.form() prompt = form.get("prompt", "") chat_id = form.get("chat_id", str(uuid.uuid4())) files = form.getlist("files") session['current_chat_id'] = chat_id history = load_history() sec_prompt = f"""Analyse et route cette demande. Si recherche web nécessaire ("va sur", "site", "historique", "version", "cherche", etc.) -> choisis "gemini". Si code/technique -> "groq". Sinon -> "local". Renvoie STRICTEMENT un JSON : {{"intention": "...", "fournisseur": "gemini|groq|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() 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"] if any(m in prompt.lower() for m in mots_cles): urls.extend(rechercher_sur_google(prompt)) web_text = extraire_contenu_urls(list(set(urls))) if urls else "" file_summary = [] file_names = [] for f in files[:10]: if f and f.filename: file_names.append(f.filename) content = await f.read() file_summary.append(f"\n--- Fichier: {f.filename} ---\n{content.decode('utf-8', errors='ignore')}") 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.]" 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": reponse, couleur, fournisseur_nom, modele = appeler_groq_api(full_prompt) 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" if chat_id not in history: history[chat_id] = {"title": (prompt[:30] if prompt else "Discussion") + "...", "pinned": False, "timestamp": time.time(), "messages": []} display_msg = prompt + (f"\n📎 [Fichiers: {', '.join(file_names)}]" if file_names else "") history[chat_id]['messages'].append({"role": "user", "content": display_msg}) history[chat_id]['messages'].append({"role": "ai", "content": reponse, "intention": intention, "fournisseur": fournisseur_nom, "modele": modele, "couleur": couleur}) save_history(history) return render_user_msg(display_msg), render_ai_msg(reponse, intention, fournisseur_nom, modele, couleur), Script("renderMarkdown();"), render_sidebar() except Exception as e: return Div(f"Erreur : {e}", style="color:red; background:#300; padding:15px; border-radius:10px;")