wiki/implementation/implementation_ai-call-looping-architecture_done.md
2026-01-11 13:07:11 +01:00

64 KiB

AI-Call Looping Architektur

Übersicht

Dieses Dokument beschreibt die zentrale Architektur für AI-Calls mit Looping-Funktionalität nach cut-response. Es dokumentiert die verschiedenen Use Cases, ihre Looping-Mechanismen, Continuation-Prompt-Strukturen und die Unterschiede zwischen ihnen.

Fokus: AI-Loop-Call mit automatischen Iterationen nach unvollständigen JSON-Responses.

Ziel: Übersichtliche Grundlage für das Aufräumen und Vereinheitlichen der Looping-Logik.


Use Cases Summary

Alle registrierten Use Cases:

  1. section_content - Section-Content-Generierung Looping
  2. chapter_structure - Chapter-Struktur-Generierung Looping
  3. code_structure - Code-Struktur-Generierung Looping
  4. code_content - Code-Content-Generierung Looping

Vergleichstabelle:

Use Case Looping Direct Return Accumulation Extraction Prompt Builder Template Konsistenz Prompt Builder Parameter
section_content buildSectionPromptWithContinuation() IDENTISCH section, contentParts, userPrompt, generationHint, allSections, sectionIndex, isAggregation, services
chapter_structure buildChapterStructurePromptWithContinuation() IDENTISCH userPrompt, contentParts, outputFormat, services
code_structure FEHLT PROBLEM FEHLT
code_content buildCodeContentPromptWithContinuation() IDENTISCH filename, fileType, functions, classes, dependencies, metadata, userPrompt, contentParts, contextInfo, services

Hinweis zu Prompt-Builder-Parametern:

  • Alle Prompt-Builder akzeptieren zusätzlich: continuationContext: Dict[str, Any] (wird automatisch übergeben)
  • Aktuell verwenden alle Builder **kwargs für Parameter-Extraktion
  • Ziel-Architektur: Explizite Parameter statt **kwargs (siehe "Ziel-Architektur" Abschnitt)

Kern-System: callAiWithLooping

Location: gateway/modules/services/serviceAi/subAiCallLooping.py

Zentrale Funktion: AiCallLooper.callAiWithLooping()

Funktionsweise:

  1. Erste Iteration: Verwendet den initialen Prompt
  2. Weitere Iterationen (nach cut-response):
    • Prüft, ob JSON vollständig ist (String-basierte und Parsing-basierte Checks)
    • Wenn unvollständig: Baut Continuation-Prompt mit promptBuilder
    • Merged JSON-Fragmente mit Overlap-Detection
    • Wiederholt bis JSON vollständig oder kein Overlap gefunden

Loop-Bedingungen:

  • Stoppt wenn: JSON vollständig, kein Overlap gefunden, Fehler, max Iterationen erreicht
  • Weiter wenn: JSON unvollständig, Overlap gefunden, Parsing fehlgeschlagen

Ziel-Architektur: Harmonisiertes AI-Looping-System

1. Continuation-Context-Building

Aktueller Zustand:

  • buildContinuationContext(allSections, lastRawResponse, useCaseId) extrahiert template_structure aus dem Response
  • template_structure wird aus dem Response abgeleitet, nicht explizit übergeben

⚠️ KRITISCH: Template-Struktur NICHT extrahieren

  • Template-Struktur wird NICHT aus dem initialen Prompt extrahiert
  • Template-Struktur wird NICHT aus dem Response extrahiert
  • Template-Struktur ist ein expliziter Parameter, der beim Erstellen des initialen Prompts erstellt wird
  • Derselbe Template-Struktur-Parameter wird dann für den Continuation-Prompt verwendet
  • Dies garantiert exakte Identität zwischen initialem und Continuation-Prompt

Ziel-Architektur:

from pydantic import BaseModel
from typing import Optional, List, Dict, Any

class ContinuationContext(BaseModel):
    """Pydantic model for continuation context information."""
    section_count: int
    delivered_summary: str
    cut_off_element: Optional[str] = None
    element_before_cutoff: Optional[str] = None
    template_structure: Optional[str] = None  # JSON structure template from initial prompt
    last_complete_part: Optional[str] = None
    incomplete_part: Optional[str] = None
    structure_context: Optional[str] = None
    last_raw_json: Optional[str] = None

def buildContinuationContext(
    allSections: List[Dict[str, Any]], 
    lastRawResponse: Optional[str] = None,
    useCaseId: Optional[str] = None,
    templateStructure: Optional[str] = None  # NEU: Expliziter Parameter
) -> ContinuationContext:
    """
    Build context information from accumulated sections for continuation prompt.
    
    Args:
        allSections: List of ALL sections accumulated across ALL iterations
        lastRawResponse: Raw JSON response from last iteration (can be broken/incomplete)
        useCaseId: Optional use case ID to determine expected JSON structure
        templateStructure: JSON structure template from initial prompt (MUST be identical)
        
    Returns:
        ContinuationContext: Pydantic model with all continuation context information
    """
    # ... implementation ...
    return ContinuationContext(
        section_count=len(allSections),
        delivered_summary=delivered_summary,
        cut_off_element=cut_off_element,
        element_before_cutoff=element_before_cutoff,
        template_structure=templateStructure,  # Explizit übergeben
        last_complete_part=last_complete_part,
        incomplete_part=incomplete_part,
        structure_context=structure_context,
        last_raw_json=lastRawResponse
    )

Vorteile:

  • Typsicherheit: Pydantic-Modell statt Dict für bessere IDE-Support und Validierung
  • Konsistenz: Gleiche Architektur wie andere Modelle im System (z.B. Prompt-Args-Dataclasses)
  • Validierung: Automatische Validierung der Felder durch Pydantic
  • Dokumentation: Explizite Feld-Definitionen statt Dict-Keys
  • Initialer und iterativer Prompt haben garantiert die gleiche Struktur
  • Keine Abhängigkeit von Response-Parsing für Template-Extraktion
  • Explizite Kontrolle über Template-Struktur

Erforderliche Änderungen:

  1. ContinuationContext Pydantic-Modell erstellen (jsonUtils.py oder separate Model-Datei)
  2. buildContinuationContext() erweitern um templateStructure Parameter
  3. buildContinuationContext() Rückgabetyp ändern von Dict[str, Any] zu ContinuationContext
  4. Alle Aufrufe von buildContinuationContext() anpassen, um templateStructure zu übergeben
  5. Alle Verwendungen von continuationContext anpassen (Dict-Zugriff → Attribut-Zugriff)
    • continuationContext.get("delivered_summary")continuationContext.delivered_summary
    • continuationContext.get("cut_off_element")continuationContext.cut_off_element
    • etc.

2. Prompt-Builder-Architektur

Aktueller Zustand:

  • Alle Prompt-Builder verwenden **kwargs für Parameter
  • Parameter werden aus kwargs extrahiert (nicht typsicher)
  • 3 identische Instanzen von buildSectionPromptWithContinuation() in subStructureFilling.py

Ziel-Architektur:

Entscheidungen:

  • BasePrompt als Parameter übergeben: Saubere Lösung, garantiert Identität mit initialem Prompt
  • Dataclasses für Parameter-Strukturen: Ja, für Typsicherheit und bessere Code-Qualität
  • Schrittweise Migration: Von **kwargs zu expliziten Parametern mit klarem Plan
  • Einheitliche Signatur: Alle Builder auf die gleiche Signatur umstellen

Einheitliche Signatur mit Dataclasses:

from typing import Protocol
from dataclasses import dataclass

# Beispiel: Section Content Prompt Args
@dataclass
class SectionPromptArgs:
    """Type-safe arguments for section content prompt builder."""
    section: Dict[str, Any]
    contentParts: List[ContentPart]
    userPrompt: str
    generationHint: str
    allSections: List[Dict[str, Any]]
    sectionIndex: int
    isAggregation: bool
    services: Any

# Beispiel: Chapter Structure Prompt Args
@dataclass
class ChapterStructurePromptArgs:
    """Type-safe arguments for chapter structure prompt builder."""
    userPrompt: str
    contentParts: List[ContentPart]
    outputFormat: str
    services: Any

