From 3db3561780328a4e78b9b40ada58fa50c6f26210 Mon Sep 17 00:00:00 2001 From: Floke Date: Mon, 21 Jul 2025 08:12:50 +0000 Subject: [PATCH] Final Refined & Positive-Toned FSM Pitch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - REFACTOR: Der FSM-Pitch-Prompt wurde final überarbeitet, um eine positive, lösungsorientierte Tonalität für die direkte Kundenansprache zu gewährleisten. - FIX: Die "FEHLER_DATEN"-Regel wurde gelockert, um die Erfolgsquote bei der Pitch-Generierung auch bei dünnerer Datenlage zu erhöhen. - Die generierten Pitches sind nun strategisch fundiert UND für die Marketing-Automation geeignet. --- helpers.py | 63 +++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/helpers.py b/helpers.py index 5e3db1f5..95122bff 100644 --- a/helpers.py +++ b/helpers.py @@ -1031,32 +1031,27 @@ def generate_fsm_pitch( techniker_bucket_ml, ): """ - Generiert einen maßgeschneiderten, nicht-werblichen Satz, der eine operative - Service-Herausforderung des Unternehmens beschreibt (v2.1). + Generiert einen maßgeschneiderten, positiv formulierten Satz, der eine operative + Service-Herausforderung impliziert und für die Kundenansprache geeignet ist (v2.2.6). """ logger = logging.getLogger(__name__) - # 1. Daten-Check und Extraktion + # 1. Daten-Check und Extraktion der reinen Zusammenfassung beschreibung_kombiniert = [] - # Extrahiere NUR den reinen Zusammenfassungstext, falls unsere strukturierte Analyse vorliegt if website_summary and '**GESCHÄFTSMODELL**' in website_summary: try: - # Extrahiert den Text nach "Zusammenfassung:" und vor dem nächsten Abschnitt summary_text = website_summary.split('Zusammenfassung:')[1].split('**FSM-POTENZIAL**')[0].strip() if summary_text: beschreibung_kombiniert.append(f"Website-Zusammenfassung: {summary_text}") except IndexError: - # Fallback, falls das Format unerwartet ist - beschreibung_kombiniert.append(f"Website-Zusammenfassung: {website_summary}") - elif website_summary and 'k.a.' not in website_summary.lower(): - beschreibung_kombiniert.append(f"Website-Zusammenfassung: {website_summary}") # Für alte, unstrukturierte Zusammenfassungen - + pass # Ignoriere Formatierungsfehler, fahre mit anderen Daten fort + if wiki_absatz and 'k.a.' not in wiki_absatz.lower(): beschreibung_kombiniert.append(f"Wikipedia-Einleitung: {wiki_absatz}") - combined = "\n".join(beschreibung_kombiniert) - - if len(combined.split()) < 10: + final_beschreibung = "\n".join(beschreibung_kombiniert) + + if not final_beschreibung: logger.warning(f"Zu wenige Informationen für FSM-Pitch bei {company_name}.") return "FEHLER (Mangelnde Daten)" @@ -1072,45 +1067,49 @@ def generate_fsm_pitch( personal_info = "in einem Unternehmen Ihrer Größe" try: tech = int(anzahl_techniker or 0) + ma = int(anzahl_ma or 0) if tech > 0: personal_info = f"bei rund {round_number(tech)} Servicetechnikern" elif techniker_bucket_ml and 'k.a.' not in techniker_bucket_ml.lower(): personal_info = f"bei schätzungsweise {techniker_bucket_ml} Servicetechnikern" - elif int(anzahl_ma or 0) > 0: - personal_info = f"bei über {round_number(int(anzahl_ma))} Mitarbeitern" - except Exception: + elif ma > 0: + personal_info = f"bei über {round_number(ma)} Mitarbeitern" + except (ValueError, TypeError): logger.debug("Keine validen MA/Techniker-Zahlen für Pitch.") - # 4. Prompt bauen + # 4. Der finale, positiv formulierte Prompt prompt_parts = [ - "Du bist ein B2B-Lösungsberater, spezialisiert auf die Optimierung von Außendienstprozessen. Deine Stärke ist es, aus Unternehmensbeschreibungen den kritischsten operativen Schmerzpunkt (Pain Point) im Service abzuleiten.", - "Aufgabe: Formuliere EINEN EINZIGEN, prägnanten Satz (ca. 20-35 Wörter), der den wahrscheinlichsten **operativen Schmerzpunkt** des Unternehmens im technischen Außendienst adressiert.", + "Du bist ein B2B-Stratege, der die operativen Hebel eines Unternehmens im technischen Außendienst versteht.", + "Aufgabe: Formuliere EINEN EINZIGEN, positiv-beobachtenden Satz (ca. 20-35 Wörter), der die zentrale operative Herausforderung im Service subtil andeutet, indem er die Wichtigkeit ihrer Lösung betont.", "", - "--- Denkprozess & Inferenz-Regeln ---", - "1. **Analysiere das Kerngeschäft:** Ist es die Herstellung komplexer Anlagen, die Installation von Systemen bei Kunden oder ein Reparaturservice?", - "2. **Leite den Schmerzpunkt ab:** Was ist die größte operative Hürde bei dieser Tätigkeit in dieser Größenordnung?", - " - **Regel A (Hersteller):** Bei Anlagenherstellern ist der Schmerzpunkt die **Effizienz bei der Inbetriebnahme** oder die **garantierte Anlagenverfügbarkeit (Uptime)** durch Wartung.", - " - **Regel B (Dezentraler Installateur):** Bei vielen Standorten/Partnern ist der Schmerzpunkt die **Standardisierung der Servicequalität** und die **Routenoptimierung**.", - " - **Regel C (Reparaturservice):** Bei Reparaturdiensten ist der Schmerzpunkt die **Einhaltung von SLAs** und die **First-Time Fix Rate**.", - "3. **Formuliere den Satz:** Verbinde das Unternehmen und seine Personalinfo mit dem identifizierten Schmerzpunkt und den geschäftlichen Konsequenzen (z.B. 'entscheidend für die Kundentreue', 'unerlässlich für die Einhaltung von SLAs').", - "4. **Selbstkritik:** Wenn die Beschreibung zu allgemein ist, um einen spezifischen Schmerzpunkt abzuleiten, antworte NUR mit 'FEHLER_DATEN'.", + "--- Tonalität & Stil ---", + "- Formuliere als scharfsinnige Beobachtung, nicht als Problem.", + "- Der Satz muss direkt als erster Absatz in einer E-Mail an das Unternehmen funktionieren.", + "- Fokus auf die geschäftlichen Konsequenzen (z.B. 'entscheidend für den Projekterfolg', 'unerlässlich für die Kundenzufriedenheit').", + "", + "--- Inferenz-Regeln (um die Kernaussage zu finden) ---", + "1. **Hersteller von Anlagen/Maschinen:** Betone die Wichtigkeit der **'effizienten Inbetriebnahme'** oder der **'maximalen Anlagenverfügbarkeit (Uptime)'**.", + "2. **Installateur/Dienstleister mit vielen Standorten/Partnern:** Betone die Wichtigkeit der **'Standardisierung der Servicequalität'** über alle Standorte hinweg.", + "3. **Reiner Reparaturservice:** Betone die Wichtigkeit der **'schnellen Reaktionszeiten'** und der **'Einhaltung von Service-Levels'**.", + "4. **Wenn unspezifisch:** Formuliere einen etwas allgemeineren, aber immer noch relevanten Satz über die 'Effizienz des Service-Teams'.", "", "--- Unternehmenskontext ---", f"Kurzname des Unternehmens: {display_name}", f"KI-validierte Branche: {ki_branche}", - f"Beschreibung: {combined}", + f"Beschreibung: {final_beschreibung}", f"Personalinfo für den Satz: {personal_info}", "", "--- Deine Aufgabe ---", - "Führe den Denkprozess durch und gib NUR den finalen Satz aus ODER das Wort 'FEHLER_DATEN'.", + "Gib NUR den finalen, positiv formulierten Satz aus.", ] prompt = "\n".join(prompt_parts) try: fsm_pitch = call_openai_chat(prompt, temperature=0.6, model="gpt-4o") - if not fsm_pitch or "FEHLER_DATEN" in fsm_pitch: - logger.warning(f"KI konnte keinen validen FSM-Pitch für {company_name} generieren.") - return "FEHLER (Mangelnde Daten)" + # Wir entfernen die "FEHLER_DATEN"-Prüfung, um die Trefferquote zu erhöhen + if not fsm_pitch: + logger.warning(f"KI konnte keinen FSM-Pitch für {company_name} generieren (leere Antwort).") + return "FEHLER (API-Antwort leer)" return fsm_pitch.strip().replace('"', '') except Exception as e: logger.error(f"Fehler bei der Generierung des FSM-Pitches für {company_name}: {e}")