gateway/modules/services/serviceAi/REFACTORING_PLAN.md
2025-12-25 23:51:47 +01:00

4.1 KiB

Refactoring Plan für mainServiceAi.py

Ziel

Aufteilen des 3000-Zeilen-Moduls in überschaubare Submodule (~300-600 Zeilen pro Modul).

Vorgeschlagene Struktur

Bereits erstellt:

  1. subResponseParsing.py - ResponseParser Klasse
  2. subDocumentIntents.py - DocumentIntentAnalyzer Klasse

Noch zu erstellen:

  1. subContentExtraction.py - ContentExtractor Klasse

    • extractAndPrepareContent() (~490 Zeilen)
    • extractTextFromImage() (~55 Zeilen)
    • processTextContentWithAi() (~72 Zeilen)
    • _isBinary() (~10 Zeilen)
  2. subStructureGeneration.py - StructureGenerator Klasse

    • generateStructure() (~60 Zeilen)
    • _buildStructurePrompt() (~130 Zeilen)
  3. subStructureFilling.py - StructureFiller Klasse

    • fillStructure() (~290 Zeilen)
    • _buildSectionGenerationPrompt() (~185 Zeilen)
    • _findContentPartById() (~5 Zeilen)
    • _needsAggregation() (~20 Zeilen)
  4. subAiCallLooping.py - AiCallLooper Klasse

    • callAiWithLooping() (~405 Zeilen)
    • _defineKpisFromPrompt() (~92 Zeilen)

Refactoring-Schritte für mainServiceAi.py

Schritt 1: Submodule-Initialisierung erweitern

def _initializeSubmodules(self):
    """Initialize all submodules after aiObjects is ready."""
    if self.aiObjects is None:
        raise RuntimeError("aiObjects must be initialized before initializing submodules")
    
    if self.extractionService is None:
        logger.info("Initializing ExtractionService...")
        self.extractionService = ExtractionService(self.services)
    
    # Neue Submodule initialisieren
    from modules.services.serviceAi.subResponseParsing import ResponseParser
    from modules.services.serviceAi.subDocumentIntents import DocumentIntentAnalyzer
    from modules.services.serviceAi.subContentExtraction import ContentExtractor
    from modules.services.serviceAi.subStructureGeneration import StructureGenerator
    from modules.services.serviceAi.subStructureFilling import StructureFiller
    
    if not hasattr(self, 'responseParser'):
        self.responseParser = ResponseParser(self.services)
    
    if not hasattr(self, 'intentAnalyzer'):
        self.intentAnalyzer = DocumentIntentAnalyzer(self.services, self)
    
    if not hasattr(self, 'contentExtractor'):
        self.contentExtractor = ContentExtractor(self.services, self)
    
    if not hasattr(self, 'structureGenerator'):
        self.structureGenerator = StructureGenerator(self.services, self)
    
    if not hasattr(self, 'structureFiller'):
        self.structureFiller = StructureFiller(self.services, self)

Schritt 2: Methoden durch Delegation ersetzen

Beispiel für Response Parsing:

# ALT:
def _extractSectionsFromResponse(self, ...):
    # 100 Zeilen Code
    ...

# NEU:
def _extractSectionsFromResponse(self, ...):
    return self.responseParser.extractSectionsFromResponse(...)

Beispiel für Document Intents:

# ALT:
async def _clarifyDocumentIntents(self, ...):
    # 100 Zeilen Code
    ...

# NEU:
async def _clarifyDocumentIntents(self, ...):
    return await self.intentAnalyzer.clarifyDocumentIntents(...)

Schritt 3: Helper-Methoden beibehalten

Kleine Helper-Methoden bleiben im Hauptmodul:

  • _buildPromptWithPlaceholders()
  • _getIntentForDocument()
  • _shouldSkipContentPart()
  • _determineDocumentName()

Schritt 4: Public API unverändert lassen

Die öffentliche API (callAiPlanning, callAiContent) bleibt unverändert.

Erwartete Ergebnis-Größen

  • mainServiceAi.py: ~800-1000 Zeilen (von 3016)
  • subResponseParsing.py: ~200 Zeilen
  • subDocumentIntents.py: ~300 Zeilen
  • subContentExtraction.py: ~600 Zeilen
  • subStructureGeneration.py: ~200 Zeilen
  • subStructureFilling.py: ~400 Zeilen
  • subAiCallLooping.py: ~500 Zeilen

Gesamt: ~3000 Zeilen (gleich, aber besser organisiert)

Vorteile

  1. Übersichtlichkeit: Jedes Modul hat eine klare Verantwortlichkeit
  2. Wartbarkeit: Änderungen sind lokalisiert
  3. Testbarkeit: Module können einzeln getestet werden
  4. Wiederverwendbarkeit: Module können in anderen Kontexten verwendet werden