140 lines
11 KiB
Markdown
140 lines
11 KiB
Markdown
# Migration Report: Competitor Analysis Agent
|
|
|
|
## Status: Jan 11, 2026 - ✅ ROBUSTNESS UPGRADE COMPLETE
|
|
|
|
Die App ist unter `/ca/` voll funktionsfähig und verfügt nun über eine "Grounded Truth" Engine (Scraping + SerpAPI) sowie eine skalierbare **Map-Reduce Architektur**.
|
|
|
|
### 🚨 Vollständige Chronik der Fehler & Lösungen
|
|
|
|
1. **Problem: 404 auf `/ca/`**
|
|
* **Ursache:** Der Container startete aufgrund von Syntaxfehlern nicht, was Nginx mit einem 404 (später 502) quittierte.
|
|
|
|
2. **Problem: `SyntaxError: unterminated string literal` (Runde 1)**
|
|
* **Ursache:** Verwendung von `f"""..."""` für komplexe Prompts.
|
|
* **Lösung:** Umstellung auf `.format()`. **Wichtig:** Docker-Volumes synchronisierten nicht zuverlässig, was zu "Phantom-Fehlern" führte. Ein `build --no-cache` war nötig.
|
|
|
|
3. **Problem: `ImportError: cannot import name 'Schema'`**
|
|
* **Ursache:** Uralte SDK-Version `google-generativeai==0.3.0` in `requirements.txt`.
|
|
* **Lösung:** Umstellung auf Dictionaries, später komplettes SDK-Upgrade.
|
|
|
|
4. **Problem: `404 models/gemini-1.5-pro ... for API version v1beta`**
|
|
* **Ursache:** Das alte SDK nutzte veraltete Endpunkte.
|
|
* **Lösung:** Migration auf das moderne **`google-genai`** Paket (v1.x) und Nutzung des neuen `genai.Client`.
|
|
|
|
5. **Problem: `TypeError: unexpected keyword argument 'client_options'`**
|
|
* **Analyse:** Obwohl das SDK in `requirements.txt` aktualisiert wurde, installierte Docker auf der Diskstation hartnäckig eine alte Version.
|
|
* **Lösung:** Erzwingen der Version `google-genai>=1.2.0`.
|
|
|
|
6. **Problem: Das "Grounding Upgrade" & Die Syntax-Hölle (Runde 2)**
|
|
* **Aufgabe:** Einbau von echtem Web-Scraping und SerpAPI zur Qualitätssteigerung.
|
|
* **Fehler:** `SyntaxError: f-string: expecting '}'` in komplexen Listen-Generatoren (z.B. `c_sum`).
|
|
* **Ursache:** Python 3.11 erlaubt keine geschachtelten Anführungszeichen in F-Strings, wenn diese Backslashes oder komplexe Ausdrücke enthalten.
|
|
* **Lösung:** **RADIKALER VERZICHT auf F-Strings** in allen kritischen Logik-Bereichen. Umstellung auf einfache Schleifen und `.format()`.
|
|
|
|
7. **Problem: `unterminated string literal (detected at line 203)`**
|
|
* **Ursache:** Einfache Anführungszeichen `'` in Kombination mit `\n` wurden im Container-Kontext falsch interpretiert.
|
|
* **Lösung:** **ULTIMATIVE SYNTAX:** Verwendung von **Triple Raw Quotes (`r"""..."""`)** für jeden einzelnen String, der Variablen oder Sonderzeichen enthält.
|
|
|
|
8. **Problem: Analyse stoppt nach 5 Konkurrenten (Token Limit / Lazy LLM)**
|
|
* **Symptom:** Bei 9 Konkurrenten wurden nur die ersten 5 analysiert, der Rest fehlte.
|
|
* **Ursache:** Der riesige Prompt ("Analysiere alle 9...") überforderte das Kontext-Fenster oder führte zu Timeouts.
|
|
* **Lösung:** Umstellung auf **Map-Reduce**: Jeder Konkurrent wird in einem eigenen parallelen Task (`asyncio.gather`) analysiert. Erhöhung von `max_output_tokens` auf 8192.
|
|
|
|
9. **Problem: `NameResolutionError` im Container**
|
|
* **Symptom:** Scraping schlug fehl ("Name or service not known").
|
|
* **Ursache:** Docker-Container nutzten den (instabilen) Host-DNS.
|
|
* **Lösung:** Explizites Setzen von Google DNS (`8.8.8.8`, `8.8.4.4`) in `docker-compose.yml`.
|
|
|
|
10. **Problem: `422 Unprocessable Entity` in Schritt 6 & 8**
|
|
* **Ursache:** Diskrepanz zwischen Frontend-Request (z.B. sendet `industries`) und Backend-Pydantic-Modell (erwartet `target_industries`).
|
|
* **Lösung:** Backend-Modelle exakt an die Frontend-Payloads angepasst.
|
|
|
|
11. **Problem: Leere Matrizen in der Conclusion**
|
|
* **Ursache:** Das LLM füllte das `availability`-Array nicht korrekt oder erfand eigene Produktnamen als Zeilenbeschriftung.
|
|
* **Lösung:** Extrem strikter Prompt ("KEINE Produktnamen", "GENAU einen Eintrag pro Kategorie") und detailliertes JSON-Schema.
|
|
|
|
12. **Problem: Blinde KI in Schritt 8 (Referenzen)**
|
|
* **Symptom:** Die Referenzanalyse lieferte nur generische, oft erfundene Branchen, anstatt echter Kunden.
|
|
* **Ursache:** Der Prompt bat die KI, "nach Referenzen zu suchen", ohne ihr eine Datengrundlage zu geben. Die KI hat halluziniert.
|
|
* **Lösung:** Implementierung einer **"Grounded" Referenz-Suche**.
|
|
* **Ergebnis:** Die Analyse basiert nun auf Fakten von der Webseite des Wettbewerbers.
|
|
|
|
13. **Problem: Informations-Overload (Text-Wüste)**
|
|
* **Symptom:** In Notion landeten hunderte Produkte und Landmines, aber man konnte nicht effektiv filtern (z.B. "Zeige alle Reinigungsroboter").
|
|
* **Lösung:** Einführung von **Semantic Clustering & Taxonomies**.
|
|
* Das Backend ordnet nun jedem Produkt eine feste Kategorie zu (z.B. *Cleaning*, *Logistics*).
|
|
* Jede Landmine erhält ein Themen-Tag (z.B. *Price*, *Support*, *Technology*).
|
|
* **Ergebnis:** Das Competitive Radar ist nun ein echtes BI-Tool. In Notion können nun "Board Views" nach Kategorien erstellt werden (Level 4 Relational Model).
|
|
|
|
### 🛡️ Die finale "Grounded" Architektur
|
|
... (Scraping/Map-Reduce etc. bleiben gleich) ...
|
|
|
|
### 📊 Relationaler Notion Import (Competitive Radar v3.0 - Level 4)
|
|
Um die Analyse-Ergebnisse optimal nutzbar zu machen, wurde ein intelligenter Import-Prozess nach Notion implementiert (`import_competitive_radar.py`).
|
|
|
|
* **Architektur:** Vier vernetzte Datenbanken mit **semantischer Klassifizierung**:
|
|
1. **📦 Companies (Hub):** Stammdaten und strategische Zusammenfassung.
|
|
2. **💣 Landmines (Satellite):** Angriffsfragen, automatisch getaggt nach Themen:
|
|
- *Price/TCO, Service/Support, Technology/AI, Performance, Trust/Reliability*.
|
|
3. **🏆 References (Satellite):** Echte Kundenprojekte (Grounded Truth).
|
|
4. **🤖 Products (Satellite):** Einzelne Produkte, klassifiziert nach Typ:
|
|
- *Cleaning (Indoor/Outdoor), Transport/Logistics, Service/Gastro, Security, Software*.
|
|
* **Dual-Way Relations:** Alle Datenbanken sind bidirektional verknüpft. Auf einer Produktkarte sieht man sofort den Hersteller; auf einer Herstellerkarte sieht man das gesamte (kategorisierte) Portfolio.
|
|
|
|
### 🚀 Next-Gen Analyse-Strategie (v5) - Beschluss vom 12. Jan. 2026
|
|
|
|
Die Analyse der v4-Ergebnisse zeigte fundamentale Schwächen im monolithischen Analyse-Ansatz. Probleme wie die falsche Gruppierung von Produktlisten (z.B. "A, B, C" als ein Produkt) und die fehlende Differenzierung desselben Produkts über verschiedene Anbieter hinweg (z.B. "BellaBot" vs. "Pudu Bella Bot") machten eine strategische Neuausrichtung notwendig.
|
|
|
|
Der neue Prozess basiert auf einer **"Extract-Normalize-Enrich" Pipeline in drei Phasen:**
|
|
|
|
**Phase 1: Datensammlung (pro Wettbewerber)**
|
|
1. **Gezieltes Scraping:** Fokussierte Suche nach Seiten mit Keywords wie "Produkte", "Portfolio", "Lösungen". Der Rohtext dieser Seiten wird extrahiert.
|
|
2. **Rohe Produkt-Extraktion (1. LLM-Call):** Ein einfacher, isolierter Prompt extrahiert nur eine unstrukturierte Liste potenzieller Produktnamen.
|
|
3. **Deterministische Säuberung (Python):** Die rohe Liste wird per Code aufbereitet (Trennung bei Kommas, "und", etc.), um einzelne Produkte zu isolieren.
|
|
4. **Allgemeine Analyse (2. LLM-Call):** Ein paralleler Prompt analysiert den Rohtext auf allgemeine, nicht-produktbezogene Merkmale (`delivery_model`, `target_industries`, `differentiators`).
|
|
|
|
**Phase 2: Marktweite Produkt-Kanonisierung (Global & Einmalig)**
|
|
5. **Master-Liste erstellen:** Die bereinigten Produktlisten aller Wettbewerber werden zu einer globalen Master-Liste zusammengefasst.
|
|
6. **Grounded Truth (Hersteller-Daten):** Eine vordefinierte, kanonische Produktliste der wichtigsten Hersteller (Pudu, Gausium etc.) wird als Referenz geladen.
|
|
7. **Kanonisierungs-Prompt (3. LLM-Call):** Ein einziger, globaler Call gleicht die Master-Liste mit der "Grounded Truth" der Hersteller ab. Er gruppiert alle Namensvarianten ("Bella Bot", "Pudu BellaBot") unter einem kanonischen Namen ("BellaBot").
|
|
|
|
**Phase 3: Gezielte Anreicherung & Assemblierung (pro Wettbewerber)**
|
|
8. **Portfolio zusammenstellen:** Das System iteriert durch die kanonische Produkt-Map aus Phase 2.
|
|
9. **Anreicherungs-Prompt (Serie von Micro-LLM-Calls):** Für jedes kanonische Produkt, das ein Wettbewerber anbietet, wird ein kleiner, gezielter Prompt abgesetzt, um spezifische Details (`purpose`, `category`) aus dem ursprünglichen Rohtext zu extrahieren.
|
|
10. **Finale Assemblierung:** Die Ergebnisse der allgemeinen Analyse (Schritt 4) und des angereicherten Portfolios (Schritt 9) werden zum finalen, sauberen und normalisierten JSON-Objekt für den Wettbewerber zusammengefügt.
|
|
|
|
Dieser Ansatz trennt klar zwischen Datensammlung, marktweiter Normalisierung und spezifischer Anreicherung, was zu deutlich präziseren, konsistenteren und wertvolleren Analyse-Ergebnissen führt.
|
|
|
|
### ✅ Status: Jan 12, 2026 - v5 STABLE & PRODUCTION READY
|
|
|
|
Die Implementierung der v5-Pipeline ist abgeschlossen. Die initialen Kinderkrankheiten (SDK-Konflikte, Token-Limits bei Matrizen) wurden durch radikale Architektur-Entscheidungen behoben.
|
|
|
|
**Die 3 Säulen der finalen Lösung:**
|
|
|
|
1. **Hybrid Intelligence (The "Matrix Fix"):**
|
|
* **Problem:** LLMs scheiterten daran, große Matrizen (Produkte x Wettbewerber) konsistent als JSON zu generieren (Abbruch wegen Token-Limit).
|
|
* **Lösung:** **Python übernimmt die Struktur, KI den Inhalt.** Die Matrizen (`product_matrix`, `industry_matrix`) werden nun **deterministisch im Python-Code berechnet**, basierend auf den in Phase 3 gesammelten Daten. Die KI wird nur noch für die *textliche* Zusammenfassung (`summary`, `opportunities`) gerufen. Das Ergebnis ist 100% fehlerfrei und stabil.
|
|
|
|
2. **User-In-The-Loop (Data Rescue):**
|
|
* **Feature:** In Schritt 4 wurde ein "Repair"-Modus implementiert. Nutzer können nun für jeden Wettbewerber **manuelle Produkt-URLs** nachreichen und eine **isolierte Neu-Analyse** (Re-Scrape & Re-Enrich) für diesen einen Wettbewerber auslösen, ohne den gesamten Prozess neu zu starten. Dies löst das Problem von "versteckten" Produktseiten (z.B. Giobotics).
|
|
|
|
3. **Quality Boost (CoT):**
|
|
* **Feature:** Der Enrichment-Prompt (Phase 3) nutzt nun **Chain-of-Thought (CoT)**. Anstatt stumpf Daten zu extrahieren, wird die KI angewiesen: *"Suche alle Erwähnungen -> Synthetisiere eine Beschreibung -> Bestimme die Kategorie"*. Dies hat die inhaltliche Qualität der Produktbeschreibungen wieder auf das hohe Niveau von v2 gehoben, bei gleichzeitiger Beibehaltung der sauberen Struktur von v3.
|
|
|
|
**Fazit:** Der Competitor Analysis Agent ist nun ein robustes, professionelles BI-Tool, das bereit für den produktiven Einsatz und den Import nach Notion ist.
|
|
|
|
### 🏆 Final Validation (Jan 12, 2026 - 14:00)
|
|
|
|
Der Validierungslauf mit `analysis_robo-planet.de-4.json` bestätigt den Erfolg aller Maßnahmen:
|
|
|
|
* **Lückenlose Erfassung:** Dank des "Repair Mode" (Manuelle URLs) konnte das Portfolio von *Giobotics*, das zuvor leer war, vollständig mit 9 Produkten (PuduBot 2, KettyBot, etc.) erfasst werden.
|
|
* **Hohe Datentiefe:** Die Produktbeschreibungen sind dank **Chain-of-Thought** detailliert und wertstiftend (z.B. genaue Funktionsweise des *Phantas* Roboters bei TCO Robotics), statt nur generische Einzeiler zu sein.
|
|
* **Perfekte Matrizen:** Die Python-generierten Matrizen sind vollständig und fehlerfrei. Das Token-Limit-Problem gehört der Vergangenheit an.
|
|
* **Stabilität:** Der gesamte Prozess lief ohne Abstürze oder API-Fehler durch.
|
|
|
|
**Status:** ✅ **MIGRATION COMPLETE & VERIFIED.**
|
|
|
|
---
|
|
*Dokumentation finalisiert am 12.01.2026.*
|
|
|