# Einheitliche Signatur für ALLE Prompt-Builder:
class PromptBuilder(Protocol):
    """Protocol for prompt builders with unified signature."""
    async def __call__(
        self,
        continuationContext: ContinuationContext,  # Pydantic-Modell (NICHT Optional - wird immer übergeben)
        templateStructure: str,  # Expliziter Parameter (aus promptArgs) - NICHT extrahiert, sondern als Parameter übergeben
        basePrompt: str,  # Initialer Prompt (als Parameter übergeben) - NICHT regeneriert, sondern als Parameter übergeben
        promptArgs: Any  # Dataclass mit use-case-spezifischen Parametern
    ) -> str:
        """Build continuation prompt with unified signature."""
        ...

Vorteile:

  • Typsicherheit durch Dataclasses
  • Einheitliche Signatur für alle Builder
  • BasePrompt als Parameter garantiert Identität
  • Bessere IDE-Support und Dokumentation

Aufruf-Stelle (subAiCallLooping.py Zeile 124):

# Aktueller Aufruf:
iterationPrompt = await promptBuilder(continuationContext=continuationContext, **promptArgs)

Aktuelle Signaturen (INKONSISTENT):

  • buildSectionPromptWithContinuation(continuationContext: Dict[str, Any], **kwargs)continuationContext NICHT Optional
  • buildChapterStructurePromptWithContinuation(continuationContext: Optional[Dict[str, Any]] = None, **kwargs)continuationContext Optional
  • buildCodeContentPromptWithContinuation(continuationContext: Optional[Dict[str, Any]] = None, **kwargs)continuationContext Optional

Problem: Inkonsistente Signaturen! Einige Builder haben Optional, andere nicht.

Parameter-Übergabe-Unterschiede (AKTUELL):

Use Case Parameter-Übergabe Beschreibung
section_content Alle promptArgs werden übergeben section, contentParts, userPrompt, generationHint, allSections, sectionIndex, isAggregation, services
chapter_structure Alle promptArgs werden übergeben userPrompt, contentParts, outputFormat, services
code_content Alle promptArgs werden übergeben filename, fileType, functions, classes, dependencies, metadata, userPrompt, contentParts, contextInfo, services
Andere Use Cases (historisch) Gefilterte promptArgs Nur: outputFormat, userPrompt, title, extracted_content, services

Hinweis: Die historische Unterscheidung zwischen section_content (alle Parameter) und anderen Use Cases (gefilterte Parameter) wurde bereits aufgehoben. Alle aktuellen Use Cases verwenden alle promptArgs.

⚠️ KRITISCH: Template-Struktur-Quelle

WICHTIG: Template-Struktur wird NICHT aus dem initialen Prompt extrahiert. Stattdessen:

Use Case Template-Erstellung Beschreibung
section_content Wird erstellt via _getContentStructureExample(contentType) Template wird beim Erstellen des initialen Prompts erstellt (nicht extrahiert)
chapter_structure Wird erstellt aus "EXAMPLE STRUCTURE" Struktur Template wird beim Erstellen des initialen Prompts erstellt (nicht extrahiert)
code_content Wird erstellt aus JSON-Struktur-Definition Template wird beim Erstellen des initialen Prompts erstellt (nicht extrahiert)
code_structure Wird erstellt aus "## FILE STRUCTURE REQUIREMENTS" Template wird beim Erstellen des initialen Prompts erstellt (nicht extrahiert)

Ziel-Architektur:

  • Template wird beim Erstellen des initialen Prompts erstellt (nicht extrahiert!)
  • Template wird als separater Parameter zurückgegeben: (prompt, templateStructure)
  • Template wird in promptArgs gespeichert beim Aufruf von callAiWithLooping()
  • Template wird aus promptArgs geholt und an Continuation-Prompt-Builder übergeben
  • Garantiert exakte Identität zwischen initialem und Continuation-Prompt

Einheitliche Signatur (ZIEL):

# Einheitliche Signatur für ALLE Prompt-Builder:
async def buildXxxPromptWithContinuation(
    continuationContext: ContinuationContext,  # Pydantic-Modell (NICHT Optional - wird immer übergeben)
    templateStructure: str,  # Expliziter Parameter (aus promptArgs)
    basePrompt: str,  # Initialer Prompt (als Parameter übergeben)
    promptArgs: Any  # Dataclass mit use-case-spezifischen Parametern
) -> str:
    """Build continuation prompt with unified signature."""
    ...

Erforderliche Änderungen:

  1. Einheitlicher Prompt-Builder für section_content:

    • 3 Instanzen zu einer einzigen Funktion konsolidieren
    • Funktion als Methode der Klasse definieren (nicht nested)
    • Dataclass SectionPromptArgs für Parameter verwenden
  2. Alle Prompt-Builder harmonisieren:

    • continuationContext als NICHT-Optional Parameter (wird immer übergeben)
    • templateStructure als expliziten Parameter hinzufügen
    • basePrompt als expliziten Parameter hinzufügen (garantiert Identität)
    • Dataclasses für use-case-spezifische Parameter einführen
    • **kwargs schrittweise durch Dataclass-Parameter ersetzen
  3. buildCodeStructurePromptWithContinuation() implementieren:

    • Als Klassenmethode in CodeGenerationPath
    • Ähnlich wie buildChapterStructurePromptWithContinuation()
    • Template aus "## FILE STRUCTURE REQUIREMENTS" (Zeile 276-303 in codePath.py)
    • Dataclass CodeStructurePromptArgs erstellen
  4. Aufruf-Stelle anpassen (subAiCallLooping.py Zeile 112-124):

    # Aktuell:
    continuationContext = buildContinuationContext(allSections, lastRawResponse, useCaseId)  # Gibt Dict zurück
    iterationPrompt = await promptBuilder(continuationContext=continuationContext, **promptArgs)
    
    # Verwendung (aktuell):
    deliveredSummary = continuationContext.get("delivered_summary", "")
    cutOffElement = continuationContext.get("cut_off_element", "")
    
    # Ziel (nach vollständiger Migration):
    # templateStructure und basePrompt werden bereits beim Erstellen des initialen Prompts als Parameter übergeben
    templateStructure = promptArgs.get("templateStructure")  # Aus promptArgs
    basePrompt = prompt  # Initialer Prompt (wird bereits übergeben)
    continuationContext = buildContinuationContext(
        allSections, lastRawResponse, useCaseId, templateStructure
    )
    
    # Dataclass aus promptArgs erstellen (use-case-spezifisch)
    # Beispiel für section_content:
    sectionArgs = SectionPromptArgs(
        section=promptArgs["section"],
        contentParts=promptArgs["contentParts"],
        userPrompt=promptArgs["userPrompt"],
        generationHint=promptArgs["generationHint"],
        allSections=promptArgs["allSections"],
        sectionIndex=promptArgs["sectionIndex"],
        isAggregation=promptArgs["isAggregation"],
        services=promptArgs["services"]
    )
    
    iterationPrompt = await promptBuilder(
        continuationContext=continuationContext,
        templateStructure=templateStructure,
        basePrompt=basePrompt,
        promptArgs=sectionArgs  # Dataclass statt **kwargs
    )
    

⚠️ WICHTIG: Keine Rückwärtskompatibilität

  • Keine Backward Compatibility - neue Architektur wird vollständig implementiert
  • Keine Fallback-Logik - alle Parameter sind REQUIRED
  • Klare neue Architektur - alte Implementierungen werden vollständig ersetzt

Schrittweise Migration:

  • Phase 1: ContinuationContext Pydantic-Modell erstellen, templateStructure als expliziten Parameter hinzufügen
  • Phase 2: basePrompt als expliziten Parameter hinzufügen
  • Phase 3: Prompt-Builder konsolidieren und als Klassenmethoden definieren
  • Phase 4: Alle Builder auf einheitliche Signatur umstellen (einheitliche Continuation-Prompt-Struktur)
  • Phase 5: Dataclasses einführen und **kwargs schrittweise ersetzen

5. Prompt-Builder-Aufruf-Mechanismus

Zentrale Aufruf-Stelle: subAiCallLooping.py Zeile 112-124

Aktueller Aufruf-Mechanismus:

# In subAiCallLooping.py (Zeile 112-124):
if (len(allSections) > 0 or lastRawResponse) and promptBuilder and promptArgs:
    # Build continuation context
    continuationContext = buildContinuationContext(allSections, lastRawResponse, useCaseId)
    
    # Ensure services is available in promptArgs
    if not promptArgs.get('services') and hasattr(self, 'services'):
        promptArgs['services'] = self.services
    
    # Call prompt builder with continuationContext and **kwargs
    iterationPrompt = await promptBuilder(continuationContext=continuationContext, **promptArgs)
