maj auto 2

This commit is contained in:
xavier committed 2026-08-16 23:26:07 +02:00
1 parent d47bd67391
commit f91b5ae215
11 files changed
+647 -477

No files matched your search

+32
View File
@@ -0,0 +1,32 @@
import os
from dotenv import load_dotenv
from openai import OpenAI
from groq import Groq
from google import genai
load_dotenv()
local_client = OpenAI(base_url="http://192.168.1.20:11434/v1", api_key="ollama")
groq_client = Groq(api_key=os.getenv("GROQ_API_KEY"))
gemini_client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
def interroger_gemini_cascade(prompt):
modeles_a_tester = ["gemini-3.1-pro-preview", "gemini-3.1-pro", "gemini-2.5-pro", "gemini-3.7-flash", "gemini-3.6-flash"]
for nom_modele in modeles_a_tester:
try:
config = {"system_instruction": "Réponds toujours dans la langue de l'utilisateur. Utilise exclusivement le format Markdown pour les tableaux et la mise en forme. N'utilise JAMAIS de code LaTeX."}
chat = gemini_client.chats.create(model=nom_modele, config=config)
ia_response = chat.send_message(prompt)
if not ia_response.text:
raise Exception("Réponse vide de Google.")
return ia_response.text, nom_modele
except Exception:
continue
raise Exception("Tous les modèles Gemini sont indisponibles actuellement.")
def appeler_groq_api(prompt_text):
resp = groq_client.chat.completions.create(
messages=[{"role": "system", "content": "Réponds dans la langue de l'utilisateur. Tu as accès aux recherches web fournies. Utilise uniquement Markdown. Pas de code LaTeX."}, {"role": "user", "content": prompt_text}],
model="llama-3.3-70b-versatile"
)
return resp.choices[0].message.content, "#f97316", "GROQ", "llama-3.3-70b"
+27
View File
@@ -0,0 +1,27 @@
import os
import json
import time
HISTORY_FILE = "aethas_history.json"
def load_history():
if not os.path.exists(HISTORY_FILE):
with open(HISTORY_FILE, 'w', encoding='utf-8') as f:
json.dump({}, f)
with open(HISTORY_FILE, 'r', encoding='utf-8') as f:
return json.load(f)
def save_history(history):
with open(HISTORY_FILE, 'w', encoding='utf-8') as f:
json.dump(history, f, indent=4)
def nettoyer_vieilles_discussions():
history = load_history()
now = time.time()
un_an_en_secondes = 365 * 24 * 60 * 60
a_supprimer = [cid for cid, data in history.items() if not data.get('pinned', False) and now - data.get('timestamp', now) > un_an_en_secondes]
if a_supprimer:
for cid in a_supprimer:
del history[cid]
save_history(history)
print(f"🧹 AETHAS CORE : Nettoyage auto terminé. {len(a_supprimer)} discussion(s) supprimée(s).")
+14
View File
@@ -0,0 +1,14 @@
import json
import re
def nettoyer_decision_router(raw_text):
try:
clean = re.sub(r'```(?:json)?\s*', '', raw_text)
clean = clean.replace('```', '').strip()
start = clean.find('{')
end = clean.rfind('}') + 1
if start != -1 and end != 0:
return json.loads(clean[start:end])
except Exception:
pass
return {"intention": "Analyse", "fournisseur": "gemini"}
+42
View File
@@ -0,0 +1,42 @@
import requests
from bs4 import BeautifulSoup
def rechercher_sur_google(requete):
try:
url = "https://lite.duckduckgo.com/lite/"
data = {'q': requete}
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
resp = requests.post(url, data=data, headers=headers, timeout=5)
soup = BeautifulSoup(resp.text, 'html.parser')
urls = []
for a in soup.find_all('a', class_='result-link', href=True):
href = a['href']
if href.startswith('http') and 'duckduckgo' not in href:
urls.append(href)
if len(urls) >= 5:
break
if not urls:
for a in soup.find_all('a', href=True):
href = a['href']
if href.startswith('http') and 'duckduckgo' not in href and href not in urls:
urls.append(href)
if len(urls) >= 5:
break
return urls[:5]
except Exception as e:
print(f"Erreur recherche web: {e}")
return []
def extraire_contenu_urls(urls_list):
scraped_text = ""
for url in urls_list:
try:
resp = requests.get(url, timeout=5, headers={"User-Agent": "Mozilla/5.0"})
soup = BeautifulSoup(resp.text, 'html.parser')
for script in soup(["script", "style", "nav", "footer"]):
script.extract()
scraped_text += f"\n\n--- Source web extraite ({url}) ---\n{soup.get_text(separator=' ', strip=True)[:3000]}"
except Exception as e:
scraped_text += f"\n\n[Impossible de récupérer {url}: {e}]"
return scraped_text
+49
View File
@@ -0,0 +1,49 @@
from fasthtml.common import *
from modules.database import load_history
def render_user_msg(text):
return Div(P(text, style="margin:0; font-weight:bold; white-space: pre-wrap;"), cls="user-bubble")
def render_ai_msg(text, intention, nom_fournisseur, nom_modele, couleur):
encart_info = Div(
Span(f"🎯 {intention}", style="margin-right: 10px; color:#aaa; font-size:0.8em;"),
Span(f"🏢 {nom_fournisseur}", style="margin-right: 10px; color:#aaa; font-size:0.8em;"),
Span(f"🧠 {nom_modele}", style=f"margin-right: 10px; color:{couleur}; font-weight:bold; font-size:0.8em;"),
style="border-bottom: 1px solid #333; padding-bottom: 10px; margin-bottom: 15px; display: flex; flex-wrap: wrap; gap: 5px;"
)
actions = Div(
Button("📄 PDF", onclick="downloadResponsePDF(this)", cls="msg-action-btn", title="Télécharger en PDF"),
Button("📘 DOC", onclick="downloadResponseDOC(this)", cls="msg-action-btn", title="Télécharger en Word"),
Button("📝 TXT", onclick="downloadResponseTXT(this)", cls="msg-action-btn", title="Télécharger en Texte"),
Button("🗄️ JSON", onclick="downloadResponseJSON(this)", cls="msg-action-btn", title="Télécharger en JSON"),
Button("💬 WhatsApp", onclick="shareWhatsApp(this)", cls="msg-action-btn", title="Partager sur WhatsApp"),
Button("📧 Email", onclick="shareEmail(this)", cls="msg-action-btn", title="Envoyer par Email"),
cls="msg-actions"
)
return Div(
encart_info,
Div(text, cls="markdown-raw", style="display:none;"),
Div(cls="markdown-rendered", style="line-height: 1.6;"),
actions,
cls="ai-bubble", style=f"border-left: 4px solid {couleur};"
)
def render_sidebar():
history = load_history()
sorted_chats = sorted(history.items(), key=lambda x: (not x[1].get('pinned', False), -x[1].get('timestamp', 0)))
items = []
for chat_id, data in sorted_chats:
pin_icon = "📌" if data.get('pinned', False) else "📍"
items.append(
Div(
A(Span(data['title'], style="color:inherit;"), href=f"/load_chat/{chat_id}", cls="history-link"),
Button(pin_icon, cls="history-btn", hx_post=f"/pin/{chat_id}", hx_target="#sidebar-content", hx_swap="outerHTML"),
Button("✏️", cls="history-btn", hx_post=f"/rename/{chat_id}", hx_prompt="Nouveau nom :", hx_target="#sidebar-content", hx_swap="outerHTML"),
Button("🗑️", cls="history-btn", hx_post=f"/delete/{chat_id}", hx_target="#sidebar-content", hx_swap="outerHTML"),
cls="history-item", id=f"chat-item-{chat_id}"
)
)
return Div(*items, id="sidebar-content", cls="sidebar-history", hx_swap_oob="true")