gateway/modules/chat_agent_documentation.py
2025-04-19 01:02:46 +02:00

320 lines
No EOL
12 KiB
Python

"""
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"
self.result_format = "FormattedDocument"
def get_agent_info(self) -> Dict[str, Any]:
"""Gibt Agent-Informationen für die Registry zurück"""
info = super().get_config()
info.update({
"metadata": {
"document_types": ["manual", "report", "process", "presentation", "document"],
"formats": ["markdown", "text"]
}
})
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,
"result_format": self.result_format,
"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 = 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