else:
    # First iteration - use original prompt
    iterationPrompt = prompt

Aufruf-Beispiele für verschiedene Use Cases:

1. section_content Use Case

Aufruf-Stelle: subStructureFilling.py (3 Instanzen: Zeilen ~850, ~1100, ~1461)

Aktueller Aufruf:

# In _generateSectionContent() oder ähnlicher Methode:
generationPrompt, templateStructure = self._buildSectionGenerationPrompt(
    section=section,
    contentParts=contentParts,
    userPrompt=userPrompt,
    generationHint=generationHint,
    allSections=allSections,
    sectionIndex=sectionIndex,
    isAggregation=isAggregation,
    language=language
)

# Nested function definieren (wird später als promptBuilder übergeben)
async def buildSectionPromptWithContinuation(
    continuationContext: Dict[str, Any],
    **kwargs
) -> str:
    # Extrahiert Parameter aus kwargs:
    section = kwargs.get("section")
    contentParts = kwargs.get("contentParts", [])
    userPrompt = kwargs.get("userPrompt", "")
    generationHint = kwargs.get("generationHint", "")
    allSections = kwargs.get("allSections", [])
    sectionIndex = kwargs.get("sectionIndex", 0)
    isAggregation = kwargs.get("isAggregation", False)
    # ... baut Continuation-Prompt
    return continuationPrompt

# Aufruf von callAiWithLooping:
aiResponse = await self.aiService.callAiWithLooping(
    prompt=generationPrompt,
    options=options,
    promptBuilder=buildSectionPromptWithContinuation,  # Nested function
    promptArgs={
        "section": section,
        "contentParts": contentParts,
        "userPrompt": userPrompt,
        "generationHint": generationHint,
        "allSections": allSections,
        "sectionIndex": sectionIndex,
        "isAggregation": isAggregation,
        "services": self.services
    },
    useCaseId="section_content",
    debugPrefix=f"{chapterId}_section_{sectionId}",
    contentParts=contentParts
)

Ziel-Aufruf (nach Migration):

# In _generateSectionContent():
generationPrompt, templateStructure = self._buildSectionGenerationPrompt(...)

# Prompt-Builder als Klassenmethode (konsolidiert):
# (wird als self.buildSectionPromptWithContinuation definiert)

# Aufruf von callAiWithLooping:
aiResponse = await self.aiService.callAiWithLooping(
    prompt=generationPrompt,
    options=options,
    promptBuilder=self.buildSectionPromptWithContinuation,  # Klassenmethode
    promptArgs={
        "section": section,
        "contentParts": contentParts,
        "userPrompt": userPrompt,
        "generationHint": generationHint,
        "allSections": allSections,
        "sectionIndex": sectionIndex,
        "isAggregation": isAggregation,
        "services": self.services,
        "templateStructure": templateStructure,  # NEU: Explizit hinzugefügt
        "basePrompt": generationPrompt  # NEU: Explizit hinzugefügt
    },
    useCaseId="section_content",
    debugPrefix=f"{chapterId}_section_{sectionId}",
    contentParts=contentParts
)

# In subAiCallLooping.py (nach Migration):
templateStructure = promptArgs.get("templateStructure")
basePrompt = prompt  # Initialer Prompt
continuationContext = buildContinuationContext(
    allSections, lastRawResponse, useCaseId, templateStructure
)

# Dataclass erstellen (use-case-spezifisch):
sectionArgs = SectionPromptArgs(
    section=promptArgs["section"],
    contentParts=promptArgs["contentParts"],
    userPrompt=promptArgs["userPrompt"],
    generationHint=promptArgs["generationHint"],
    allSections=promptArgs["allSections"],
    sectionIndex=promptArgs["sectionIndex"],
    isAggregation=promptArgs["isAggregation"],
    services=promptArgs["services"]
)

iterationPrompt = await promptBuilder(
    continuationContext=continuationContext,
    templateStructure=templateStructure,
    basePrompt=basePrompt,
    promptArgs=sectionArgs  # Dataclass statt **kwargs
)

2. chapter_structure Use Case

Aufruf-Stelle: subStructureGeneration.py Zeile 162-176

Aktueller Aufruf:

# In _generateChapterStructure():
structurePrompt = self._buildChapterStructurePrompt(
    userPrompt=userPrompt,
    contentParts=contentParts,
    outputFormat=outputFormat
)

# Nested function definieren:
async def buildChapterStructurePromptWithContinuation(
    continuationContext: Optional[Dict[str, Any]] = None,
    **kwargs
) -> str:
    userPrompt = kwargs.get("userPrompt", "")
    contentParts = kwargs.get("contentParts", [])
    outputFormat = kwargs.get("outputFormat", "txt")
    # ... baut Continuation-Prompt
    return continuationPrompt or basePrompt

# Aufruf von callAiWithLooping:
aiResponseJson = await self.aiService.callAiWithLooping(
    prompt=structurePrompt,
    options=options,
    promptBuilder=buildChapterStructurePromptWithContinuation,
    promptArgs={
        "userPrompt": userPrompt,
        "outputFormat": outputFormat,
        "services": self.services
        # HINWEIS: contentParts wird NICHT übergeben (nur Metadata im Prompt)
    },
    useCaseId="chapter_structure",
    debugPrefix="chapter_structure_generation",
    contentParts=None  # Explizit None - nur Metadata benötigt
)

Ziel-Aufruf (nach Migration):

# In _generateChapterStructure():
structurePrompt, templateStructure = self._buildChapterStructurePrompt(...)

# Aufruf von callAiWithLooping:
aiResponseJson = await self.aiService.callAiWithLooping(
    prompt=structurePrompt,
    options=options,
    promptBuilder=self.buildChapterStructurePromptWithContinuation,  # Klassenmethode
    promptArgs={
        "userPrompt": userPrompt,
        "outputFormat": outputFormat,
        "services": self.services,
        "templateStructure": templateStructure,  # NEU
        "basePrompt": structurePrompt  # NEU
    },
    useCaseId="chapter_structure",
    debugPrefix="chapter_structure_generation",
    contentParts=None
)

# In subAiCallLooping.py (nach Migration):
chapterArgs = ChapterStructurePromptArgs(
    userPrompt=promptArgs["userPrompt"],
    contentParts=promptArgs.get("contentParts", []),
    outputFormat=promptArgs["outputFormat"],
    services=promptArgs["services"]
)

iterationPrompt = await promptBuilder(
    continuationContext=continuationContext,
    templateStructure=templateStructure,
    basePrompt=basePrompt,
    promptArgs=chapterArgs  # Dataclass
)

3. code_content Use Case

Aufruf-Stelle: codePath.py Zeile 812-830

Aktueller Aufruf:

# In _generateCodeContent() -> generateFileContent():
contentPrompt = f"""# TASK: Generate Code File Content
...
Return ONLY valid JSON in this format:
{{
  "files": [
    {{
      "filename": "{filename}",
      "content": "// Complete code here",
      ...
    }}
  ]
}}
"""

# Nested function definieren:
async def buildCodeContentPromptWithContinuation(
    continuationContext: Optional[Dict[str, Any]] = None,
    **kwargs
) -> str:
    filename = kwargs.get("filename", "")
    fileType = kwargs.get("fileType", "")
    functions = kwargs.get("functions", [])
    classes = kwargs.get("classes", [])
    dependencies = kwargs.get("dependencies", [])
    metadata = kwargs.get("metadata", {})
    userPrompt = kwargs.get("userPrompt", "")
    contentParts = kwargs.get("contentParts", [])
    contextInfo = kwargs.get("contextInfo", "")
    # ... baut Continuation-Prompt
    return continuationPrompt or basePrompt

# Aufruf von callAiWithLooping:
contentJson = await self.services.ai.callAiWithLooping(
    prompt=contentPrompt,
    options=options,
    promptBuilder=buildCodeContentPromptWithContinuation,
    promptArgs={
        "filename": filename,
        "fileType": fileType,
        "functions": functions,
        "classes": classes,
        "dependencies": dependencies,
        "metadata": metadata,
        "userPrompt": userPrompt,
        "contentParts": contentParts,
        "contextInfo": contextInfo,
        "services": self.services
    },
    useCaseId="code_content",
    debugPrefix=f"code_content_{fileStructure.get('id', 'file')}",
)

