Files
Brancheneinstufung2/MIGRATION_REPORT_COMPETITOR_ANALYSIS.md
Floke 63c7219800 feat(analysis): Ground Step 8 Reference Analysis
Improves the competitor reference analysis (Step 8) by replacing the previous LLM-only approach with a grounded, scraping-based method.

- Implemented a new scraper to actively search for and parse competitor reference/case study pages.
- The analysis is now based on actual website content, significantly increasing the accuracy and reliability of the results and preventing model hallucinations.
- Updated documentation to reflect the new 'Grounded References' architecture.
2026-01-11 11:01:44 +00:00

6.0 KiB

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.
      1. Ein neuer Scraper (discover_and_scrape_references_page) sucht gezielt nach "Referenzen", "Case Studies" oder "Kunden" auf der Website des Wettbewerbers.
      2. Der Inhalt DIESER Seiten wird extrahiert.
      3. Nur dieser "grounded" Text wird an das LLM zur Analyse und Extraktion übergeben.
    • Ergebnis: Die Analyse basiert nun auf Fakten von der Webseite des Wettbewerbers, nicht auf dem allgemeinen Wissen der KI.

🛡️ Die finale "Grounded" Architektur

  • Scraping: Nutzt requests und BeautifulSoup, um nicht nur die Homepage, sondern auch Produkt- und Branchen-Unterseiten zu lesen.
  • Grounded References: Für die Referenzanalyse (Schritt 8) wird nun gezielt nach "Case Study" oder "Kunden"-Seiten gescraped, um die Extraktion auf echte Daten zu stützen und Halluzinationen zu vermeiden.
  • Map-Reduce: Statt eines Riesen-Prompts werden Konkurrenten parallel einzeln analysiert. Das skaliert linear.
  • Logging: Ein spezieller log_debug Helper schreibt direkt in /app/Log_from_docker, um Python-Logging-Probleme zu umgehen.

Lessons Learned für die Ewigkeit

  1. F-STRINGS SIND VERBOTEN für Prompts und komplexe Listen-Operationen.
  2. TRIPLE RAW QUOTES (r"""...""") sind der einzige sichere Weg für Strings in Docker-Umgebungen.
  3. DUAL SDK STRATEGY: Legacy SDK für Stabilität (gemini-2.0-flash), Modern SDK für Spezial-Features.
  4. MAP-REDUCE: Bei Listen > 3 Elementen niemals das LLM bitten, "alle auf einmal" zu bearbeiten. Immer zerlegen (Map) und aggregieren (Reduce).
  5. SCHEMA FIRST: Frontend (types.ts) und Backend (Pydantic) müssen vorher abgeglichen werden. 422 bedeutet fast immer Schema-Mismatch.

Dokumentation aktualisiert am 11.01.2026 nach erfolgreicher Skalierung auf 9+ Konkurrenten.