ragflow_preprocess/utils/workflow_logger.py
2025-03-27 17:59:10 +01:00

147 lines
5.6 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Utilitaire pour enregistrer le flux de traitement entre les agents LLM
"""
import os
import time
import uuid
import json
from typing import Dict, Any, Optional, List
class WorkflowLogger:
"""
Enregistreur de flux de travail pour suivre le traitement entre les agents
"""
def __init__(self, session_id: Optional[str] = None):
"""
Initialise l'enregistreur de flux de travail
Args:
session_id (str, optional): Identifiant de session (généré si non fourni)
"""
# Utiliser l'ID fourni ou en générer un nouveau
self.session_id = session_id or str(uuid.uuid4())[:8]
self.timestamp = time.strftime("%Y%m%d-%H%M%S")
# Répertoire pour les journaux
self.log_dir = os.path.join("data", "workflows")
os.makedirs(self.log_dir, exist_ok=True)
# Fichier principal pour ce flux de travail
self.workflow_file = os.path.join(self.log_dir, f"{self.timestamp}_{self.session_id}_workflow.md")
# Initialiser le fichier avec un en-tête
with open(self.workflow_file, "w", encoding="utf-8") as f:
f.write(f"# Flux de traitement - Session {self.session_id}\n\n")
f.write(f"Date et heure: {time.strftime('%d/%m/%Y %H:%M:%S')}\n\n")
f.write("## Étapes du traitement\n\n")
def log_step(self, agent_name: str, input_data: Dict[str, Any], output_data: Any,
metadata: Optional[Dict[str, Any]] = None) -> None:
"""
Enregistre une étape du flux de traitement
Args:
agent_name (str): Nom de l'agent utilisé
input_data (Dict): Données d'entrée de l'agent
output_data (Any): Données de sortie de l'agent
metadata (Dict, optional): Métadonnées supplémentaires
"""
step_time = time.strftime("%H:%M:%S")
with open(self.workflow_file, "a", encoding="utf-8") as f:
# En-tête de l'étape
f.write(f"### Étape: {agent_name} ({step_time})\n\n")
# Métadonnées si fournies
if metadata:
f.write("#### Métadonnées\n\n")
for key, value in metadata.items():
f.write(f"- **{key}**: {value}\n")
f.write("\n")
# Entrées
f.write("#### Entrées\n\n")
for key, value in input_data.items():
if key == "images" and value:
f.write(f"- **{key}**: {len(value)} image(s) fournie(s)\n")
else:
# Limiter la taille des entrées affichées
if isinstance(value, str) and len(value) > 500:
preview = value[:497] + "..."
f.write(f"- **{key}**:\n```\n{preview}\n```\n")
else:
f.write(f"- **{key}**:\n```\n{value}\n```\n")
# Sorties
f.write("#### Sorties\n\n")
if isinstance(output_data, str) and len(output_data) > 1000:
preview = output_data[:997] + "..."
f.write(f"```\n{preview}\n```\n")
else:
f.write(f"```\n{output_data}\n```\n")
# Séparateur
f.write("\n---\n\n")
def log_error(self, agent_name: str, error_message: str,
input_data: Optional[Dict[str, Any]] = None) -> None:
"""
Enregistre une erreur dans le flux de traitement
Args:
agent_name (str): Nom de l'agent qui a généré l'erreur
error_message (str): Message d'erreur
input_data (Dict, optional): Données d'entrée qui ont causé l'erreur
"""
step_time = time.strftime("%H:%M:%S")
with open(self.workflow_file, "a", encoding="utf-8") as f:
# En-tête de l'erreur
f.write(f"### ERREUR dans {agent_name} ({step_time})\n\n")
# Message d'erreur
f.write("#### Message d'erreur\n\n")
f.write(f"```\n{error_message}\n```\n\n")
# Entrées si fournies
if input_data:
f.write("#### Entrées ayant causé l'erreur\n\n")
for key, value in input_data.items():
if key == "images" and value:
f.write(f"- **{key}**: {len(value)} image(s) fournie(s)\n")
else:
# Limiter la taille des entrées affichées
if isinstance(value, str) and len(value) > 500:
preview = value[:497] + "..."
f.write(f"- **{key}**:\n```\n{preview}\n```\n")
else:
f.write(f"- **{key}**:\n```\n{value}\n```\n")
# Séparateur
f.write("\n---\n\n")
def log_summary(self, summary_text: str) -> None:
"""
Ajoute un résumé final au flux de traitement
Args:
summary_text (str): Texte du résumé
"""
with open(self.workflow_file, "a", encoding="utf-8") as f:
f.write("## Résumé du traitement\n\n")
f.write(f"{summary_text}\n\n")
f.write(f"*Fin du flux de traitement - {time.strftime('%d/%m/%Y %H:%M:%S')}*\n")
def get_workflow_path(self) -> str:
"""
Renvoie le chemin du fichier de flux de travail
Returns:
str: Chemin du fichier
"""
return self.workflow_file