import os import json from dotenv import load_dotenv from fasthtml.common import * from openai import OpenAI # Chargement du coffre-fort des clés API load_dotenv() # Petit test pour vérifier que Python trouve bien les clés au démarrage print("Vérification des API :") print("- Groq chargée :", "✅" if os.getenv("GROQ_API_KEY") else "❌") print("- Gemini chargée :", "✅" if os.getenv("GEMINI_API_KEY") else "❌") # Initialisation de l'application FastHTML app, rt = fast_app() # Configuration du client local (Qwen) client = OpenAI( base_url="http://192.168.1.20:11434/v1", api_key="ollama" ) # Route principale : l'interface utilisateur @rt('/') def get(): return Titled("Aethas38 - Orchestrateur", Main( H1("Interface de Test - Qwen 2.5 (3B)"), Form( Input(type="text", name="prompt", placeholder="Posez votre question à Qwen...", style="width: 100%; padding: 10px; margin-bottom: 10px;"), Button("Envoyer la requête", type="submit", style="padding: 10px 20px; cursor: pointer;"), hx_post="/chat", # Envoie la requête à la route /chat hx_target="#result", # Injecte la réponse dans la div "result" hx_indicator="#loading" # Affiche un indicateur de chargement ), Div("Traitement en cours par le serveur Aethas38...", id="loading", cls="htmx-indicator", style="color: gray; font-style: italic; margin-top: 10px;"), Div(id="result", style="margin-top: 20px; padding: 15px; border: 1px solid #444; border-radius: 5px; background-color: #222; color: white;"), cls="container" ) ) # Route API : Traitement de la requête par l'IA @rt('/chat') def post(prompt: str): try: # 1. Le Prompt Système amélioré pour éviter les pièges router_prompt = """Tu es l'Aiguilleur (Routeur) du projet Aethas38. Analyse la demande de l'utilisateur et choisis le fournisseur d'IA le plus adapté selon ces règles strictes : - "groq" : programmation, code, scripts, mathématiques, logique, informatique. - "gemini" : rédaction, recettes de cuisine, culture générale, histoire, résumés, art. - "local" : UNIQUEMENT pour les salutations (bonjour, test, coucou) ou les banalités très courtes. Format de réponse obligatoire : un objet JSON strict. AUCUN texte d'accompagnement. Exemple 1 : {"intention": "créer un script", "fournisseur": "groq"} Exemple 2 : {"intention": "recette de gâteau", "fournisseur": "gemini"} """ # 2. On interroge notre Qwen local (la GTX 1650 bosse !) response = client.chat.completions.create( model="qwen2.5:3b", messages=[ {"role": "system", "content": router_prompt}, {"role": "user", "content": prompt} ], temperature=0.1 # Température basse pour qu'il soit très précis et formel ) # 3. On récupère et on lit sa décision brute raw_decision = response.choices[0].message.content # 4. On l'affiche sur l'interface de test (temporaire, pour voir la magie opérer) return Div( P(f"🗣️ Votre question : {prompt}", style="color: #888;"), P("🧠 Décision de l'Orchestrateur (Qwen) :", style="color: #00d2ff; font-weight: bold; margin-top: 10px;"), Pre(raw_decision, style="background: #111; padding: 10px; border-radius: 5px; color: #0f0;"), style="border-left: 4px solid #00d2ff; padding-left: 15px; margin-top: 15px;" ) except Exception as e: return P(f"Erreur de l'orchestrateur : {e}", style="color: red; font-weight: bold;") # Lancement du serveur local if __name__ == '__main__': serve(port=5001)