Files
Brancheneinstufung2/BUILDER_APPS_MIGRATION.md

11 KiB

Migration Guide: Google AI Builder Apps -> Local Docker Stack

CRITICAL WARNINGS & BEST PRACTICES (READ BEFORE MIGRATION):

  1. PYTHON PROMPTS (F-STRINGS STRENG VERBOTEN): Nutze NIEMALS f"""...""" für komplexe Prompts mit JSON/Markdown. Das führt zu unlösbaren SyntaxError: unterminated string literal Schleifen. Nutze AUSSCHLIESSLICH `r"""...

""".format(...)`.

  1. SDK WAHL (MODERN FIRST): Das alte google-generativeai Paket ist "Legacy". Nutze für alle neuen Projekte das moderne google-genai Paket. Es löst alle Probleme mit API-Versionen (v1beta) und unterstützt JSON-Modus/Schemata nativ.
  1. DOCKER VOLUMES (404-FALLE): Mounte NIEMALS das gesamte App-Verzeichnis (.:/app), wenn darin ein dist-Ordner (Build-Artefakt) im Image liegt. Du löschst damit die gebaute Web-App im Container. Mounte nur die spezifische Orchestrator-Datei.
  1. FRONTEND BUILD: vite, typescript etc. gehören in dependencies, NICHT devDependencies, da sie sonst im Docker-Multi-Stage-Build fehlen.

0. Der "Quick-Start" Checkliste (5-Minuten-Plan)

  1. SDK: Steht google-genai in der requirements.txt? (Wenn nein -> hinzufügen).

  2. Prompts: Sind alle Prompts als .format()-Strings angelegt? (Wenn nein -> umstellen).

  3. Package.json: Sind vite, typescript, react-router in dependencies? (Wenn nein -> verschieben).

  4. Docker-Compose: Wird nur die .py-Datei gemountet? (Wenn nein -> korrigieren).

  5. Vite Config: Ist base: './' gesetzt? (Muss immer).


1. Vorbereitung & Abhängigkeiten (Common Pitfalls)

Bevor Code kopiert wird, m.ssen die Grundlagen stimmen.

1.1 Package.json Check (Frontend Build-Falle)

Generierte Apps haben oft kein express, da sie keinen Server erwarten. Noch wichtiger ist, dass kritische Build-Tools oft fälschlicherweise in devDependencies deklariert werden.

  • Aktion: Öffne package.json der App.
  • Prüfung 1 (Backend): Steht express unter dependencies?
  • Fix 1:
    "dependencies": {
      ...
      "express": "^4.18.2",
      "cors": "^2.8.5"
    }
    
  • Prüfung 2 (Frontend Build): Stehen Build-Tools wie vite, @vitejs/plugin-react oder typescript unter devDependencies?
  • Fix 2 (KRITISCH): Verschiebe alle devDependencies in die dependencies. Der npm install-Befehl im Dockerfile installiert devDependencies standardmäßig nicht, was zu einem fehlgeschlagenen npm run build führt.

1.2 Datenbank-Datei

Docker kann keine einzelne Datei mounten, wenn sie auf dem Host nicht existiert.

  • Fehler: "Bind mount failed: ... does not exist"
  • Fix: VOR dem ersten Start die Datei anlegen:
    touch mein_neues_projekt.db
    

1.3 Vite Base Path (White Screen Fix)

Wenn die App unter einem Unterverzeichnis (z.B. /gtm/) l.uft, findet sie ihre JS/CSS-Dateien nicht, wenn Vite Standard-Pfade (/) nutzt.

  • Datei: vite.config.ts
  • Fix: base auf ./ setzen.
    export default defineConfig({
      base: './', // WICHTIG f.r Sub-Pfad Deployment
      // ...
    });
    

1.4 Python Dependencies & Shared Libraries (Critical Pitfall)

Das Projekt nutzt ein zentrales helpers.py, das von mehreren Services geteilt wird. Dies f.hrt oft zu ModuleNotFoundError, da eine kleine App (wie gtm-architect) nicht alle Bibliotheken ben.tigt, die in helpers.py importiert werden (z.B. gspread, pandas).

  • Fehler: ModuleNotFoundError: No module named 'gspread'

  • Ursache: Die gtm-architect/requirements.txt enth.lt gspread nicht, aber helpers.py versucht es zu importieren.

  • Fix (in helpers.py): Machen Sie "exotische" Importe optional. Dies ist die robusteste Methode, um die Kompatibilit.t zu wahren, ohne die requirements.txt kleiner Apps aufzubl.hen.

    # Beispiel in helpers.py
    try:
        import gspread
        GSPREAD_AVAILABLE = True
    except ImportError:
        GSPREAD_AVAILABLE = False
        gspread = None # Wichtig, damit Referenzen nicht fehlschlagen
    
  • Fix (in requirements.txt): Stellen Sie sicher, dass die f.r die App unmittelbar ben.tigten Bibliotheken vorhanden sind. F.r gtm-architect sind das:

google-generativeai google-genai Pillow requests beautifulsoup4


### 1.5 Python Syntax & F-Strings (Der Prompt-Albtraum)
Multi-Line Prompts in Kombination mit `f-strings`, JSON und Markdown führen in Docker-Umgebungen zu **extrem hartnäckigen Syntaxfehlern** (`SyntaxError: unterminated string literal`), die oft nicht reproduzierbar wirken.

*   **Das Problem:** Der Python-Parser stolpert über verschachtelte Anführungszeichen (`"`, `'`), geschweifte Klammern `{}` (die in JSON und f-strings vorkommen) und Backslashes. Ein einziges falsch interpretiertes Zeichen sprengt den gesamten String.

*   **ULTIMATIVE LÖSUNG (Die einzig wahre Methode):**
    Vergessen Sie `f-strings` für komplexe Prompts! Nutzen Sie **Raw Strings (`r"""..."""`)** kombiniert mit der **`.format()` Methode**.
    
    1.  **Raw Strings (`r"..."`):** Verhindern, dass Backslashes als Escape-Sequenzen interpretiert werden.
    2.  **`.format()`:** Trennt den Text sauber von den Variablen.

    **FALSCH (Explosionsgefahr):**
    ```python
    prompt = f"""
    Analysiere "{request.name}". Antworte im JSON-Format: {{"key": "value"}}
    """
    ```

    **RICHTIG (Robust & Sicher):**
    ```python
    prompt = r"""
    Analysiere "{name}". Antworte im JSON-Format: {{"key": "value"}}
    """.format(name=request.name)
    ```

### 1.6 Volume Mounts & Datei-Synchronisierung (Phantom-Fehler)
Wenn Sie Code ändern, der Fehler aber bestehen bleibt ("Geisterfehler"), synchronisiert Docker die Datei nicht korrekt.

*   **Symptom:** `SyntaxError` an Zeilen, die Sie gerade korrigiert haben.
*   **Ursache:** Einzeldatei-Mounts (`- ./file.py:/app/file.py`) sind oft unzuverlässig, besonders wenn die Inode der Datei durch Editoren geändert wird.
*   **Lösung:** Mounten Sie das **gesamte Verzeichnis** (`- ./my-app:/app`) oder bauen Sie das Image neu (`COPY . .` im Dockerfile) und entfernen Sie den Volume-Mount temporär zur Diagnose.

---

## 2. Die Backend-Bridge (`server.cjs`)

Dies ist der Node.js Server im Container. Er muss **robust** gegen Timeouts sein und Pfade dynamisch erkennen (Dev vs. Prod).

---

## 3. Docker Optimierung (Multi-Stage)

Wir nutzen **Multi-Stage Builds**, um das Image klein zu halten (kein `src`, keine Dev-Tools im Final Image).

---

## 4. Docker Compose & Mounts (WICHTIGER PITFALL)

**WARNUNG: Lokale Dateien .berschreiben den Container-Code!**

---

## 5. Nginx Proxy

Achtung beim Routing. Wenn die App unter `/app/` laufen soll, muss der Trailing Slash (`/`) stimmen.

---

## 6. Frontend Anpassungen (React)

1.  **API Calls:** Alle direkten Aufrufe an `GoogleGenAI` entfernen. Stattdessen `fetch('/api/run', ...)` nutzen.
2.  **Base URL:** In `vite.config.ts` `base: './'` setzen (siehe Punkt 1.3).

---


## Appendix A: GTM Architect Fixes & Gemini Migration

### A.1 - A.4 (Siehe .ltere Versionen f.r Prompt-Fixes & GenerativeModel API)

### A.5 Image Generation 2.0 (Hybrid Approach - Jan 04)

Um die Einschr.nkungen der "Text-only" Modelle und die regionale Verf.gbarkeit von Imagen 3 zu umgehen, nutzen wir einen hybriden Ansatz.