Ziel-Aufruf (nach Migration):

# In generateFileContent():
contentPrompt, templateStructure = self._buildCodeContentPrompt(...)

# Aufruf von callAiWithLooping:
contentJson = await self.services.ai.callAiWithLooping(
    prompt=contentPrompt,
    options=options,
    promptBuilder=self.buildCodeContentPromptWithContinuation,  # Klassenmethode
    promptArgs={
        "filename": filename,
        "fileType": fileType,
        "functions": functions,
        "classes": classes,
        "dependencies": dependencies,
        "metadata": metadata,
        "userPrompt": userPrompt,
        "contentParts": contentParts,
        "contextInfo": contextInfo,
        "services": self.services,
        "templateStructure": templateStructure,  # NEU
        "basePrompt": contentPrompt  # NEU
    },
    useCaseId="code_content",
    debugPrefix=f"code_content_{fileStructure.get('id', 'file')}",
)

# In subAiCallLooping.py (nach Migration):
codeContentArgs = CodeContentPromptArgs(
    filename=promptArgs["filename"],
    fileType=promptArgs["fileType"],
    functions=promptArgs["functions"],
    classes=promptArgs["classes"],
    dependencies=promptArgs["dependencies"],
    metadata=promptArgs["metadata"],
    userPrompt=promptArgs["userPrompt"],
    contentParts=promptArgs["contentParts"],
    contextInfo=promptArgs["contextInfo"],
    services=promptArgs["services"]
)

iterationPrompt = await promptBuilder(
    continuationContext=continuationContext,
    templateStructure=templateStructure,
    basePrompt=basePrompt,
    promptArgs=codeContentArgs  # Dataclass
)

4. code_structure Use Case

Aufruf-Stelle: codePath.py Zeile 311-317

Aktueller Aufruf (OHNE Prompt-Builder - noch nicht implementiert):

# In _generateCodeStructure():
structureJson = await self.services.ai.callAiWithLooping(
    prompt=structurePrompt,
    options=options,
    useCaseId="code_structure",
    debugPrefix="code_structure_generation",
    contentParts=contentParts
    # KEIN promptBuilder - noch nicht implementiert!
)

Ziel-Aufruf (nach Implementierung):

# In _generateCodeStructure():
structurePrompt, templateStructure = self._buildCodeStructurePrompt(...)

# Aufruf von callAiWithLooping:
structureJson = await self.services.ai.callAiWithLooping(
    prompt=structurePrompt,
    options=options,
    promptBuilder=self.buildCodeStructurePromptWithContinuation,  # NEU: Implementieren
    promptArgs={
        "userPrompt": userPrompt,
        "contentParts": contentParts,
        "services": self.services,
        "templateStructure": templateStructure,  # NEU
        "basePrompt": structurePrompt  # NEU
    },
    useCaseId="code_structure",
    debugPrefix="code_structure_generation",
    contentParts=contentParts
)

# In subAiCallLooping.py (nach Migration):
codeStructureArgs = CodeStructurePromptArgs(
    userPrompt=promptArgs["userPrompt"],
    contentParts=promptArgs["contentParts"],
    services=promptArgs["services"]
)

iterationPrompt = await promptBuilder(
    continuationContext=continuationContext,
    templateStructure=templateStructure,
    basePrompt=basePrompt,
    promptArgs=codeStructureArgs  # Dataclass
)

Zusammenfassung der Aufruf-Mechanismen:

Use Case Aktueller Aufruf Ziel-Aufruf Status
section_content Mit promptBuilder (nested function, 3 Instanzen) Klassenmethode, Dataclass SectionPromptArgs Migration erforderlich
chapter_structure Mit promptBuilder (nested function) Klassenmethode, Dataclass ChapterStructurePromptArgs Migration erforderlich
code_content Mit promptBuilder (nested function) Klassenmethode, Dataclass CodeContentPromptArgs Migration erforderlich
code_structure OHNE promptBuilder Klassenmethode, Dataclass CodeStructurePromptArgs Implementierung erforderlich

Wichtige Punkte:

  1. Zentrale Aufruf-Stelle: Alle Prompt-Builder werden zentral in subAiCallLooping.py Zeile 112-124 aufgerufen
  2. Parameter-Übergabe: Aktuell via **kwargs in promptArgs Dict, zukünftig via Dataclasses
  3. Template-Struktur: Wird aktuell im Builder regeneriert, zukünftig als expliziter Parameter übergeben
  4. BasePrompt: Wird aktuell im Builder regeneriert, zukünftig als expliziter Parameter übergeben
  5. Konsolidierung: section_content hat 3 identische Instanzen → 1 konsolidierte Klassenmethode

Parameter-Mapping für explizite Signatures mit Dataclasses:

Prompt-Builder Aktuelle Parameter (aus **kwargs) Dataclass Ziel-Signature (einheitlich)
buildSectionPromptWithContinuation() section, contentParts, userPrompt, generationHint, allSections, sectionIndex, isAggregation, services SectionPromptArgs async def buildSectionPromptWithContinuation(continuationContext: Dict[str, Any], templateStructure: str, basePrompt: str, promptArgs: SectionPromptArgs) -> str
buildChapterStructurePromptWithContinuation() userPrompt, contentParts, outputFormat, services ChapterStructurePromptArgs async def buildChapterStructurePromptWithContinuation(continuationContext: Dict[str, Any], templateStructure: str, basePrompt: str, promptArgs: ChapterStructurePromptArgs) -> str
buildCodeContentPromptWithContinuation() filename, fileType, functions, classes, dependencies, metadata, userPrompt, contentParts, contextInfo, services CodeContentPromptArgs async def buildCodeContentPromptWithContinuation(continuationContext: Dict[str, Any], templateStructure: str, basePrompt: str, promptArgs: CodeContentPromptArgs) -> str
buildCodeStructurePromptWithContinuation() FEHLT CodeStructurePromptArgs async def buildCodeStructurePromptWithContinuation(continuationContext: Dict[str, Any], templateStructure: str, basePrompt: str, promptArgs: CodeStructurePromptArgs) -> str

Vollständige Dataclass-Definitionen:

@dataclass
class SectionPromptArgs:
    """Type-safe arguments for section content prompt builder."""
    section: Dict[str, Any]
    contentParts: List[ContentPart]
    userPrompt: str
    generationHint: str
    allSections: List[Dict[str, Any]]
    sectionIndex: int
    isAggregation: bool
    services: Any

@dataclass
class ChapterStructurePromptArgs:
    """Type-safe arguments for chapter structure prompt builder."""
    userPrompt: str
    contentParts: List[ContentPart]
    outputFormat: str
    services: Any

@dataclass
class CodeContentPromptArgs:
    """Type-safe arguments for code content prompt builder."""
    filename: str
    fileType: str
    functions: List[Dict]
    classes: List[Dict]
    dependencies: List[str]
    metadata: Dict[str, Any]
    userPrompt: str
    contentParts: List[ContentPart]
    contextInfo: str
    services: Any

@dataclass
class CodeStructurePromptArgs:
    """Type-safe arguments for code structure prompt builder."""
    userPrompt: str
    contentParts: List[ContentPart]
    services: Any

Prompt-Builder Locations und Konsolidierung:

Prompt-Builder Location Anzahl Typ Konsolidierung
buildSectionPromptWithContinuation subStructureFilling.py 3 Instanzen Nested functions (Zeilen 814, 1100, 1461) 3 → 1 (als Klassenmethode in StructureFiller)
buildChapterStructurePromptWithContinuation subStructureGeneration.py 1 Instanz Nested function (Zeile 111) Als Klassenmethode in StructureGenerator
buildCodeContentPromptWithContinuation codePath.py 1 Instanz Nested function (Zeile 683) Als Klassenmethode in CodeGenerationPath
buildCodeStructurePromptWithContinuation FEHLT 0 - Als Klassenmethode in CodeGenerationPath (neu erstellen)

Architektur-Entscheidung:

  • NICHT in eine zentrale Klasse verschieben (zu enge Kopplung)
  • ABER: Konsolidierung innerhalb der jeweiligen Klassen
  • Vorteil: Modulare Struktur, keine enge Kopplung, einfache Wartung

