wiki/z-archive/appdoc/doc_architecture_ai_service.html

814 lines
34 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PowerON - AI Service Architektur</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%);
color: #333;
padding: 20px;
line-height: 1.6;
}
.container {
max-width: 1400px;
margin: 0 auto;
background: white;
border-radius: 20px;
padding: 40px;
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
}
h1 {
color: #e74c3c;
font-size: 2.5em;
margin-bottom: 10px;
text-align: center;
border-bottom: 4px solid #c0392b;
padding-bottom: 20px;
}
h2 {
color: #c0392b;
font-size: 2em;
margin-top: 40px;
margin-bottom: 20px;
border-left: 5px solid #e74c3c;
padding-left: 15px;
}
h3 {
color: #e74c3c;
font-size: 1.5em;
margin-top: 30px;
margin-bottom: 15px;
}
.diagram {
background: #f8f9fa;
border: 2px solid #e74c3c;
border-radius: 10px;
padding: 30px;
margin: 30px 0;
position: relative;
overflow: hidden;
}
.service-box {
background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%);
color: white;
padding: 20px;
border-radius: 10px;
margin: 15px 0;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
transition: transform 0.3s ease;
}
.service-box:hover {
transform: translateY(-5px);
}
.service-box h4 {
font-size: 1.3em;
margin-bottom: 10px;
}
.service-box p {
margin: 8px 0;
}
.component-box {
background: white;
border: 3px solid #e74c3c;
border-radius: 10px;
padding: 20px;
margin: 15px 0;
display: inline-block;
width: 100%;
}
.component-box h4 {
color: #e74c3c;
font-size: 1.2em;
margin-bottom: 10px;
}
.flow-arrow {
text-align: center;
font-size: 2em;
color: #e74c3c;
margin: 10px 0;
}
.method-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
margin: 20px 0;
}
.method-card {
background: white;
border: 2px solid #e74c3c;
border-radius: 10px;
padding: 15px;
transition: all 0.3s ease;
}
.method-card:hover {
box-shadow: 0 10px 25px rgba(231, 76, 60, 0.3);
transform: translateY(-3px);
}
.method-card h4 {
color: #c0392b;
margin-bottom: 10px;
font-size: 1.1em;
}
.method-badge {
display: inline-block;
background: #e74c3c;
color: white;
padding: 5px 10px;
border-radius: 5px;
font-size: 0.85em;
margin-right: 10px;
margin-bottom: 5px;
}
.example-flow {
background: linear-gradient(135deg, #fef5e7 0%, #fad7a0 100%);
border: 3px solid #e74c3c;
border-radius: 15px;
padding: 25px;
margin: 30px 0;
}
.step-box {
background: white;
border-left: 5px solid #e74c3c;
border-radius: 5px;
padding: 15px;
margin: 15px 0;
box-shadow: 0 3px 10px rgba(0,0,0,0.1);
}
.step-box h5 {
color: #c0392b;
margin-bottom: 10px;
font-size: 1.1em;
}
.loop-visualization {
background: #fff3e0;
border: 2px dashed #ff9800;
border-radius: 10px;
padding: 20px;
margin: 20px 0;
}
.loop-step {
background: white;
border: 1px solid #ff9800;
border-radius: 5px;
padding: 10px;
margin: 10px 0;
position: relative;
}
.loop-step::before {
content: "→";
position: absolute;
left: -20px;
top: 50%;
transform: translateY(-50%);
color: #ff9800;
font-weight: bold;
}
.legend {
background: #f8f9fa;
border: 2px solid #e74c3c;
border-radius: 10px;
padding: 20px;
margin: 20px 0;
}
.legend-item {
display: flex;
align-items: center;
margin: 10px 0;
}
.legend-color {
width: 30px;
height: 30px;
border-radius: 5px;
margin-right: 10px;
}
code {
background: #f4f4f4;
padding: 2px 6px;
border-radius: 3px;
font-family: 'Courier New', monospace;
color: #e83e8c;
}
ul, ol {
margin-left: 30px;
margin-top: 10px;
}
li {
margin: 8px 0;
}
.highlight {
background: #fff3cd;
padding: 2px 6px;
border-radius: 3px;
}
.info-box {
background: #d1ecf1;
border: 2px solid #0c5460;
border-radius: 10px;
padding: 15px;
margin: 20px 0;
}
.warning-box {
background: #fff3cd;
border: 2px solid #856404;
border-radius: 10px;
padding: 15px;
margin: 20px 0;
}
.success-box {
background: #d4edda;
border: 2px solid #28a745;
border-radius: 10px;
padding: 15px;
margin: 20px 0;
}
.architecture-diagram {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border: 3px solid #e74c3c;
border-radius: 15px;
padding: 25px;
margin: 30px 0;
}
.layer-box {
background: white;
border: 2px solid #e74c3c;
border-radius: 10px;
padding: 15px;
margin: 15px 0;
display: flex;
align-items: center;
justify-content: space-between;
}
.layer-box .layer-label {
font-weight: bold;
color: #e74c3c;
margin-right: 20px;
}
</style>
</head>
<body>
<div class="container">
<h1>PowerON AI Service Architektur</h1>
<div class="info-box">
<strong>📖 Dokumentation:</strong> Diese Dokumentation beschreibt die Architektur des zentralen AI-Service von PowerON. Der Service orchestriert alle AI-Operationen und verwaltet die Kommunikation mit verschiedenen AI-Modellen und Services.
</div>
<h2>1. High-Level Übersicht</h2>
<div class="diagram">
<div class="service-box">
<h4>🎯 AI Service Center</h4>
<p><code>@modules/services/serviceAi/mainServiceAi.py</code></p>
<p><strong>Rolle:</strong> Orchestrator, koordiniert alle AI-Operationen</p>
<p><strong>Verantwortung:</strong> Lazy Initialization, Delegation, Public API</p>
</div>
<div class="flow-arrow">⬇️</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div class="component-box">
<h4>🔧 Core AI Operations</h4>
<code>@subCoreAi.py</code>
<ul style="font-size: 0.95em; margin-top: 10px;">
<li>callAiPlanning() - JSON Planning</li>
<li>callAiDocuments() - Dokument-Verarbeitung</li>
<li>readImage() - Bildanalyse</li>
<li>generateImage() - Bildgenerierung</li>
<li>Looping-System für lange Antworten</li>
</ul>
</div>
<div class="component-box">
<h4>📄 Document Processing</h4>
<code>@subDocumentProcessing.py</code>
<ul style="font-size: 0.95em; margin-top: 10px;">
<li>processDocumentsPerChunk()</li>
<li>processDocumentsPerChunkJson()</li>
<li>Extraction-Integration</li>
<li>Merging-Logik</li>
</ul>
</div>
</div>
<div class="flow-arrow">⬇️</div>
<div class="component-box">
<h4>🏗️ AI Interface Layer</h4>
<code>@interfaces/interfaceAiObjects.py (AiObjects)</code>
<ul style="font-size: 0.95em; margin-top: 10px;">
<li>Model Registry - Auto-Discovery von Connectors</li>
<li>Model Selector - Dynamische Model-Auswahl</li>
<li>Standardisierte Call-Interface</li>
<li>Price-Calculations</li>
</ul>
</div>
</div>
<h2>2. AI-Call-Prozess</h2>
<div class="example-flow">
<h3>🔄 Komponenten-Übersicht</h3>
<div class="architecture-diagram">
<div class="layer-box">
<div class="layer-label">📥 Input Layer</div>
<div style="flex: 1;">
<strong>Entry Points:</strong> callAiPlanning(), callAiDocuments()<br>
<code>prompt + options + placeholders/documents</code>
</div>
</div>
<div class="flow-arrow">⬇️</div>
<div class="layer-box">
<div class="layer-label">🔀 Orchestration Layer</div>
<div style="flex: 1;">
<strong>Placeholder Replacement → Prompt Building → Options Determination</strong><br>
<code>subSharedAiUtils.py</code> - buildPromptWithPlaceholders()
</div>
</div>
<div class="flow-arrow">⬇️</div>
<div class="layer-box">
<div class="layer-label">🌐 AI Call Layer</div>
<div style="flex: 1;">
<strong>Looping System → Model Selection → API Call → Response Processing</strong><br>
<code>_callAiWithLooping() → AiObjects.call()</code>
</div>
</div>
<div class="flow-arrow">⬇️</div>
<div class="layer-box">
<div class="layer-label">📊 Response Layer</div>
<div style="flex: 1;">
<strong>JSON Merging → Debug Logging → Stats Tracking</strong><br>
<code>_mergeJsonContent() → writeDebugFile() → storeWorkflowStat()</code>
</div>
</div>
<div class="flow-arrow">⬇️</div>
<div class="layer-box">
<div class="layer-label">📤 Output Layer</div>
<div style="flex: 1;">
<strong>Return → Document Processing → Generation</strong><br>
<code>result → Extracted Content → Final Documents</code>
</div>
</div>
</div>
</div>
<h2>3. Looping-System für lange Antworten</h2>
<div class="loop-visualization">
<h3>🔄 Multi-Iteration Processing</h3>
<p style="margin-bottom: 15px;"><strong>Problem:</strong> Token-Limits können bei großen Ausgaben überschritten werden</p>
<p style="margin-bottom: 15px;"><strong>Lösung:</strong> Kontinuierliches Looping mit State-Transfer</p>
<div class="loop-step" style="background: #e8f5e9;">
<strong>Iteration 1:</strong> Start des AI-Calls<br>
<code>prompt + LOOP_INSTRUCTION → AI Response</code><br>
<span style="color: #2e7d32;">→ Response wird an Token-Limit evaluiert</span>
</div>
<div class="loop-step" style="background: #fff3e0;">
<strong>Continuation Check:</strong> Response enthält <code>{"continuation": {...}}</code><br>
<code>if continuation != null:</code> Weiter mit next_instruction<br>
<span style="color: #f57c00;">→ Letzte Daten + nächste Anweisung gespeichert</span>
</div>
<div class="loop-step" style="background: #e8f5e9;">
<strong>Iteration N:</strong> Continuation wird erneut verarbeitet<br>
<code>continuation_prompt + previous_state → AI Response</code><br>
<span style="color: #2e7d32;">→ Neue Daten werden akkumuliert</span>
</div>
<div class="loop-step" style="background: #e3f2fd;">
<strong>Final:</strong> <code>{"continuation": null}</code> erreicht<br>
<code>_mergeJsonContent()</code> - Alle JSON-Listen werden zusammengeführt<br>
<span style="color: #1976d2;">→ Komplette Antwort wird zurückgegeben</span>
</div>
</div>
<div class="info-box">
<strong>💡 Wichtige Features des Looping-Systems:</strong>
<ul>
<li><strong>Max 100 Iterations</strong> - Verhindert Endlosschleifen</li>
<li><strong>Automatisches JSON-Merging</strong> - Listen werden intelligent zusammengeführt</li>
<li><strong>Debug Logging</strong> - Jede Iteration wird in separate Dateien gespeichert</li>
<li><strong>Continuation Detection</strong> - Nur aktiv wenn <code>LOOP_INSTRUCTION</code> im Prompt ist</li>
<li><strong>Stats Tracking</strong> - Jede Iteration erzeugt Workflow-Statistiken</li>
</ul>
</div>
<h2>4. Verfügbare Methoden</h2>
<div class="diagram">
<h3>🚀 Public API Methods</h3>
<div class="method-grid">
<div class="method-card">
<span class="method-badge">Planning</span>
<h4>callAiPlanning()</h4>
<p><strong>Parameter:</strong></p>
<ul style="font-size: 0.9em;">
<li>prompt (required)</li>
<li>placeholders (optional)</li>
</ul>
<p style="margin-top: 10px;"><strong>Verwendung:</strong> Task Planning, Action Selection, Review</p>
<p style="margin-top: 10px; color: #28a745;">✓ Statische Parameter (QUALITY + DETAILED)</p>
</div>
<div class="method-card">
<span class="method-badge">Documents</span>
<h4>callAiDocuments()</h4>
<p><strong>Parameter:</strong></p>
<ul style="font-size: 0.9em;">
<li>prompt (required)</li>
<li>documents (optional)</li>
<li>options (optional)</li>
<li>outputFormat (optional)</li>
<li>title (optional)</li>
</ul>
<p style="margin-top: 10px;"><strong>Support:</strong> PDF, DOCX, TXT, HTML, JSON, CSV, XLSX, Bilder (JPG, PNG)</p>
<p style="margin-top: 10px;"><strong>Intern:</strong> Alles wird in Standard-JSON konvertiert (formatunabhängig)</p>
<p style="margin-top: 10px;"><strong>Features:</strong> Neutralizer, Image-Analysis, Multi-Format-Ausgabe</p>
<p style="margin-top: 10px; color: #ffc107;">⚙️ Adaptive Parameter via _analyzePromptAndCreateOptions()</p>
</div>
<div class="method-card">
<span class="method-badge">Image</span>
<h4>readImage()</h4>
<p><strong>Parameter:</strong></p>
<ul style="font-size: 0.9em;">
<li>prompt (required)</li>
<li>imageData (required)</li>
<li>mimeType (optional)</li>
<li>options (optional)</li>
</ul>
<p style="margin-top: 10px;"><strong>Verwendung:</strong> Direkte Bild-Analyse mit Vision-Modellen</p>
<p style="margin-top: 10px; color: #e74c3c;"> Auch integriert in callAiDocuments()!</p>
<p style="margin-top: 10px; color: #28a745;">✓ Operation: IMAGE_ANALYSE</p>
</div>
<div class="method-card">
<span class="method-badge">Image</span>
<h4>generateImage()</h4>
<p><strong>Parameter:</strong></p>
<ul style="font-size: 0.9em;">
<li>prompt (required)</li>
<li>size (optional)</li>
<li>quality (optional)</li>
<li>style (optional)</li>
</ul>
<p style="margin-top: 10px;"><strong>Verwendung:</strong> Direkte AI-Bildgenerierung</p>
<p style="margin-top: 10px; color: #e74c3c;"> Auch in Generation-Workflows integriert</p>
<p style="margin-top: 10px; color: #28a745;">✓ Delegiert an aiObjects.generateImage()</p>
</div>
</div>
</div>
<h2>5. Beispiel: AI-Call Flow</h2>
<div class="example-flow">
<h3>🎯 Use Case: Dokument-Verarbeitung mit AI</h3>
<div class="step-box">
<h5>📍 Step 1: Eingabe</h5>
<p style="font-size: 0.9em; color: #666;">Workflow-Call: <code>ai.process()</code></p>
<code style="display: block; background: #f4f4f4; padding: 10px; margin-top: 10px; border-radius: 5px;">
{
"aiPrompt": "Extrahiere alle wichtigen Fakten aus den Dokumenten",
"documentList": ["docList:msg_123"],
"resultType": "docx"
}
</code>
</div>
<div class="step-box">
<h5>🔄 Step 2: Prompt-Building</h5>
<p style="font-size: 0.9em; color: #666;">Placeholder Replacement (falls vorhanden)</p>
<code style="display: block; background: #f4f4f4; padding: 10px; margin-top: 10px; border-radius: 5px;">
buildPromptWithPlaceholders(
"{{KEY:TASK_OBJECTIVE}} extrahieren",
{"TASK_OBJECTIVE": "Spesenbelege"}
)
→ "Spesenbelege extrahieren"
</code>
</div>
<div class="step-box">
<h5>⚙️ Step 3: Options Determination</h5>
<p style="font-size: 0.9em; color: #666;">Adaptive oder Static Parameter?</p>
<ul style="font-size: 0.9em; margin-top: 10px;">
<li><strong>Planning:</strong> Static → QUALITY + DETAILED</li>
<li><strong>Documents:</strong> Optional → AI-gestützte Analyse via <code>_analyzePromptAndCreateOptions()</code></li>
</ul>
</div>
<div class="step-box">
<h5>🌐 Step 4: AI-Call mit Looping</h5>
<p style="font-size: 0.9em; color: #666;">Iteration 1 → Iteration N (falls continuation)</p>
<ul style="font-size: 0.9em; margin-top: 10px;">
<li><strong>Request erstellen:</strong> <code>AiCallRequest(prompt, options)</code></li>
<li><strong>Model Selection:</strong> <code>modelSelector.select(prompt, options)</code></li>
<li><strong>API Call:</strong> <code>model.functionCall(modelCall)</code></li>
<li><strong>Response:</strong> <code>AiCallResponse(content, modelName, priceUsd)</code></li>
<li><strong>Debug:</strong> Speicherung in <code>debug/[timestamp]_prompt.txt</code></li>
</ul>
</div>
<div class="step-box">
<h5>📊 Step 5: Response Processing</h5>
<p style="font-size: 0.9em; color: #666;">JSON Merging (falls Multi-Iteration)</p>
<code style="display: block; background: #f4f4f4; padding: 10px; margin-top: 10px; border-radius: 5px;">
if continuation != null:
# Weiter mit next_instruction
accumulatedContent.append(partialResponse)
continue
else:
# Final - alle JSON-Listen mergen
finalResult = _mergeJsonContent(accumulatedContent)
return finalResult
</code>
</div>
<div class="step-box">
<h5>📈 Step 6: Stats & Logging</h5>
<p style="font-size: 0.9em; color: #666;">Workflow-Statistiken speichern</p>
<code style="display: block; background: #f4f4f4; padding: 10px; margin-top: 10px; border-radius: 5px;">
storeWorkflowStat(
workflow,
aiCallResponse,
"ai.call.document_processing"
)
# Logs: processingTime, priceUsd, tokensUsed
</code>
</div>
<div class="success-box" style="margin-top: 20px;">
<h5 style="color: #155724;">✓ AI-Call abgeschlossen</h5>
<p style="margin-top: 10px;"><strong>Return:</strong> DOCX mit extrahierten Daten</p>
<p><strong>Iterations:</strong> 3 (wegen Token-Limits)</p>
<p><strong>Processing Time:</strong> 12.5s</p>
<p><strong>Cost:</strong> $0.0032 USD</p>
</div>
</div>
<h2>6. Neutralizer & Normalizer - Datenschutz & Formatunabhängigkeit</h2>
<div class="diagram">
<h3>🔒 Neutralizer - Datenschutz bei User-Dokumenten</h3>
<div class="warning-box" style="margin-bottom: 30px;">
<strong>🔐 Neutralizer-Funktion:</strong> Alle Dokumente, die im User-Prompt mitgeliefert werden, werden durch den Neutralizer geschleust, um personenbezogene und sensible Daten durch Platzhalter zu ersetzen.
</div>
<div style="display: grid; grid-template-columns: 1fr; gap: 20px;">
<div class="component-box" style="background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%);">
<h4>🔄 Datenschutz-Neutralisierung</h4>
<p style="margin-top: 10px;"><strong>Beispiel:</strong></p>
<code style="display: block; background: white; padding: 15px; margin-top: 10px; border-radius: 5px;">
<span style="color: #e74c3c;">Original:</span> "Max Mustermann, geboren am 01.01.1980 in Berlin"
<span style="color: #28a745;">Neutralisiert:</span> "{{person}}, geboren am {{date}} in {{city}}"
</code>
<ul style="margin-top: 15px; font-size: 0.9em;">
<li><strong>Personendaten:</strong> Namen → {{person}}</li>
<li><strong>Daten:</strong> Geburts-/Gesundheitsdaten → {{date}} / {{health_data}}</li>
<li><strong>Financial:</strong> Kontonummern, Kreditkarten → {{account_number}}</li>
<li><strong>Lokationen:</strong> Adressen → {{address}}</li>
<li><strong>Kontakte:</strong> E-Mails, Telefonnummern → {{contact}}</li>
</ul>
<p style="margin-top: 15px; color: #e74c3c;"><strong>✓ Automatisch bei allen User-Prompt-Dokumenten!</strong></p>
</div>
</div>
<div class="flow-arrow">⬇️</div>
<h3>📊 Normalizer - Formatunabhängige JSON-Struktur</h3>
<div class="info-box" style="margin-bottom: 30px;">
<strong>💡 Kern-Prinzip:</strong> Alle Dokument-Formate werden intern in ein einheitliches Standard-JSON-Format konvertiert. Dadurch ist die Verarbeitung formatunabhängig.
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div class="component-box">
<h4>📥 Input-Formate</h4>
<ul style="font-size: 0.95em;">
<li><strong>Dokumente:</strong> PDF, DOCX, TXT, HTML, JSON, CSV, XLSX</li>
<li><strong>Bilder:</strong> JPG, PNG, GIF, WebP</li>
<li><strong>Strukturierte Daten:</strong> XML, YAML</li>
<li><strong>Code:</strong> Python, JavaScript, etc.</li>
</ul>
<p style="margin-top: 15px; color: #e74c3c;"><strong>→ Normalizer:</strong></p>
<p style="font-size: 0.9em;">NormalizationService konvertiert alles in Standard-JSON-Struktur</p>
</div>
<div class="component-box">
<h4>📤 Output-Formate</h4>
<ul style="font-size: 0.95em;">
<li><strong>Dokumente:</strong> PDF, DOCX, HTML, TXT, MD</li>
<li><strong>Daten:</strong> JSON, CSV, XLSX</li>
<li><strong>Präsentation:</strong> Powerpoint</li>
<li><strong>Spezial:</strong> Custom Renderer</li>
</ul>
<p style="margin-top: 15px; color: #28a745;"><strong>→ Renderer:</strong></p>
<p style="font-size: 0.9em;">Generation-Service rendert JSON → gewünschtes Format</p>
</div>
</div>
<div class="flow-arrow">⬇️</div>
<div class="component-box" style="background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);">
<h4>📊 Standard-JSON Struktur</h4>
<code style="display: block; background: white; padding: 15px; margin-top: 10px; border-radius: 5px; white-space: pre-wrap;">
{
"metadata": {
"title": "Document Title",
"format": "auto-detected",
"timestamp": "2024-01-15T10:30:00Z"
},
"documents": [
{
"documentName": "output.pdf",
"sections": [
{
"sectionTitle": "Section 1",
"content": "...",
"type": "text|table|list|image"
}
]
}
]
}
</code>
</div>
<div class="success-box" style="margin-top: 20px;">
<strong>✓ Vollständige Pipeline:</strong> Input (jedes Format) → <span style="color: #ff9800;">Neutralizer</span> (Datenschutz) → Extraction → <span style="color: #e74c3c;">Normalizer</span> (JSON) → AI Processing → Renderer → Output (jedes Format)
</div>
</div>
<h2>7. Integration mit anderen Services</h2>
<div class="diagram">
<h3>🔗 Service-Dependencies</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div class="component-box">
<h4>📤 Generation Service</h4>
<code>@serviceGeneration/</code>
<p style="margin-top: 10px;"><strong>Verwendung:</strong></p>
<ul style="font-size: 0.9em;">
<li>Prompt-Building für Generierung</li>
<li>Rendering von JSON → Final Format</li>
<li>Multi-File Generation</li>
<li>Format-spezifische Renderer</li>
</ul>
</div>
<div class="component-box">
<h4>🔍 Extraction Service</h4>
<code>@serviceExtraction/</code>
<p style="margin-top: 10px;"><strong>Verwendung:</strong></p>
<ul style="font-size: 0.9em;">
<li>extractContent() - Dokument-Extraktion</li>
<li>Chunking-Strategien</li>
<li>Merging-Strategien</li>
<li>Bild-Analyse (Vision-Models)</li>
</ul>
</div>
</div>
<div class="flow-arrow">⬇️</div>
<div class="component-box" style="background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%);">
<h4>🔄 Normalization Service</h4>
<code>@serviceNormalization/</code>
<p style="margin-top: 10px; color: #e74c3c;"><strong>Zentral für formatunabhängige Verarbeitung!</strong></p>
<ul style="font-size: 0.9em;">
<li>discoverStructures() - Erkennt Tabellen, Listen, Strukturen</li>
<li>requestHeaderMapping() - AI-gestützte Spalten-Mapping</li>
<li>applyMapping() - Konvertiert in kanonisches JSON</li>
<li>validateCanonical() - Validiert JSON-Struktur</li>
</ul>
<p style="margin-top: 15px; color: #ff9800;"><strong>⚠️ Hinweis:</strong> Zu unterscheiden vom Neutralizer (Datenschutz) - dieser konvertiert Formate in JSON</p>
</div>
<div style="margin-top: 20px; padding: 15px; background: #f8f9fa; border: 2px solid #ff9800; border-radius: 10px;">
<h4 style="color: #ff9800; margin-bottom: 10px;">🔍 Klärung: Neutralizer vs. Normalizer</h4>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
<div style="background: white; padding: 10px; border-radius: 5px;">
<strong style="color: #e74c3c;">Neutralizer</strong>
<ul style="font-size: 0.85em; margin-top: 5px;">
<li>Für User-Prompt-Dokumente</li>
<li>Datenschutz durch Platzhalter</li>
<li>Ersetzt sensible Daten</li>
<li>z.B. Name → {{person}}</li>
</ul>
</div>
<div style="background: white; padding: 10px; border-radius: 5px;">
<strong style="color: #c0392b;">Normalizer</strong>
<ul style="font-size: 0.85em; margin-top: 5px;">
<li>Für alle Dokument-Formate</li>
<li>Konvertiert in JSON-Struktur</li>
<li>Formatunabhängige Verarbeitung</li>
<li>z.B. PDF → JSON</li>
</ul>
</div>
</div>
</div>
<div class="flow-arrow">⬇️</div>
<div class="component-box">
<h4>🗄️ Storage & Logging</h4>
<p style="margin-top: 10px;"><strong>Components:</strong></p>
<ul style="font-size: 0.95em;">
<li><strong>Debug Files:</strong> <code>local/logs/debug/[timestamp]_[type].txt</code></li>
<li><strong>Workflow Stats:</strong> <code>services.workflow.storeWorkflowStat()</code></li>
<li><strong>Progress Logging:</strong> <code>services.workflow.progressLogStart()</code></li>
</ul>
</div>
</div>
<div class="legend">
<h3>📊 Legende</h3>
<div class="legend-item">
<div class="legend-color" style="background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%);"></div>
<span><strong>Service Box:</strong> Hauptkomponenten des AI-Service</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: white; border: 2px solid #e74c3c;"></div>
<span><strong>Component Box:</strong> Sub-Komponenten (Core, Processing, Generation)</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #fff3e0; border: 2px solid #ff9800;"></div>
<span><strong>Loop Step:</strong> Iteration im Looping-System</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #d4edda; border: 2px solid #28a745;"></div>
<span><strong>Success Box:</strong> Erfolgreich abgeschlossener Call</span>
</div>
</div>
<div class="warning-box" style="margin-top: 30px;">
<strong>⚠️ Wichtige Hinweise:</strong>
<ul>
<li><strong>Lazy Initialization:</strong> Sub-Module werden erst bei Bedarf initialisiert</li>
<li><strong>Model Registry:</strong> Auto-Discovery von AI-Connectors zur Laufzeit</li>
<li><strong>Looping System:</strong> Nur aktiv wenn <code>LOOP_INSTRUCTION</code> im Prompt ist</li>
<li><strong>Debug Logging:</strong> Alle Prompts und Responses werden in Debug-Files gespeichert</li>
<li><strong>Price Tracking:</strong> Kosten werden pro Call berechnet und gespeichert</li>
</ul>
</div>
</div>
</body>
</html>