**1. Anforderungen**
*   **Bibliothek:** `google-genai` (v1.x) MUSS installiert sein (`pip install google-genai`). `google-generativeai` (v0.x) ist veraltet.
*   **Bildverarbeitung:** `Pillow` muss installiert sein (`pip install Pillow`).

**2. Die Logik (Text vs. Bild)**
Das System entscheidet automatisch, welches Modell genutzt wird:

*   **Szenario A: Generisches Bild (Text-to-Image)**
    *   **Modell:** `imagen-4.0-generate-001`.
*   **Szenario B: Produkt-Integration (Image-to-Image)**
    *   **Modell:** `gemini-2.5-flash-image`.

### A.6 Gemini SDK-Chaos & Modell-Verfügbarkeit (Kritische Erkenntnis)

Ein wiederkehrendes Problem bei der Migration ist der Konflikt zwischen SDK-Versionen und regionalen Modell-Beschränkungen, sowie die schnelle Evolution der API-Schnittstellen.

**1. Das SDK-Dilemma**
Es existieren zwei parallele Google SDKs, und selbst innerhalb von `google-generativeai` ändern sich die Modulstrukturen schnell:
1.  **`google-generativeai` (Legacy):** Versionen wie `0.3.0` verhalten sich anders als neuere. Oft instabil bei neuen Modellen, wirft Deprecation-Warnungen. Import: `import google.generativeai`.
2.  **`google-genai` (Modern):** Erforderlich für Imagen 4 und Gemini 2.x Features. Import: `from google import genai`.

**KRITISCHES PROBLEM: `ImportError` für `Schema` und `Content` mit `google-generativeai==0.3.0`**
*   **Fehler:** `ImportError: cannot import name 'Schema' from 'google.generativeai.types'` oder `ImportError: cannot import name 'Content' from 'google.generativeai.types'`.
*   **Ursache:** In älteren Versionen des `google-generativeai`-SDK (z.B. `0.3.0`, wie in diesem Projekt verwendet) existierten diese Klassen (`Schema`, `Content`) nicht an den gleichen Importpfaden wie in neueren Versionen oder wurden gar nicht als separate Klassen verwendet.
*   **LÖSUNG (für `google-generativeai==0.3.0`):**
    *   Entferne **alle** Importe für `Schema` und `Content` (z.B. `from google.generativeai.types import HarmCategory, HarmBlockThreshold`).
    *   Ersetze **alle** Instanziierungen von `Schema(...)` durch einfache Python-Dictionaries, die direkt das JSON-Schema repräsentieren. Die `generation_config` akzeptiert in dieser Version direkt das Dictionary.

**2. Der "404 Not Found" Modell-Fehler**
Oft liefert die API einen 404 Fehler f.r ein Modell (z.B. `gemini-1.5-flash`), obwohl es laut Dokumentation existiert.
*   **Ursache:** Regionale Beschr.nkungen (EU vs US) oder Account-Berechtigungen.
*   **Erkenntnis:** Wenn 1.5 Flash nicht geht, funktioniert oft **`gemini-2.0-flash`** problemlos.
*   **Best Practice:** Implementiere eine **Kandidaten-Liste** (Fallback-Loop) f.r Modelle.

**3. SDK Syntax-Fallen**
Das neue SDK (`google-genai`) hat ge.nderte Methodennamen:
*   Statt `generate_image` (Singular) wird oft **`generate_images`** (Plural) erwartet.
*   Modelle f.r Bildgenerierung (Imagen) reagieren allergisch auf `response_mime_type="application/json"`. Dieses Feld MUSS bei Imagen-Modellen weggelassen werden.

**Gold-Standard f.r Modell-Wahl (Python):**
```python
candidates = ['imagen-4.0-generate-001', 'imagen-3.0-generate-001']
for model in candidates:
    try:
        # Versuch des API-Calls
        break
    except ClientError as e:
        if "404" in str(e): continue
        raise e

7. Troubleshooting & Lessons Learned (Jan 2026)

7.5 Double JSON Encoding (Database Trap)

  • Problem: Wenn json.dumps() sowohl im Backend beim Speichern als auch in der DB-Klasse aufgerufen wird, landet "Stringified JSON" in der DB. Beim Laden im Frontend crasht React, da es einen String statt eines Objekts erh.lt.
  • Fix Backend: Speichere rohe Dictionaries in der DB-Klasse.
  • Fix Frontend: Nutze eine robuste Parse-Funktion, die JSON.parse() mehrfach versucht:
    const parseData = (d) => (typeof d === 'string' ? JSON.parse(d) : d);