|
|
@@ -71,76 +71,46 @@ def inspect_data(file_name: str):
|
|
|
@tool
|
|
|
def excel_code_interpreter(file_path: str, code: str):
|
|
|
"""Exécute du code Python sur le fichier (CSV ou Excel) chargé dans 'df'."""
|
|
|
- # Nettoyage du nom de fichier
|
|
|
- file_name = os.path.basename(file_path.strip().replace("'", "").replace('"', ""))
|
|
|
+
|
|
|
+
|
|
|
+ import warnings
|
|
|
+ warnings.filterwarnings("ignore")
|
|
|
|
|
|
- # 1. Définition de la priorité : Dossier 'data' d'abord
|
|
|
+ # Nettoyage et construction du chemin (Ton code existant est bon ici)
|
|
|
+ file_name = os.path.basename(file_path.strip().replace("'", "").replace('"', ""))
|
|
|
data_folder_path = os.path.join(BASE_DIR, "data", file_name)
|
|
|
root_path = os.path.join(BASE_DIR, file_name)
|
|
|
|
|
|
- # Choix du chemin
|
|
|
if os.path.exists(data_folder_path):
|
|
|
full_path = data_folder_path
|
|
|
elif os.path.exists(root_path):
|
|
|
full_path = root_path
|
|
|
else:
|
|
|
- # Si rien n'est trouvé, on aide l'agent avec un message clair
|
|
|
- files_in_data = os.listdir(os.path.join(BASE_DIR, "data")) if os.path.exists(os.path.join(BASE_DIR, "data")) else "Dossier data absent"
|
|
|
- return f"ERREUR : Fichier '{file_name}' introuvable. Contenu de 'data/': {files_in_data}"
|
|
|
-
|
|
|
+ return f"ERREUR : Fichier '{file_name}' introuvable."
|
|
|
|
|
|
-
|
|
|
try:
|
|
|
- # Lecture selon l'extension
|
|
|
- if file_name.endswith('.csv'):
|
|
|
- df = pd.read_csv(full_path)
|
|
|
- else:
|
|
|
- df = pd.read_excel(full_path)
|
|
|
-
|
|
|
- safe_globals={"__builtins__" :{}}
|
|
|
+ # Lecture du fichier
|
|
|
+ df = pd.read_csv(full_path) if file_name.endswith('.csv') else pd.read_excel(full_path)
|
|
|
+
|
|
|
+ # SOLUTION : On utilise un seul dictionnaire pour simplifier
|
|
|
+ # On passe les builtins réels du système pour autoriser les imports
|
|
|
+ context = {
|
|
|
+ "df": df,
|
|
|
+ "pd": pd,
|
|
|
+ "plt": plt,
|
|
|
+ "os": os,
|
|
|
+ "result": None,
|
|
|
+ "__builtins__": __builtins__ # On donne accès aux fonctions natives
|
|
|
+ }
|
|
|
|
|
|
- # Injection des bibliothèques pour l'IA
|
|
|
- local_vars = {"df": df, "pd": pd, "plt": plt, "result": None}
|
|
|
- exec(code, safe_globals , local_vars)
|
|
|
+ # On exécute dans le même dictionnaire pour globals et locals
|
|
|
+ exec(code, context)
|
|
|
|
|
|
- return str(local_vars.get("result", "Exécution terminée."))
|
|
|
+ return str(context.get("result", "Exécution terminée."))
|
|
|
except Exception as e:
|
|
|
return f"ERREUR PYTHON : {str(e)}"
|
|
|
|
|
|
|
|
|
-@tool
|
|
|
-def generate_excel_chart(file_path: str, code: str, output_image: str = "chart.png"):
|
|
|
- """
|
|
|
- Exécute du code Python pour générer un graphique Matplotlib/Seaborn à partir du fichier Excel.
|
|
|
- Le DataFrame est chargé dans 'df'.
|
|
|
- IMPORTANT : Le code doit finir par plt.savefig(output_image).
|
|
|
- """
|
|
|
- # Force le mode sans interface graphique (important pour les scripts automatisés)
|
|
|
- plt.switch_backend('Agg')
|
|
|
- plt.clf() # Nettoie les anciens graphiques en mémoire
|
|
|
-
|
|
|
- full_path = os.path.join(BASE_DIR, file_path)
|
|
|
- try:
|
|
|
- df = pd.read_excel(full_path)
|
|
|
-
|
|
|
- # Environnement d'exécution pour l'IA
|
|
|
- local_vars = {
|
|
|
- "df": df,
|
|
|
- "plt": plt,
|
|
|
- "sns": sns,
|
|
|
- "output_image": output_image
|
|
|
- }
|
|
|
-
|
|
|
- exec(code, {}, local_vars)
|
|
|
-
|
|
|
- if os.path.exists(output_image):
|
|
|
- return f"Succès : Graphique généré et enregistré sous '{output_image}'."
|
|
|
- else:
|
|
|
- return "Erreur : Le code a été exécuté mais aucun fichier image n'a été créé."
|
|
|
-
|
|
|
- except Exception as e:
|
|
|
- return f"Erreur lors de la génération du graphique : {str(e)}"
|
|
|
-
|
|
|
|
|
|
ddg = DuckDuckGoSearchRun()
|
|
|
@tool
|