320 lines
No EOL
12 KiB
Python
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 |