Spaces:
Sleeping
Sleeping
import os | |
import re | |
import json | |
import time | |
from typing import List, Dict, Any, Optional | |
from pathlib import Path | |
import tempfile | |
from smolagents import CodeAgent, MultiStepAgent, AgentError, PythonInterpreterTool | |
from models import ModelManager | |
from tools import search_web, scrape_website, read_file | |
# --- CLASSE ORCHESTRATEUR COMPLÈTE --- | |
class OrchestratorAgent(MultiStepAgent): | |
""" | |
Agent orchestrateur qui hérite de MultiStepAgent et implémente | |
les méthodes requises pour le prompt système et la réponse finale. | |
""" | |
def initialize_system_prompt(self) -> str: | |
"""Définit le prompt système pour l'agent orchestrateur.""" | |
return ( | |
"You are a world-class autonomous agent. Your goal is to fully answer the user's question. " | |
"To do so, you have access to a set of tools. " | |
"First, think step-by-step and lay out a plan to solve the problem. " | |
"Then, execute the plan by calling the tools in the required sequence. " | |
"Analyze the results of each tool call. If the plan is not working, reassess and create a new plan. " | |
"When you have the final answer, present it clearly to the user." | |
) | |
def render_final_answer(self, final_context: dict, final_response: str) -> str: | |
""" | |
Formate et retourne la réponse finale de l'agent. | |
""" | |
# Pour l'instant, nous retournons simplement la réponse brute du modèle. | |
return final_response | |
class UltraAgent: | |
""" | |
Agent ultra-puissant avec orchestration multi-modèles. | |
Utilise différents modèles spécialisés selon le type de tâche. | |
""" | |
def __init__(self, hf_token: Optional[str] = None): | |
"""Initialise l'UltraAgent et ses composants.""" | |
print("🚀 Initialisation de l'UltraAgent...") | |
self.hf_token = hf_token or os.getenv("HF_TOKEN") | |
self.model_manager = ModelManager(self.hf_token) | |
self.tools = [search_web, scrape_website, read_file, PythonInterpreterTool()] | |
self._init_specialized_agents() | |
self.conversation_history = [] | |
print("✅ UltraAgent initialisé avec succès!") | |
def _init_specialized_agents(self): | |
"""Initialise les agents spécialisés.""" | |
try: | |
self.orchestrator = OrchestratorAgent( | |
model=self.model_manager.get_orchestrator(), | |
tools=self.tools, | |
max_steps=15, | |
planning_interval=3 | |
) | |
self.code_agent = CodeAgent( | |
model=self.model_manager.get_code_agent(), | |
tools=[PythonInterpreterTool()], | |
additional_authorized_imports=["requests", "pandas", "numpy", "matplotlib", "seaborn", "scipy", "sklearn"] | |
) | |
print("✅ Agents spécialisés initialisés") | |
except Exception as e: | |
print(f"❌ Erreur lors de l'initialisation des agents: {e}") | |
raise | |
def __call__(self, question: str) -> str: | |
"""Point d'entrée principal de l'agent.""" | |
print("\n" + "="*80) | |
print(f"🧠 ULTRA-AGENT - Nouvelle question reçue\nQuestion: {question[:200]}{'...' if len(question) > 200 else ''}") | |
print("="*80) | |
try: | |
self.conversation_history.append({"role": "user", "content": question, "timestamp": time.time()}) | |
strategy = self._analyze_question(question) | |
print(f"📋 Stratégie sélectionnée: {strategy['type']}") | |
response = self._execute_strategy(question, strategy) | |
self.conversation_history.append({"role": "assistant", "content": response, "strategy": strategy, "timestamp": time.time()}) | |
print(f"✅ Réponse générée avec succès ({len(response)} caractères)") | |
return response | |
except Exception as e: | |
error_msg = f"❌ Erreur critique dans l'UltraAgent: {e}" | |
print(error_msg) | |
try: | |
print("🔄 Tentative de récupération avec le modèle de raisonnement...") | |
fallback_response = self._fallback_reasoning(question, str(e)) | |
return fallback_response | |
except Exception as fallback_e: | |
final_error = f"Je rencontre des difficultés techniques. Erreur: {str(fallback_e)[:200]}" | |
print(f"❌ La récupération a également échoué: {fallback_e}") | |
return final_error | |
def _analyze_question(self, question: str) -> Dict[str, Any]: | |
"""Analyse la question pour déterminer la meilleure stratégie.""" | |
# Cette fonction de scoring simple reste la même | |
question_lower = question.lower() | |
vision_keywords = ['image', 'photo', 'picture', 'visual', 'voir', 'regarder', 'analyser l\'image', 'screenshot'] | |
code_keywords = ['code', 'program', 'script', 'algorithm', 'python', 'javascript', 'sql', 'debug', 'programmer'] | |
if any(kw in question_lower for kw in vision_keywords): | |
return {"type": "vision"} | |
if any(kw in question_lower for kw in code_keywords): | |
return {"type": "code"} | |
return {"type": "general"} # Simplification de la stratégie pour le débogage | |
def _execute_strategy(self, question: str, strategy: Dict[str, Any]) -> str: | |
"""Exécute la stratégie déterminée.""" | |
strategy_type = strategy["type"] | |
try: | |
if strategy_type == "vision": | |
return self._handle_vision_task(question) | |
elif strategy_type == "code": | |
return self._handle_code_task(question) | |
else: # general, search_web, file_processing, reasoning | |
return self._handle_general_task(question) | |
except Exception as e: | |
print(f"❌ Erreur dans l'exécution de la stratégie {strategy_type}: {e}") | |
raise e # Fait remonter l'erreur pour la gestion centrale | |
def _handle_vision_task(self, question: str) -> str: | |
"""Gère les tâches de vision.""" | |
print("👁️ Traitement avec le modèle de vision...") | |
response = self.model_manager.get_vision_model()(question) | |
return f"🔍 Analyse visuelle:\n{response}" | |
def _handle_code_task(self, question: str) -> str: | |
"""Gère les tâches de code.""" | |
print("💻 Traitement avec l'agent de code...") | |
return self.code_agent.run(question) | |
def _handle_general_task(self, question: str) -> str: | |
"""Gère toutes les autres tâches avec l'orchestrateur.""" | |
print("🎯 Traitement général avec l'orchestrateur...") | |
context = self._get_conversation_context() | |
enhanced_prompt = f"{context}\nQuestion actuelle: {question}" | |
return self.orchestrator.run(enhanced_prompt) | |
def _fallback_reasoning(self, question: str, error: str) -> str: | |
"""Fallback avec le modèle de raisonnement.""" | |
fallback_prompt = f"An error occurred while processing the question. Question: '{question}'. Error: '{error}'. Provide the best possible answer, explaining the limitations due to the error." | |
return self.model_manager.get_reasoning_model()(fallback_prompt) | |
def _get_conversation_context(self, max_exchanges: int = 3) -> str: | |
"""Récupère le contexte des échanges récents.""" | |
if not self.conversation_history: return "" | |
recent_history = self.conversation_history[-max_exchanges*2:] | |
context_parts = ["Contexte de la conversation récente:"] | |
for entry in recent_history: | |
role = "Utilisateur" if entry["role"] == "user" else "Assistant" | |
content = str(entry["content"])[:200] | |
context_parts.append(f"{role}: {content}") | |
return "\n".join(context_parts) | |
class BasicAgent: | |
""" | |
Classe de compatibilité pour remplacer l'ancien BasicAgent dans app.py. | |
Elle utilise l'UltraAgent en arrière-plan pour toute la logique. | |
""" | |
def __init__(self): | |
"""Initialise le BasicAgent en créant une instance de l'UltraAgent.""" | |
print("🚀 Initialisation du BasicAgent (powered by UltraAgent)...") | |
try: | |
# Assurez-vous que le token HF est disponible (via les secrets de l'espace HF) | |
if not os.getenv("HF_TOKEN"): | |
print("⚠️ Attention: Le token Hugging Face (HF_TOKEN) n'est pas défini. L'initialisation pourrait échouer.") | |
self.ultra_agent = UltraAgent() | |
print("✅ BasicAgent initialisé avec succès!") | |
except Exception as e: | |
print(f"❌ Erreur critique lors de l'initialisation de l'UltraAgent: {e}") | |
self.ultra_agent = None | |
def __call__(self, question: str) -> str: | |
""" | |
Point d'entrée compatible avec l'interface de app.py. | |
Délègue l'appel à l'UltraAgent. | |
""" | |
if self.ultra_agent is None: | |
return "Erreur: L'agent n'a pas pu être initialisé correctement. Veuillez vérifier les logs et la configuration (notamment le HF_TOKEN)." | |
try: | |
return self.ultra_agent(question) | |
except Exception as e: | |
print(f"❌ Erreur lors du traitement par l'UltraAgent: {e}") | |
return f"Une erreur s'est produite lors du traitement de votre demande: {str(e)[:200]}" |