Aufruf-Mechanismus:

  • Alle Builder werden in subAiCallLooping.py Zeile 124 aufgerufen
  • Einheitliche Signatur ermöglicht einheitlichen Aufruf ohne use-case-spezifische Logik
  • Nach Migration: await promptBuilder(continuationContext=..., templateStructure=..., basePrompt=..., promptArgs=dataclassInstance)

3. Template-Struktur-Parameter

⚠️ KRITISCH: Template-Struktur ist ein expliziter Parameter

WICHTIG:

  • Template-Struktur wird NICHT aus dem initialen Prompt extrahiert
  • Template-Struktur wird NICHT aus dem Response extrahiert
  • Template-Struktur ist ein expliziter Parameter, der beim Erstellen des initialen Prompts erstellt wird
  • Derselbe Template-Struktur-Parameter wird dann für den Continuation-Prompt verwendet
  • Dies garantiert exakte Identität zwischen initialem und Continuation-Prompt

Ziel-Architektur:

  • Template wird beim Erstellen des initialen Prompts als expliziter Parameter erstellt
  • Template wird in promptArgs gespeichert beim Aufruf von callAiWithLooping()
  • Template wird aus promptArgs extrahiert und an buildContinuationContext() und promptBuilder übergeben
  • Keine Extraktion aus Prompt-String - Template ist ein expliziter Parameter, garantiert identisch

Beispiel-Implementierung:

# Beim Erstellen des initialen Prompts:
def _buildSectionGenerationPrompt(
    self,
    section: Dict[str, Any],
    contentParts: List[ContentPart],
    userPrompt: str,
    generationHint: str,
    allSections: List[Dict[str, Any]],
    sectionIndex: int,
    isAggregation: bool,
    language: str
) -> tuple[str, str]:  # Gibt (prompt, templateStructure) zurück
    """Build section generation prompt and return prompt + template structure.
    
    WICHTIG: templateStructure wird hier ERSTELLT (nicht extrahiert) und als separater
    Parameter zurückgegeben. Derselbe Parameter wird dann für den Continuation-Prompt verwendet.
    """
    
    contentType = section.get("content_type", "paragraph")
    contentStructureExample = self._getContentStructureExample(contentType)
    
    # Template-Struktur explizit ERSTELLEN (nicht extrahieren!)
    # Dies ist der Parameter, der später für den Continuation-Prompt verwendet wird
    templateStructure = f"""{{
  "elements": [
    {{
      "type": "{contentType}",
      "content": {contentStructureExample}
    }}
  ]
}}"""
    
    # Prompt mit Template erstellen (Template wird hier eingebettet)
    prompt = f"""...
Return ONLY valid JSON in this format:
{templateStructure}
..."""
    
    # WICHTIG: Beide zurückgeben - prompt UND templateStructure als separater Parameter
    return prompt, templateStructure  # templateStructure wird NICHT aus prompt extrahiert!

# Beim Aufruf von callAiWithLooping:
prompt, templateStructure = self._buildSectionGenerationPrompt(...)
promptArgs["templateStructure"] = templateStructure  # In promptArgs speichern
promptArgs["basePrompt"] = prompt  # BasePrompt auch speichern

# Später im Continuation-Prompt:
templateStructure = promptArgs.get("templateStructure")  # Aus promptArgs holen
basePrompt = promptArgs.get("basePrompt")  # BasePrompt aus promptArgs holen
continuationContext = buildContinuationContext(
    allSections, lastRawResponse, useCaseId, templateStructure
)

# Dataclass erstellen (nach Migration):
sectionArgs = SectionPromptArgs(
    section=promptArgs["section"],
    contentParts=promptArgs["contentParts"],
    userPrompt=promptArgs["userPrompt"],
    generationHint=promptArgs["generationHint"],
    allSections=promptArgs["allSections"],
    sectionIndex=promptArgs["sectionIndex"],
    isAggregation=promptArgs["isAggregation"],
    services=promptArgs["services"]
)

iterationPrompt = await promptBuilder(
    continuationContext=continuationContext,
    templateStructure=templateStructure,  # Derselbe Parameter wie im initialen Prompt
    basePrompt=basePrompt,  # Derselbe Prompt wie initial
    promptArgs=sectionArgs  # Dataclass statt **kwargs
)

Vorteil:

  • Garantierte Identität: Initialer und Continuation-Prompt verwenden exakt denselben Template-Parameter
  • Keine Extraktion nötig: Template wird nicht aus Prompt-String geparst
  • Einfacher: Template wird einmal erstellt und wiederverwendet

Erforderliche Änderungen:

  1. Alle Prompt-Erstellungs-Funktionen anpassen:
    • Template-Struktur explizit erstellen (nicht extrahieren!)
    • Template-Struktur als separater Rückgabewert zurückgeben: (prompt, templateStructure)
    • Template-Struktur in promptArgs speichern beim Aufruf von callAiWithLooping()
  2. In callAiWithLooping():
    • templateStructure aus promptArgs holen (REQUIRED - Fehler wenn fehlt)
    • basePrompt aus prompt Parameter holen (ist der initiale Prompt)
    • Beide an buildContinuationContext() und promptBuilder übergeben
  3. Alle Prompt-Builder anpassen:
    • templateStructure als expliziten Parameter akzeptieren (nicht extrahieren!)
    • basePrompt als expliziten Parameter akzeptieren (nicht regenerieren!)
    • Template und BasePrompt direkt verwenden (garantiert identisch mit initialem Prompt)

4. Konsolidierung: 3 Instanzen → 1 Funktion

Aktueller Zustand:

  • 3 identische Instanzen von buildSectionPromptWithContinuation() in subStructureFilling.py
  • Unterschiede nur in promptArgs (z.B. contentParts manchmal leer, manchmal gefüllt)

Ziel-Architektur:

class StructureFiller:
    """Handles structure filling for document generation."""
    
    async def buildSectionPromptWithContinuation(
        self,
        continuationContext: Dict[str, Any],
        templateStructure: str,  # NEU: Expliziter Parameter
        section: Dict[str, Any],
        contentParts: List[ContentPart],
        userPrompt: str,
        generationHint: str,
        allSections: List[Dict[str, Any]],
        sectionIndex: int,
        isAggregation: bool,
        language: str
    ) -> str:
        """
        Build section prompt with continuation context.
        
        Single unified implementation for all section content generation contexts.
        """
        # Build base prompt
        basePrompt = self._buildSectionGenerationPrompt(
            section=section,
            contentParts=contentParts,
            userPrompt=userPrompt,
            generationHint=generationHint,
            allSections=allSections,
            sectionIndex=sectionIndex,
            isAggregation=isAggregation,
            language=language
        )
        
        # Use provided templateStructure (from initial prompt)
        # This ensures exact match between initial and continuation prompts
        structureTemplate = f"""JSON Structure Template:
{templateStructure}

"""
        
        # Build continuation prompt with template and context
        ...

Erforderliche Änderungen:

  1. Eine einzige Methode buildSectionPromptWithContinuation() in StructureFiller Klasse definieren
  2. Alle 3 nested functions entfernen
  3. Alle Aufrufe anpassen, um die neue Methode zu verwenden

Zusammenfassung: Erforderliche Code-Änderungen

