From ef43a8174b9cb0e41c6b73ef9173a1ab6ea3f06f Mon Sep 17 00:00:00 2001 From: Floke Date: Sat, 10 Jan 2026 17:47:58 +0100 Subject: [PATCH] docs: Comprehensive lessons learned from Competitor Analysis migration --- BUILDER_APPS_MIGRATION.md | 84 ++++++++++++++++++------- GEMINI.md | 1 + MIGRATION_REPORT_COMPETITOR_ANALYSIS.md | 67 ++++++++++---------- 3 files changed, 93 insertions(+), 59 deletions(-) diff --git a/BUILDER_APPS_MIGRATION.md b/BUILDER_APPS_MIGRATION.md index e210867d..9d739e5c 100644 --- a/BUILDER_APPS_MIGRATION.md +++ b/BUILDER_APPS_MIGRATION.md @@ -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. --- diff --git a/GEMINI.md b/GEMINI.md index 67cedfc3..0b6075a8 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -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 diff --git a/MIGRATION_REPORT_COMPETITOR_ANALYSIS.md b/MIGRATION_REPORT_COMPETITOR_ANALYSIS.md index cbf8b5f9..66f1a89d 100644 --- a/MIGRATION_REPORT_COMPETITOR_ANALYSIS.md +++ b/MIGRATION_REPORT_COMPETITOR_ANALYSIS.md @@ -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.*