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,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.*