Priorität 1: Template-Struktur-Konsistenz (KRITISCH)

  1. ContinuationContext Pydantic-Modell erstellen (jsonUtils.py oder separate Model-Datei):

    • Alle Felder definieren: section_count, delivered_summary, cut_off_element, element_before_cutoff, template_structure, last_complete_part, incomplete_part, structure_context, last_raw_json
    • Optional-Felder korrekt markieren
  2. buildContinuationContext() erweitern (jsonUtils.py):

    • Parameter templateStructure: Optional[str] hinzufügen
    • Rückgabetyp ändern von Dict[str, Any] zu ContinuationContext
    • ContinuationContext-Instanz erstellen und zurückgeben statt Dict
  3. Prompt-Erstellungs-Funktionen anpassen (z.B. _buildSectionGenerationPrompt(), _buildChapterStructurePrompt(), etc.):

    • Template-Struktur explizit erstellen (nicht extrahieren)
    • Template-Struktur in promptArgs speichern beim Erstellen des initialen Prompts
    • Template-Struktur als Teil des Prompts einbetten
  4. Alle Verwendungen von continuationContext anpassen:

    • Prompt-Builder (subStructureFilling.py, subStructureGeneration.py, codePath.py, etc.):
      • continuationContext.get("delivered_summary")continuationContext.delivered_summary
      • continuationContext.get("cut_off_element")continuationContext.cut_off_element
      • continuationContext.get("element_before_cutoff")continuationContext.element_before_cutoff
      • continuationContext.get("template_structure")continuationContext.template_structure
      • continuationContext.get("last_complete_part")continuationContext.last_complete_part
      • continuationContext.get("incomplete_part")continuationContext.incomplete_part
      • continuationContext.get("structure_context")continuationContext.structure_context
      • continuationContext.get("last_raw_json")continuationContext.last_raw_json
    • Andere Verwendungen (subPromptBuilderGeneration.py, etc.):
      • Alle Dict-Zugriffe auf Attribut-Zugriffe umstellen
  5. callAiWithLooping() anpassen (subAiCallLooping.py):

    • Parameter-Validierung: templateStructure und basePrompt aus promptArgs holen (REQUIRED - Fehler wenn fehlt)
    • Error Handling: ValueError werfen wenn templateStructure oder basePrompt fehlen
    • templateStructure an buildContinuationContext() übergeben
    • basePrompt aus prompt Parameter holen (ist der initiale Prompt)
    • continuationContext (Pydantic-Modell) an promptBuilder übergeben
    • templateStructure und basePrompt an promptBuilder übergeben

Priorität 2: Prompt-Builder-Harmonisierung

  1. buildSectionPromptWithContinuation() konsolidieren (subStructureFilling.py):

    • 3 Instanzen zu einer Methode zusammenführen
    • Als Klassenmethode definieren (nicht nested)
  2. Alle Prompt-Builder erweitern:

    • templateStructure als expliziten Parameter hinzufügen
    • Template aus Parameter verwenden (nicht aus continuationContext extrahieren)

Priorität 3: Typsicherheit (Optional, aber empfohlen)

  1. Typsichere Parameter einführen:
    • Dataclasses für Parameter-Strukturen erstellen
    • **kwargs durch explizite Parameter ersetzen

Use Cases im Detail

Hinweis zu JSON-Template-Strukturen: Die JSON-Template-Struktur im Prompt ist die Struktur, die der AI im initialen Prompt als Vorlage gegeben wird. Diese Struktur wird auch im Continuation-Prompt verwendet, um Konsistenz zu gewährleisten. Die Template-Struktur zeigt der AI, welches JSON-Format erwartet wird.


1. section_content

JSON-Template-Struktur im Prompt:

{
  "elements": [
    {
      "type": "{contentType}",
      "content": {contentStructureExample}
    }
  ]
}

Template-Quelle: _getContentStructureExample(contentType) - dynamisch je nach contentType:

  • table: {"headers": ["Column1", "Column2"], "rows": [["Value1", "Value2"], ["Value3", "Value4"]]}
  • bullet_list: {"items": ["Item 1", "Item 2", "Item 3"]}
  • heading: {"text": "Section Title", "level": 2}
  • paragraph: {"text": "This is paragraph text."}
  • code_block: {"code": "function example() { return true; }", "language": "javascript"}
  • image: {"base64Data": "<base64_encoded_image_data>", "altText": "Description", "caption": "Optional caption"}

Prompt-Location: subStructureFilling.py Zeile 2338-2348 ("## OUTPUT FORMAT")

Looping-Mechanismus:

  • In loopingUseCases Liste: Ja
  • In directReturnUseCases Liste: Ja
  • Unterstützt Iterationen: Ja
  • Unterstützt Accumulation: Nein (supportsAccumulation=False)
  • Requires Extraction: Nein (requiresExtraction=False)

Prompt-Builder:

  • Spezifisch: buildSectionPromptWithContinuation() (3 Instanzen → SOLLTE konsolidiert werden)
  • Parameter: Alle promptArgs werden übergeben
  • Location: subStructureFilling.py (nested functions → SOLLTE Klassenmethode werden)

Merging-Strategie:

  • String-basiertes Merging mit Overlap-Detection
  • Fallback auf Deep-Structure-Merging bei Parsing-Fehlern
  • Normalisierung: Konvertiert Listen von Strings zu paragraph Elementen

Besonderheiten:

  • Verwendet spezifischen Prompt-Builder (buildSectionPromptWithContinuation)
  • JSON-Struktur-Template kommt aus initialem Prompt (_getContentStructureExample())
  • PROBLEM: 3 verschiedene Implementierungen des Prompt-Builders (je nach Kontext)
  • Template-Struktur-Quelle: KORREKT - Kommt aus initialem Prompt, nicht aus Response-Extraktion

Template-Struktur-Quelle Analyse:

  • section_content: Template kommt aus initialem Prompt via _getContentStructureExample(contentType)
  • Template wird dynamisch generiert basierend auf contentType (z.B. table, paragraph, etc.)
  • Template wird im Continuation-Prompt exakt wiederholt (gleiche Logik wie im initialen Prompt)
  • Keine Extraktion aus Response - Template wird als Parameter übergeben (Ziel-Architektur)

Template-Konsistenz geprüft:

  • Initial: subStructureFilling.py Zeile 2342-2349 ("## OUTPUT FORMAT")
  • Continuation: subStructureFilling.py Zeile 877-887 ("JSON Structure Template")
  • Status: IDENTISCH - Beide verwenden contentType = section.get("content_type", "paragraph") und contentStructureExample = self._getContentStructureExample(contentType)

2. chapter_structure

JSON-Template-Struktur im Prompt:

{
  "metadata": {
    "title": "...",
    "language": "..."
  },
  "documents": [{
    "id": "doc_1",
    "title": "...",
    "filename": "...",
    "outputFormat": "...",
    "language": "...",
    "chapters": [
      {
        "id": "chapter_1",
        "level": 1,
        "title": "...",
        "contentParts": {},
        "generationHint": "...",
        "sections": []
      }
    ]
  }]
}

Template-Quelle: Im initialen Prompt bei "EXAMPLE STRUCTURE" (Zeile 418-445 in subStructureGeneration.py)

Prompt-Location: subStructureGeneration.py Zeile 418-445 ("EXAMPLE STRUCTURE")

Looping-Mechanismus:

  • In loopingUseCases Liste: Ja
  • In directReturnUseCases Liste: Ja
  • Unterstützt Iterationen: Ja
  • Unterstützt Accumulation: Nein (supportsAccumulation=False)
  • Requires Extraction: Nein (requiresExtraction=False)

Prompt-Builder:

  • Spezifisch: buildChapterStructurePromptWithContinuation() (nested function in subStructureGeneration.py)
  • Parameter: Alle promptArgs werden übergeben (userPrompt, contentParts, outputFormat, services)
  • Location: subStructureGeneration.py (nested function)

Merging-Strategie:

  • String-basiertes Merging mit Overlap-Detection
  • Fallback auf Deep-Structure-Merging bei Parsing-Fehlern
  • Direkter Return nach Completion

Besonderheiten:

  • Verwendet spezifischen Prompt-Builder (buildChapterStructurePromptWithContinuation)
  • JSON-Struktur-Template kommt aus initialem Prompt ("EXAMPLE STRUCTURE")
  • Template wird im Continuation-Prompt exakt wiederholt

Template-Konsistenz geprüft:

  • Initial: subStructureGeneration.py Zeile 418-445 ("EXAMPLE STRUCTURE")
  • Continuation: subStructureGeneration.py Zeile 111-155 (buildChapterStructurePromptWithContinuation)
  • Status: IDENTISCH - Beide verwenden das gleiche Template aus _buildChapterStructurePrompt()

3. code_structure

JSON-Template-Struktur im Prompt:

{
  "metadata": {
    "language": "",
    "projectType": "single_file|multi_file",
    "projectName": ""
  },
  "files": [
    {
      "id": "",
      "filename": "",
      "fileType": "",
      "dependencies": [],
      "imports": [],
      "functions": [],
      "classes": []
    }
  ]
}

Template-Quelle: Im initialen Prompt bei "## FILE STRUCTURE REQUIREMENTS" (Zeile 276-303 in codePath.py)

Prompt-Location: codePath.py Zeile 276-303 ("## FILE STRUCTURE REQUIREMENTS")

