189 lines
No EOL
6.9 KiB
Python
189 lines
No EOL
6.9 KiB
Python
"""
|
|
Datenanalyst-Agent für die Analyse und Interpretation von Daten.
|
|
"""
|
|
|
|
import logging
|
|
from typing import List, Dict, Any, Optional
|
|
from modules.agentservice_base import BaseAgent
|
|
from connectors.connector_aichat_openai import ChatService
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class AnalystAgent(BaseAgent):
|
|
"""Agent für die Analyse und Interpretation von Daten"""
|
|
|
|
_instance = None
|
|
|
|
@classmethod
|
|
def get_instance(cls):
|
|
"""Gibt eine Singleton-Instanz zurück"""
|
|
if cls._instance is None:
|
|
cls._instance = cls()
|
|
return cls._instance
|
|
|
|
def __init__(self):
|
|
"""Initialisiert den Datenanalyst-Agenten"""
|
|
super().__init__()
|
|
self.id = "analyst_agent"
|
|
self.name = "Datenanalyst"
|
|
self.type = "analyzer"
|
|
self.description = "Analysiert und interpretiert Daten"
|
|
self.capabilities = "Datenanalyse, Mustererkennung, Statistik und Bewertung"
|
|
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
|
|
"""
|
|
|
|
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.
|
|
|
|
Formatiere mit [STATUS: ERGEBNIS/TEILWEISE/PLAN] am Ende.
|
|
"""
|
|
|
|
# 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], context: Dict[str, Any] = None) -> Dict[str, Any]:
|
|
"""
|
|
Verarbeitet eine Nachricht und führt eine Datenanalyse durch.
|
|
|
|
Args:
|
|
message: Die zu verarbeitende Nachricht
|
|
context: Zusätzlicher Kontext (optional)
|
|
|
|
Returns:
|
|
Die generierte Antwort mit der Datenanalyse
|
|
"""
|
|
try:
|
|
# Prompt generieren
|
|
message_context = {"documents": context.get("documents", [])} if context else {}
|
|
prompt = self.get_prompt(message_context)
|
|
|
|
# OpenAI ChatService initialisieren
|
|
chat_service = ChatService()
|
|
|
|
# Nachrichten für die API vorbereiten
|
|
messages = [
|
|
{"role": "system", "content": prompt},
|
|
{"role": "user", "content": message.get("content", "")}
|
|
]
|
|
|
|
# Kontext-Nachrichten hinzufügen, falls vorhanden
|
|
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", "")
|
|
})
|
|
|
|
# API aufrufen
|
|
response_content = await chat_service.call_api(messages)
|
|
|
|
# Verbindung schließen
|
|
await chat_service.close()
|
|
|
|
# Antwort-Objekt erstellen
|
|
analysis_response = {
|
|
"role": "assistant",
|
|
"content": response_content,
|
|
"agent_type": self.type
|
|
}
|
|
|
|
# Extrahiere den Status aus der Antwort und aktualisiere den Inhalt
|
|
content, status = self.extract_status(analysis_response["content"])
|
|
analysis_response["content"] = content
|
|
|
|
# Setze den Status im Kontext, falls vorhanden
|
|
if context is not None:
|
|
context["status"] = status
|
|
|
|
return analysis_response
|
|
|
|
except Exception as e:
|
|
logger.error(f"Fehler bei der Verarbeitung der Anfrage: {str(e)}", exc_info=True)
|
|
|
|
# Fehlerantwort zurückgeben
|
|
return {
|
|
"role": "assistant",
|
|
"content": f"Bei der Datenanalyse ist ein Fehler aufgetreten: {str(e)}",
|
|
"agent_type": self.type
|
|
}
|
|
|
|
# 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 |