""" Datenanalyst-Agent für die Analyse und Interpretation von Daten. Angepasst für das refaktorisierte Core-Modul. """ import logging import traceback from typing import List, Dict, Any, Optional, Union from datetime import datetime import uuid from modules.agentservice_base import BaseAgent from connectors.connector_aichat_openai import ChatService from modules.agentservice_utils import WorkflowUtils, MessageUtils, LoggingUtils, FileUtils logger = logging.getLogger(__name__) class AnalystAgent(BaseAgent): """Agent für die Analyse und Interpretation von Daten""" def __init__(self): """Initialisiert den Datenanalyst-Agenten""" super().__init__() self.id = "analyst" self.name = "Datenanalyst" self.type = "analyzer" self.description = "Analysiert und interpretiert Daten" self.capabilities = "data_analysis,pattern_recognition,statistics,visualization,data_interpretation" self.instructions = """ Du bist der Datenanalyseagent. Deine Aufgabe: 1. Vorliegende Daten untersuchen und interpretieren 2. Erkenntnisse aus Informationen gewinnen 3. Trends identifizieren und Zusammenhänge prüfen 4. Daten visualisieren und Konzepte erklären 5. Datenqualität bewerten und Handlungsempfehlungen geben """ self.result_format = "AnalysisReport" # Chat-Service initialisieren self.chat_service = ChatService() # Utility-Klassen initialisieren self.message_utils = MessageUtils() self.file_utils = FileUtils() def get_agent_info(self) -> Dict[str, Any]: """Get agent information for agent registry""" return { "id": self.id, "type": self.type, "name": self.name, "description": self.description, "capabilities": self.capabilities, "result_format": self.result_format } def get_prompt(self, message_context: Dict[str, Any]) -> str: """ Generiert einen angepassten Prompt für den Datenanalysten. Args: message_context: Kontext der Nachricht Returns: Formatierter Prompt für den Datenanalysten """ # Basis-Prompt prompt = f""" Du bist {self.name}, ein {self.type} Agent. {self.description} Fähigkeiten: {self.capabilities} {self.instructions} Analysiere die vorliegenden Daten. Präsentiere klar strukturierte Ergebnisse mit einer Zusammenfassung, Detailanalyse und Handlungsempfehlungen. """ # Dateitypspezifische Anweisungen hinzufügen (verkürzt) document_types = self._get_document_types(message_context) if "csv" in document_types or "excel" in document_types: prompt += "\nTABELLENDATEN: Identifiziere wichtige Spalten, Korrelationen und Trends." if "pdf" in document_types or "doc" in document_types: prompt += "\nTEXTDATEN: Extrahiere zentrale Fakten und Schlüsselthemen." if "image" in document_types: prompt += "\nBILDDATEN: Beschreibe und interpretiere dargestellte Informationen." return prompt.strip() def _get_document_types(self, message_context: Dict[str, Any]) -> List[str]: """ Extrahiert die Dateitypen aus dem Nachrichtenkontext. Args: message_context: Kontext der Nachricht Returns: Liste der Dateitypen """ document_types = [] # Versuche Dokumente aus dem Kontext zu extrahieren documents = message_context.get("documents", []) for doc in documents: source = doc.get("source", {}) name = source.get("name", "").lower() content_type = source.get("content_type", "").lower() # Dateityp aus Namen oder Content-Type ableiten if name.endswith(".csv") or "csv" in content_type: document_types.append("csv") elif name.endswith((".xls", ".xlsx")) or "excel" in content_type or "spreadsheet" in content_type: document_types.append("excel") elif name.endswith(".pdf") or "pdf" in content_type: document_types.append("pdf") elif name.endswith((".doc", ".docx")) or "word" in content_type: document_types.append("doc") elif name.endswith((".jpg", ".jpeg", ".png", ".gif")) or "image" in content_type: document_types.append("image") return document_types async def process_message(self, message: Dict[str, Any], workflow: Dict[str, Any], context: Dict[str, Any] = None, log_func=None) -> Dict[str, Any]: """ Verarbeitet eine Nachricht und führt eine Datenanalyse durch. Args: message: Die zu verarbeitende Nachricht workflow: Der aktuelle Workflow context: Zusätzlicher Kontext log_func: Funktion für Workflow-Logging Returns: Die generierte Antwort mit der Datenanalyse """ # Initialize logging workflow_id = workflow.get("id", "unknown") logging_utils = LoggingUtils(workflow_id, log_func) logging_utils.info(f"AnalystAgent startet Datenanalyse", "agents") # Create response message response = self.message_utils.create_message(workflow_id, role="assistant") response["agent_type"] = self.type response["agent_name"] = self.name response["parent_message_id"] = message.get("id") try: # Prepare message context for generating the prompt message_context = {"documents": context.get("documents", [])} if context else {} # Generate appropriate prompt based on the context prompt = self.get_prompt(message_context) logging_utils.info(f"Datenanalyse mit spezifischem Prompt gestartet", "agents") # Prepare messages for the API messages = [ {"role": "system", "content": prompt}, {"role": "user", "content": message.get("content", "")} ] # Add context messages if available if context and "history" in context: for history_item in context["history"]: messages.append({ "role": history_item.get("role", "user"), "content": history_item.get("content", "") }) # Call the API logging_utils.info("Rufe AI-Service für die Analyse auf", "agents") response_content = await self.chat_service.call_api(messages) logging_utils.info("Analyse abgeschlossen", "agents") # Set the content in the response response["content"] = response_content # Finalize the message self.message_utils.finalize_message(response) response["result_format"] = self.result_format return response except Exception as e: error_msg = f"Fehler bei der Datenanalyse: {str(e)}" logging_utils.error(error_msg, "error") # Create error response response["content"] = f"## Fehler bei der Datenanalyse\n\n{error_msg}\n\n```\n{traceback.format_exc()}\n```" self.message_utils.finalize_message(response) return response # Singleton-Instanz _analyst_agent = None def get_analyst_agent(): """Gibt eine Singleton-Instanz des Datenanalyst-Agenten zurück""" global _analyst_agent if _analyst_agent is None: _analyst_agent = AnalystAgent() return _analyst_agent