Looping-Mechanismus:

  • In loopingUseCases Liste: Ja
  • In directReturnUseCases Liste: Ja
  • Unterstützt Iterationen: Ja
  • Unterstützt Accumulation: Nein (supportsAccumulation=False)
  • Requires Extraction: Nein (requiresExtraction=False)

Prompt-Builder:

  • Status: FEHLT - Kein promptBuilder wird übergeben
  • Problem: Continuation-Prompts werden nicht unterstützt

Merging-Strategie:

  • String-basiertes Merging mit Overlap-Detection
  • Fallback auf Deep-Structure-Merging bei Parsing-Fehlern
  • Direkter Return nach Completion

Besonderheiten:

  • KRITISCH: Es gibt KEINEN promptBuilder für code_structure!
  • Continuation-Prompts werden nicht gebaut, daher keine Iterationen möglich

Template-Konsistenz geprüft:

  • Initial: codePath.py Zeile 276-303 ("## FILE STRUCTURE REQUIREMENTS")
  • Continuation: FEHLT - Kein Prompt-Builder vorhanden
  • Status: PROBLEM - Es gibt KEINEN promptBuilder für code_structure! Continuation-Prompts werden nicht unterstützt.
  • Erforderliche Änderung: Ein buildCodeStructurePromptWithContinuation() muss erstellt werden, der:
    1. Das Template aus "## FILE STRUCTURE REQUIREMENTS" (Zeile 276-303) extrahiert
    2. Es im Continuation-Prompt als "JSON Structure Template:" wiederholt
    3. Die gleiche Struktur wie buildChapterStructurePromptWithContinuation verwendet

4. code_content

JSON-Template-Struktur im Prompt:

{
  "files": [
    {
      "filename": "{filename}",
      "content": "// Complete code here",
      "functions": [],
      "classes": []
    }
  ]
}

Template-Quelle: Im initialen Prompt bei "Return ONLY valid JSON in this format:" (Zeile 668-678 in codePath.py)

Prompt-Location: codePath.py Zeile 643-679

Looping-Mechanismus:

  • In loopingUseCases Liste: Ja
  • In directReturnUseCases Liste: Ja
  • Unterstützt Iterationen: Ja
  • Unterstützt Accumulation: Ja (supportsAccumulation=True)
  • Requires Extraction: Nein (requiresExtraction=False)

Prompt-Builder:

  • Spezifisch: buildCodeContentPromptWithContinuation() (nested function in codePath.py)
  • Parameter: Alle promptArgs werden übergeben (filename, fileType, functions, classes, dependencies, metadata, userPrompt, contentParts, contextInfo, services)
  • Location: codePath.py (nested function)

Merging-Strategie:

  • String-basiertes Merging mit Overlap-Detection
  • Fallback auf Deep-Structure-Merging bei Parsing-Fehlern
  • Direkter Return nach Completion

Besonderheiten:

  • Verwendet spezifischen Prompt-Builder (buildCodeContentPromptWithContinuation)
  • JSON-Struktur-Template kommt aus initialem Prompt (Zeile 668-678)
  • Template wird im Continuation-Prompt exakt wiederholt

Template-Konsistenz geprüft:

  • Initial: codePath.py Zeile 668-678 ("Return ONLY valid JSON in this format:")
  • Continuation: codePath.py Zeile 668-678 (wird im buildCodeContentPromptWithContinuation exakt wiederholt)
  • Status: IDENTISCH - Beide verwenden das gleiche Template mit den gleichen Beispielwerten

Merging-Strategien

Merging-Strategien:

  • Primär: String-basiertes Merging mit mergeJsonStringsWithOverlap()
  • Fallback: Deep-Structure-Merging bei Parsing-Fehlern (für alle Use Cases)
    • Wenn String-Merge erfolgreich, aber Parsing fehlschlägt: Versucht jedes Fragment einzeln zu parsen
    • Verwendet mergeDeepStructures() für intelligentes Merging der geparsten Fragmente
    • Funktioniert rekursiv für beliebige JSON-Strukturen (Arrays, Objekte, verschachtelt)
  • Overlap-Detection: Multi-Strategy (exact, line-based, partial line-based, structure-aware)

Continuation-Prompt-Strukturen im Detail

Fix vs. Variabel Analyse

Kernprinzip: Alle Iterations-Prompts sollten nach der gleichen Logik aufgebaut sein, aber für verschiedene JSON-Strukturen. Die Struktur des Iterations-Prompts selbst sollte bei allen Use Cases gleich sein.

FIX (sollte bei allen Use Cases identisch sein)

Element Inhalt Beschreibung
Separator --- CONTINUATION REQUEST --- Trennlinie zwischen Base Prompt und Continuation-Anweisungen
Einleitung The previous JSON response was incomplete. Continue from where it stopped. Standard-Einleitung für alle Continuation-Requests
Section-Header JSON Structure Template: Header für Template-Sektion
Section-Header Context showing structure hierarchy with cut point: Header für Context-Sektion
Section-Header Overlap Requirement: Header für Overlap-Anweisungen
Overlap-Anweisung To ensure proper merging, your response MUST start by repeating approximately the last 100 characters from the previous response, then continue with new content. Standard-Overlap-Anweisung
Section-Header Last ~100 characters from previous response (repeat these at the start): Header für Overlap-Context
Section-Header TASK: Header für Task-Anweisungen
TASK Punkt 1 Start your response by repeating the last ~100 characters shown above (for overlap/merging) Overlap-Start-Anweisung
TASK Punkt 2 Complete the incomplete element shown in the context above (marked with CUT POINT) Completion-Anweisung
TASK Punkt 3 Continue generating the remaining content following the JSON structure template above Continuation-Anweisung
TASK Punkt 4 Return ONLY valid JSON following the structure template - no overlap/continuation wrapper objects Format-Anweisung
Section-Header CRITICAL: Header für kritische Anweisungen
CRITICAL Punkt 1 Your response must be valid JSON matching the structure template above JSON-Format-Anforderung
CRITICAL Punkt 2 Start with overlap (~100 chars) then continue seamlessly Overlap-Seamless-Anweisung
CRITICAL Punkt 3 Complete the incomplete element and continue with remaining elements Completion-Continuation-Anweisung

🔄 VARIABEL (use-case-spezifisch)

Element Beschreibung Aktuelle Implementierung
basePrompt Initialer Prompt (use-case-spezifisch) Wird als Parameter übergeben, variiert je nach Use Case
structureTemplate JSON-Struktur-Template (use-case-spezifisch) Wird aus initialem Prompt extrahiert oder als Parameter übergeben
unifiedContext Hierarchischer Cut-Point-Context (use-case-spezifisch, aber gleiche Logik) Wird aus _buildIncompleteContext() erstellt - sollte für alle Use Cases nach gleicher Logik funktionieren
overlapContext Letzte ~100 Zeichen (gleiche Logik, aber unterschiedlicher Inhalt) lastRawJson[-100:].strip() - gleiche Logik für alle

⚠️ MANDATORY: Alle Use Cases müssen die einheitliche Struktur verwenden

Wichtig:

  • Fix-Elemente MÜSSEN bei allen Use Cases exakt identisch sein - keine Variationen erlaubt
  • 🔄 Variable Elemente variieren im Inhalt, aber die Logik zur Erstellung ist gleich
  • Alle Use Cases (section_content, chapter_structure, code_structure, code_content) verwenden dieselbe Continuation-Prompt-Struktur

Einheitliche Continuation-Prompt-Struktur (Ziel)

⚠️ MANDATORY: Alle Use Cases MÜSSEN diese einheitliche Struktur verwenden

Keine Variationen erlaubt - alle Use Cases (section_content, chapter_structure, code_structure, code_content) verwenden exakt dieselbe Continuation-Prompt-Struktur:

  1. Base Prompt (initialer Prompt - unverändert, als Parameter übergeben)
  2. --- CONTINUATION REQUEST --- (Trennlinie)
  3. JSON Structure Template: (Header)
  4. Template-Struktur (exakt identisch mit initialem Prompt, als Parameter übergeben)
  5. Context showing structure hierarchy with cut point: (Header)
  6. Hierarchischer Context (hierarchischer Cut-Point-Context)
  7. Overlap Requirement: (Header)
  8. Overlap-Anweisung (~100 Zeichen)
  9. Last ~100 characters from previous response (repeat these at the start): (Header)
  10. Overlap-Context (letzte ~100 Zeichen)
  11. TASK: (Header)
  12. TASK-Anweisungen (4 Punkte)
  13. CRITICAL: (Header)
  14. CRITICAL-Anweisungen (3 Punkte)

