""" Dokumentations-Agent für die Erstellung von Dokumentation, Berichten und strukturierten Inhalten. Angepasst für die neue chat.py Architektur und chat_registry.py. """ import logging import json import uuid from typing import Dict, Any, List from datetime import datetime from modules.chat_registry import AgentBase logger = logging.getLogger(__name__) class AgentDocumentation(AgentBase): """Agent für die Erstellung von Dokumentation und strukturierten Inhalten""" def __init__(self): """Initialisiert den Dokumentations-Agent""" super().__init__() self.name = "Documentation Specialist" self.capabilities = "report_generation,documentation,content_structuring,technical_writing,knowledge_organization" def get_agent_info(self) -> Dict[str, Any]: """Gibt Agent-Informationen für die Registry zurück""" info = super().get_config() return info async def process_message(self, message: Dict[str, Any], context: Dict[str, Any] = None) -> Dict[str, Any]: """ Verarbeitet eine Nachricht und erstellt Dokumentation. Args: message: Eingabenachricht context: Optionaler Kontext Returns: Antwortnachricht mit Dokumentation """ # Workflow-ID aus Kontext oder Nachricht extrahieren workflow_id = context.get("workflow_id") if context else message.get("workflow_id", "unknown") # Antwortstruktur erstellen response = { "role": "assistant", "content": "", "agent_name": self.name, "workflow_id": workflow_id, "documents": [] } try: # Aufgabe aus Nachricht extrahieren task = message.get("content", "") # Dokumenttyp erkennen document_type = self._detect_document_type(task) logger.info(f"Erstelle {document_type}-Dokumentation") # Angehängte Dokumente verarbeiten document_context = "" if message.get("documents"): logger.info("Verarbeite Referenzdokumente") document_context = self._process_documents(message) # Prompt mit Dokumentkontext erweitern enhanced_prompt = f"{task}\n\n{document_context}" if document_context else task # Komplexität bewerten is_complex = self._assess_complexity(enhanced_prompt) # Titel generieren title = await self._generate_title(enhanced_prompt, document_type) # Inhalt basierend auf Komplexität generieren if is_complex: content = await self._generate_complex_document(enhanced_prompt, document_type, title) else: content = await self._generate_simple_document(enhanced_prompt, document_type, title) # Dokument erstellen doc_id = f"doc_{uuid.uuid4()}" document = { "id": doc_id, "source": { "type": "generated", "id": doc_id, "name": title, "content_type": "text/markdown" }, "contents": [ { "type": "text", "text": content, "is_extracted": True } ] } # Dokument zur Antwort hinzufügen response["documents"].append(document) # Antwortinhalt aktualisieren response["content"] = f"Ich habe ein Dokument mit dem Titel '{title}' erstellt, das die gewünschten Informationen enthält. Das Dokument ist dieser Nachricht beigefügt." return response except Exception as e: error_msg = f"Fehler bei der Dokumentationserstellung: {str(e)}" logger.error(error_msg) response["content"] = f"Bei der Erstellung der Dokumentation ist ein Fehler aufgetreten: {str(e)}" return response def _detect_document_type(self, message: str) -> str: """ Erkennt den Dokumenttyp aus der Nachricht. Args: message: Benutzernachricht Returns: Erkannter Dokumenttyp """ message = message.lower() if any(term in message for term in ["manual", "guide", "instruction", "tutorial", "anleitung", "handbuch"]): return "manual" elif any(term in message for term in ["report", "analysis", "assessment", "review", "bericht", "analyse"]): return "report" elif any(term in message for term in ["process", "workflow", "procedure", "steps", "prozess", "ablauf"]): return "process" elif any(term in message for term in ["presentation", "slides", "deck", "präsentation", "folien"]): return "presentation" else: return "document" def _process_documents(self, message: Dict[str, Any]) -> str: """ Verarbeitet Dokumente in der Nachricht. Args: message: Nachricht mit Dokumenten Returns: Dokumentkontext als Text """ document_context = "" for document in message.get("documents", []): source = document.get("source", {}) doc_name = source.get("name", "unnamed") document_context += f"\n\n--- {doc_name} ---\n" for content in document.get("contents", []): if content.get("type") == "text": document_context += content.get("text", "") return document_context def _assess_complexity(self, task: str) -> bool: """ Bewertet die Aufgabenkomplexität. Args: task: Die Aufgabenbeschreibung Returns: True bei komplexem Dokument, sonst False """ # Einfache Heuristik zur Komplexitätsbewertung complexity_indicators = [ "detailliert", "ausführlich", "umfassend", "komplex", "detailed", "comprehensive", "in-depth", "multiple sections", "kapitel", "abschnitte", "struktur", "analyse", "vergleich" ] # Zählen der Komplexitätsindikatoren indicator_count = sum(1 for indicator in complexity_indicators if indicator in task.lower()) # Weitere Indikatoren: Textlänge, Anzahl der Anforderungen length_factor = len(task) > 500 requirements_count = task.lower().count("muss") + task.lower().count("soll") + task.lower().count("should") + task.lower().count("must") # Komplexität basierend auf Indikatoren bestimmen return (indicator_count >= 2) or (length_factor and requirements_count >= 3) async def _generate_title(self, task: str, document_type: str) -> str: """ Generiert einen Titel für das Dokument. Args: task: Die Aufgabenbeschreibung document_type: Dokumenttyp Returns: Generierter Titel """ if not self.ai_service: return f"{document_type.capitalize()} Dokument" prompt = f""" Erstelle einen prägnanten, professionellen Titel für dieses {document_type}: {task} Antworte NUR mit dem Titel, nichts anderes. """ try: title = await self.ai_service.call_api([ {"role": "system", "content": "Du erstellst Dokumenttitel."}, {"role": "user", "content": prompt} ]) # Titel bereinigen return title.strip('"\'#*- \n\t') except Exception: return f"{document_type.capitalize()} Dokument" async def _generate_complex_document(self, task: str, document_type: str, title: str) -> str: """ Generiert ein komplexes Dokument mit Struktur. Args: task: Die Aufgabenbeschreibung document_type: Dokumenttyp title: Dokumenttitel Returns: Generierter Dokumentinhalt """ if not self.ai_service: return f"# {title}\n\nDokumentgenerierung nicht möglich: KI-Service nicht verfügbar." prompt = f""" Erstelle ein umfassendes, gut strukturiertes {document_type} mit dem Titel "{title}" basierend auf: {task} Das Dokument sollte Folgendes enthalten: 1. Eine klare Einleitung mit Zweck und Umfang 2. Logisch organisierte Abschnitte mit Überschriften 3. Detaillierte Inhalte mit Beispielen und Belegen 4. Ein Fazit mit den wichtigsten Erkenntnissen 5. Geeignete Formatierung mit Markdown Formatiere das Dokument in Markdown mit korrekten Überschriften, Listen und Hervorhebungen. """ try: content = await self.ai_service.call_api([ {"role": "system", "content": "Du erstellst umfassende, gut strukturierte Dokumentation."}, {"role": "user", "content": prompt} ]) # Sicherstellen, dass der Titel am Anfang steht if not content.strip().startswith("# "): content = f"# {title}\n\n{content}" return content except Exception as e: return f"# {title}\n\nFehler bei der Dokumentgenerierung: {str(e)}" async def _generate_simple_document(self, task: str, document_type: str, title: str) -> str: """ Generiert ein einfaches Dokument ohne komplexe Struktur. Args: task: Die Aufgabenbeschreibung document_type: Dokumenttyp title: Dokumenttitel Returns: Generierter Dokumentinhalt """ if not self.ai_service: return f"# {title}\n\nDokumentgenerierung nicht möglich: KI-Service nicht verfügbar." prompt = f""" Erstelle ein präzises, fokussiertes {document_type} mit dem Titel "{title}" basierend auf: {task} Das Dokument sollte klar, präzise und auf den Punkt sein, ohne komplexe Kapitelstruktur. Formatiere es mit Markdown und verwende geeignete Überschriften und Formatierungen. """ try: content = await self.ai_service.call_api([ {"role": "system", "content": "Du erstellst präzise, fokussierte Dokumentation."}, {"role": "user", "content": prompt} ]) # Sicherstellen, dass der Titel am Anfang steht if not content.strip().startswith("# "): content = f"# {title}\n\n{content}" return content except Exception as e: return f"# {title}\n\nFehler bei der Dokumentgenerierung: {str(e)}" # Singleton-Instanz _documentation_agent = None def get_documentation_agent(): """Gibt eine Singleton-Instanz des Dokumentations-Agenten zurück""" global _documentation_agent if _documentation_agent is None: _documentation_agent = AgentDocumentation() return _documentation_agent