docs: Comprehensive lessons learned from Competitor Analysis migration

This commit is contained in:
2026-01-10 17:47:58 +01:00
parent 249b06463b
commit ef43a8174b
3 changed files with 93 additions and 59 deletions

View File

@@ -1,14 +1,46 @@
# Migration Guide: Google AI Builder Apps -> Local Docker Stack
> **WICHTIGER HINWEIS:** Der Gemini-Agent f"."hrt Code **innerhalb** dieses Docker-Containers aus. Er hat keinen Zugriff auf den Docker-Daemon des Host-Systems. Daher kann und wird der Agent **NIEMALS** in der Lage sein, Befehle wie `docker build`, `docker-compose up` oder andere Docker-Management-Aufgaben auszuf.hren. Diese Befehle m.ssen immer vom Benutzer auf dem Host-System ausgef.hrt werden.
> **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(...)`.
> 2. **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.
> 3. **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.
> 4. **FRONTEND BUILD:** `vite`, `typescript` etc. gehören in `dependencies`, NICHT `devDependencies`, da sie sonst im Docker-Multi-Stage-Build fehlen.
**Ziel:** Standardisierter Prozess, um eine von Google AI Studio generierte React-App schnell, robust und fehlerfrei in die lokale Docker/Python-Architektur zu integrieren.
**Grundsatz:** "Minimalset & Robustheit". Wir bauen keine aufgebl.hten Container, und wir verhindern Timeouts und fehlende Abh.ngigkeiten proaktiv.
---
## 1. Vorbereitung & Abh.ngigkeiten (Common Pitfalls)
## 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.
@@ -72,33 +104,37 @@ requests
beautifulsoup4
```
### 1.5 Python Syntax & F-Strings
Multi-Line Prompts k.nnen in Docker-Umgebungen zu **sehr hartn.ckigen Syntaxfehlern** f.hren, selbst wenn sie lokal korrekt aussehen.
### 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 (insbesondere bei `f-strings` in Kombination mit Zahlen/Punkten am Zeilenanfang oder verschachtelten Klammern) kann Multi-Line-Strings (`f"""..."""`) falsch interpretieren, was zu Fehlern wie `SyntaxError: invalid decimal literal` oder `unmatched ')'` f.hrt, auch wenn der Code scheinbar korrekt ist.
* **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 (Maximale Robustheit):**
1. **Vermeide `f"""` komplett f.r komplexe Multi-Line-Prompts.** Definiere stattdessen den Prompt als **Liste von einzelnen String-Zeilen** und f.ge sie mit `"\n".join(prompt_parts)` zusammen.
2. **Nutze die `.format()` Methode oder f-Strings in EINZEILIGEN Strings** zur Variablen-Injektion. Dies trennt die String-Definition komplett von der Variablen-Interpolation und ist die robusteste Methode.
* **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
# Beispiel: Maximal robust
prompt_template_parts = [
"1) Mache dies: {variable_1}",
"2) Mache das: {variable_2}",
]
prompt_template = "\n".join(prompt_template_parts)
prompt = prompt_template.format(variable_1=wert1, variable_2=wert2)
# System-Instruktion muss immer noch vorangestellt werden:
full_prompt = sys_instr + "\n\n" + prompt
prompt = f"""
Analysiere "{request.name}". Antworte im JSON-Format: {{"key": "value"}}
"""
```
* **Versionierung f.r Debugging:** Um sicherzustellen, dass die korrekte Version des Codes l.uft, f.ge Versionsnummern in die Start-Logs des Node.js Servers (`server.cjs`) und des Python Orchestrators (`gtm_architect_orchestrator.py`) ein.
* `server.cjs`: `console.log(`... (Version: ${VERSION})`);`
* `gtm_architect_orchestrator.py`: `print(f"DEBUG: Orchestrator v{__version__} loaded ...")`
**RICHTIG (Robust & Sicher):**
```python
prompt = r"""
Analysiere "{name}". Antworte im JSON-Format: {{"key": "value"}}
""".format(name=request.name)
```
* **Signaturen pr.fen:** Shared Libraries (`helpers.py`) haben oft .ltere Signaturen. Immer die tats.chliche Definition pr.fen!
* Beispiel: `call_openai_chat` unterst.tzt oft kein `system_message` Argument. Stattdessen Prompt manuell zusammenbauen (`sys_instr + "\n\n" + prompt`).
### 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.
---

View File

@@ -4,6 +4,7 @@
- **Projektdokumentation:** Die primäre und umfassendste Dokumentation für dieses Projekt befindet sich in der Datei `readme.md`. Bitte ziehen Sie diese Datei für ein detailliertes Verständnis der Architektur und der einzelnen Module zu Rate.
- **Git-Repository:** Dieses Projekt wird über ein Git-Repository verwaltet. Alle Änderungen am Code werden versioniert. Beachten Sie den Abschnitt "Git Workflow & Conventions" für unsere Arbeitsregeln.
- **WICHTIG:** Der AI-Agent kann Änderungen committen, aber aus Sicherheitsgründen oft nicht `git push` ausführen. Bitte führen Sie `git push` manuell aus, wenn der Agent dies meldet.
## Project Overview

View File

@@ -1,47 +1,44 @@
# Migration Report: Competitor Analysis Agent
## Status: Jan 09, 2026
## Status: Jan 10, 2026 - ✅ FINAL SUCCESS
The `competitor-analysis` application has been successfully migrated to the local Docker stack and integrated into the `gemini-gateway` (Nginx).
Die Migration ist abgeschlossen. Die App ist unter `/ca/` voll funktionsfähig.
### 1. Vorgehen (Process)
### 🚨 Die Odyssee: Chronologie der Fehler & Lösungen
1. **Dateistruktur:**
* Erstellung des Verzeichnisses `competitor-analysis-app/`.
* Kopie aller Dateien aus dem Original-Verzeichnis.
2. **Frontend-Anpassung:**
* `vite.config.ts`: `base: './'` gesetzt, um korrektes Routing unter dem Sub-Pfad `/ca/` zu ermöglichen.
* `geminiService.ts`: Direkte Aufrufe an `@google/genai` entfernt. Alle Funktionen nutzen nun `fetch()` an den neuen Python-Backend-Endpunkt `/api/...`.
3. **Backend-Orchestrator (Python/FastAPI):**
* Erstellung von `competitor_analysis_orchestrator.py`.
* Portierung aller Prompts und Schemata aus dem TypeScript-Code in Python (Pydantic & Google Generative AI SDK).
* Implementierung einer robusten JSON-Parsing-Logik (`parse_json_response`), die Markdown-Blöcke entfernt und inkonsistente LLM-Antworten korrigiert.
* Implementierung einer Modell-Kandidaten-Liste (`gemini-1.5-pro` mit Fallback), um regionale Verfügbarkeit sicherzustellen.
* Integration von `StaticFiles`, um das fertig gebaute Frontend direkt über den Python-Server auszuliefern.
4. **Docker-Integration:**
* `Dockerfile`: Multi-Stage Build (Node.js zum Bauen, Python zum Ausführen).
* `docker-compose.yml`: Neuer Service `competitor-analysis` hinzugefügt, inklusive Volume-Mounts für API-Keys und Live-Debugging des Orchestrators.
* `nginx-proxy.conf`: Routing für `/ca/` konfiguriert.
Wir haben 4 Stunden für eine Aufgabe benötigt, die 10 Minuten dauern sollte. Hier ist das Protokoll des Scheiterns, damit es nie wieder passiert:
### 2. Next Steps
#### 1. Der Python-Syntax-Albtraum (Stunde 1)
* **Fehler:** `SyntaxError: unterminated string literal`.
* **Ursache:** Verwendung von `f"""..."""` für Gemini-Prompts. Das Apostroph in "competitor's" oder geschweifte Klammern im JSON-Teil sprengten den String.
* **Lösung:** Umstellung auf **Raw Strings** `r"""..."""` und die **`.format()`** Methode.
* **Persistenz:** Aktuell werden Analysen nur im App-State (RAM) gehalten. Eine Anbindung an die SQLite-Datenbank (ähnlich wie beim `b2b-app`) wäre sinnvoll, um Analysen zu speichern und später wieder aufzurufen.
* **Fehlermanagement:** Verfeinerung der Error-Handler im Frontend, um spezifische Backend-Fehler (z.B. API-Limits) besser anzuzeigen.
* **Weitere Schritte im Orchestrator:** Implementierung der verbleibenden Steps (4-8), falls diese noch nicht vollständig in Python abgebildet sind (derzeit sind Step 1, 2, 3, 4, 5, 6, 7 und 8 bereits im Code vorbereitet oder implementiert).
#### 2. Das SDK-Versions-Dilemma (Stunde 2)
* **Fehler:** `ImportError: cannot import name 'Schema'`.
* **Ursache:** Versuch, moderne SDK-Features mit `google-generativeai==0.3.0` zu nutzen. Diese Version kennt keine Klassen für Schemata.
* **Lösung:** Upgrade auf das moderne **`google-genai`** Paket (v1.x) und Umstellung des gesamten Orchestrators auf den neuen Client.
### 3. Lessons Learned
#### 3. Die 404-Falle (Stunde 2.5)
* **Fehler:** Website nicht erreichbar, obwohl der Python-Server lief.
* **Ursache A (Build):** Build-Tools (`vite`) waren in `devDependencies` und fehlten im Docker-Container. -> **Fix:** Verschieben in `dependencies`.
* **Ursache B (Compose):** Ein Volume-Mount `- .:/app` hat den im Image gebauten `dist`-Ordner mit dem leeren lokalen Ordner überschrieben. -> **Fix:** Nur die Orchestrator-Datei mounten.
* **Python SDK-Versionskonflikte (`google-generativeai==0.3.0`):** Das im Projekt verwendete Python SDK (`google-generativeai` Version `0.3.0`) ist nicht mit neueren API-Schnittstellen kompatibel.
* `ImportError: cannot import name 'Schema' from 'google.generativeai.types'` und `ImportError: cannot import name 'Content' from 'google.generativeai.types'` treten auf, da diese Klassen in dieser SDK-Version an diesen Importpfaden nicht existieren oder anders implementiert sind.
* **Lösung:** Schemata müssen direkt als Python-Dictionaries an die `generation_config` übergeben werden. Alle Importe für `Schema` und `Content` müssen entfernt werden.
* **Frontend Build (`package.json` `devDependencies`):** Build-Tools wie `vite`, `@vitejs/plugin-react` und `typescript` müssen in den `dependencies` der `package.json` stehen, nicht in `devDependencies`. Andernfalls schlägt `npm install` im Docker-Build fehl, was zu einem leeren oder fehlenden `dist`-Ordner und einem 404-Fehler des Python-Servers führt.
* **Syntaxfehler in mehrzeiligen Prompts (`f-strings`):** Besonders bei älteren Python-Versionen und komplexen mehrzeiligen Prompts mit `f-strings` können subtile Fehler (z.B. falsch platzierte Anführungszeichen oder unbeabsichtigter deutscher Text in englischen Prompts) zu `SyntaxError: unterminated string literal` führen.
* **Lösung:** Die robusteste Methode ist, mehrzeilige Prompts als Liste von Strings zu definieren und mit `"\n".join()` zusammenzufügen.
#### 4. Der "Modell nicht gefunden" Fehler (Stunde 3)
* **Fehler:** `404 models/gemini-1.5-pro is not found for API version v1beta`.
* **Ursache:** Das alte SDK nutzte veraltete Endpunkte, die die neuen 1.5/2.0 Modelle nicht sauber auflösen konnten.
* **Lösung:** Vollständige Migration auf den neuen **`genai.Client`**. Dieser nutzt die stabilen API-Pfade.
* **SDK-Unterschiede:** Das Python SDK (`google-generativeai`) verhält sich bei der Schema-Validierung strikter als die JS-Variante. Prompts mussten leicht angepasst werden, um sicherzustellen, dass die AI wirklich valides JSON liefert.
* **Vite Base Path:** Ohne `base: './'` in `vite.config.ts` schlagen alle Asset-Requests fehl, wenn die App hinter einem Proxy unter `/ca/` läuft.
* **Double JSON Trap:** LLMs neigen dazu, JSON in Markdown zu packen. Der Backend-Orchestrator muss dies proaktiv bereinigen, bevor `json.loads()` aufgerufen wird.
* **Proxy-Routing:** Der Trailing Slash in Nginx (`proxy_pass http://.../`) ist kritisch, damit die Pfade innerhalb der App korrekt aufgelöst werden.
#### 5. Der finale "map of undefined" Fehler (Stunde 4)
* **Fehler:** Frontend lädt, crasht aber bei der Datenanzeige.
* **Ursache:** Backend lieferte `target_industries` (Snake Case), Frontend erwartete das Schema aber strikt so, wie es die KI ohne Schema-Zwang lieferte.
* **Lösung:** Aktivierung von **strikten JSON-Schemata** im `google-genai` Client. Die KI wird nun gezwungen, exakt die vom Frontend erwarteten Keys zu liefern.
### 3. Lessons Learned (Zusammenfassung)
1. **F-STRINGS SIND GIFT** für Prompts.
2. **GOOGLE-GENAI (v1.x)** ist der neue Standard. Das alte Paket nicht mehr verwenden.
3. **VOLUMES** im Docker-Compose dürfen niemals Build-Artefakte (`dist`) überschreiben.
4. **SCHEMA ENFORCEMENT** ist Pflicht, um Frontend-Crashes zu vermeiden.
---
*Dokumentation erstellt am 09.01.2026*
*Dokumentation finalisiert am 10.01.2026 nach erfolgreicher Migration.*