⚠️ KRITISCH: Template-Konsistenz

  • Das JSON Structure Template im Continuation-Prompt MUSS exakt identisch mit dem Template im initialen Prompt sein
  • Template wird NICHT extrahiert - es wird als expliziter Parameter (templateStructure) übergeben
  • BasePrompt wird NICHT regeneriert - es wird als expliziter Parameter (basePrompt) übergeben
  • Dies garantiert exakte Identität zwischen initialem und Continuation-Prompt

Die 3 Prompt-Systeme für section_content

Besonderheit: Der section_content Use Case verwendet 3 verschiedene Prompt-Systeme, die sich durch den Verarbeitungsmodus unterscheiden, aber alle die gleiche Template-Struktur verwenden:

System 1: Aggregation-Modus

Kontext: if needsAggregation and useAiCall

Verwendung:

  • Alle ContentParts einer Section werden zusammen verarbeitet
  • Ein einziger AI-Call für alle Parts
  • Verwendet isAggregation=True im Prompt

Code-Location:

  • subStructureFilling.py Zeile ~611-922
  • buildSectionPromptWithContinuation Zeile ~814-901

Besonderheiten:

  • Verarbeitet mehrere ContentParts gleichzeitig
  • Aggregiert alle Parts zu einem einzigen Prompt
  • Verwendet useCaseId="section_content"

System 2: Einzelverarbeitung ohne ContentParts

Kontext: if len(contentPartIds) == 0 and useAiCall and generationHint

Verwendung:

  • Keine ContentParts vorhanden
  • Generation nur mit generationHint
  • Content wird von Grund auf generiert

Code-Location:

  • subStructureFilling.py Zeile ~1039-1208
  • buildSectionPromptWithContinuation Zeile ~1101-1197

Besonderheiten:

  • Generiert Content ohne Input-ContentParts
  • Verwendet nur generationHint als Basis
  • Verwendet useCaseId="section_content"

System 3: Einzelverarbeitung mit ContentParts

Kontext: Einzelne ContentParts werden nacheinander verarbeitet

Verwendung:

  • Einzelne ContentParts werden sequenziell verarbeitet
  • Jeder Part wird einzeln an die AI gesendet
  • Mehrere AI-Calls pro Section (einer pro Part)

Code-Location:

  • subStructureFilling.py Zeile ~1350-1570
  • buildSectionPromptWithContinuation Zeile ~1463-1567

Besonderheiten:

  • Verarbeitet Parts einzeln
  • Kann mehrere Iterationen pro Section haben
  • Verwendet useCaseId="section_content"

Gemeinsame Basis aller 3 Systeme:

  • Alle verwenden die gleiche Template-Struktur aus _getContentStructureExample()
  • Alle verwenden useCaseId="section_content"
  • Alle verwenden die gleiche Continuation-Prompt-Struktur (Fix-Elemente)
  • Alle verwenden buildSectionPromptWithContinuation() (aktuell 3 Instanzen, zukünftig 1 konsolidierte Funktion)

Entscheidungslogik (in _processSingleSection()):

if needsAggregation and useAiCall:
    # System 1: Aggregation
elif len(contentPartIds) == 0 and useAiCall and generationHint:
    # System 2: Ohne ContentParts
else:
    # System 3: Mit ContentParts (Einzelverarbeitung)

Ziel-Architektur:

  • Alle 3 Systeme sollten die konsolidierte buildSectionPromptWithContinuation() Klassenmethode verwenden
  • Template-Struktur wird als Parameter übergeben (garantiert Identität)
  • BasePrompt wird als Parameter übergeben (garantiert Identität)

Error Handling

Parameter-Validierung in callAiWithLooping():

# In subAiCallLooping.py:
if (len(allSections) > 0 or lastRawResponse) and promptBuilder and promptArgs:
    # REQUIRED: templateStructure und basePrompt müssen in promptArgs vorhanden sein
    templateStructure = promptArgs.get("templateStructure")
    if not templateStructure:
        raise ValueError(
            f"templateStructure is REQUIRED in promptArgs for use case '{useCaseId}'. "
            "Prompt creation functions must return (prompt, templateStructure) tuple."
        )
    
    basePrompt = promptArgs.get("basePrompt")
    if not basePrompt:
        # Fallback: use prompt parameter (should be the same)
        basePrompt = prompt
        # Log warning if they differ
        if basePrompt != prompt:
            logger.warning(
                f"basePrompt not found in promptArgs for use case '{useCaseId}', "
                "using prompt parameter instead. This may indicate a bug."
            )
    
    # Build continuation context
    continuationContext = buildContinuationContext(
        allSections, lastRawResponse, useCaseId, templateStructure
    )
    
    # Call prompt builder with validated parameters
    iterationPrompt = await promptBuilder(
        continuationContext=continuationContext,
        templateStructure=templateStructure,
        basePrompt=basePrompt,
        **promptArgs  # During migration, still use **kwargs
    )

Error Messages:

  • Klare Fehlermeldungen wenn REQUIRED Parameter fehlen
  • Hinweise auf erwartete Format (z.B. "Prompt creation functions must return (prompt, templateStructure) tuple")
  • Logging für Warnungen (z.B. wenn basePrompt nicht in promptArgs gefunden wird)

Implementierungs-Roadmap

Phase 1: ContinuationContext Pydantic-Modell und Template-Struktur-Parameter (KRITISCH)

  1. ContinuationContext Pydantic-Modell erstellen (jsonUtils.py oder separate Model-Datei)
  2. buildContinuationContext() um templateStructure Parameter erweitern
  3. buildContinuationContext() Rückgabetyp ändern von Dict[str, Any] zu ContinuationContext
  4. Alle Prompt-Erstellungs-Funktionen anpassen, um templateStructure zu erstellen (nicht extrahieren!) und als (prompt, templateStructure) Tuple zurückzugeben
  5. Alle Aufrufe anpassen, um templateStructure in promptArgs zu speichern
  6. callAiWithLooping() anpassen, um templateStructure aus promptArgs zu holen (mit Validierung) und an buildContinuationContext() zu übergeben
  7. Alle Prompt-Builder um templateStructure Parameter erweitern (als expliziten Parameter, nicht extrahieren!)

Phase 2: BasePrompt als Parameter

  1. Alle Prompt-Erstellungs-Funktionen anpassen, um basePrompt in promptArgs zu speichern (oder aus prompt Parameter verwenden)
  2. callAiWithLooping() anpassen, um basePrompt aus promptArgs zu holen (mit Validierung)
  3. Alle Prompt-Builder um basePrompt Parameter erweitern (als expliziten Parameter, nicht regenerieren!)
  4. BasePrompt als Parameter übergeben (garantiert Identität mit initialem Prompt)

Phase 3: Prompt-Builder-Konsolidierung und einheitliche Continuation-Prompt-Struktur

  1. buildSectionPromptWithContinuation() konsolidieren (3 → 1)
  2. buildCodeStructurePromptWithContinuation() implementieren (fehlt aktuell)
  3. Alle Prompt-Builder als Klassenmethoden definieren (nicht nested)
  4. Alle Prompt-Builder auf einheitliche Continuation-Prompt-Struktur umstellen (siehe "Einheitliche Continuation-Prompt-Struktur")
  5. continuationContext als NICHT-Optional Parameter (wird immer übergeben, Typ: ContinuationContext)

Phase 4: Einheitliche Signatur

  1. Alle Builder auf einheitliche Signatur umstellen:
    • continuationContext: ContinuationContext (Pydantic-Modell, NICHT Optional)
    • templateStructure: str (expliziter Parameter)
    • basePrompt: str (expliziter Parameter)
    • promptArgs: Any (während Migration noch Dict, später Dataclass)

Phase 5: Typsicherheit mit Dataclasses

  1. Dataclasses für Parameter-Strukturen einführen (SectionPromptArgs, ChapterStructurePromptArgs, CodeContentPromptArgs, CodeStructurePromptArgs)
  2. Schrittweise Migration von **kwargs zu Dataclass-Parametern
  3. Alle Builder auf Dataclass-basierte Parameter umstellen (promptArgs: SectionPromptArgs statt promptArgs: Any)