diff --git a/helpers.py b/helpers.py index 11cdf301..498fb7b9 100644 --- a/helpers.py +++ b/helpers.py @@ -1031,18 +1031,17 @@ def generate_fsm_pitch( techniker_bucket_ml, ): """ - Generiert einen maßgeschneiderten, strategischen Satz, der eine operative - Herausforderung impliziert und für die E-Mail-Ansprache geeignet ist (v2.2.7). + Generiert einen FSM-Pitch mittels eines "Chain of Thought"-Ansatzes, um die Qualität + und Relevanz der Ausgabe zu maximieren (v2.2.8). """ logger = logging.getLogger(__name__) - # 1. Daten-Check und Extraktion der reinen Zusammenfassung + # 1. Datenaufbereitung (bleibt gleich) beschreibung_kombiniert = [] if website_summary and '**GESCHÄFTSMODELL**' in website_summary: try: summary_text = website_summary.split('Zusammenfassung:')[1].split('**FSM-POTENZIAL**')[0].strip() - if summary_text: - beschreibung_kombiniert.append(f"Website-Zusammenfassung: {summary_text}") + if summary_text: beschreibung_kombiniert.append(f"Website-Zusammenfassung: {summary_text}") except IndexError: pass if wiki_absatz and 'k.a.' not in wiki_absatz.lower(): @@ -1051,65 +1050,57 @@ def generate_fsm_pitch( 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)" - # 2. Namenswahl und 3. Personalinfo (bleibt unverändert) display_name = company_short_name if company_short_name and company_short_name.lower() != 'k.a.' else company_name - def round_number(n): - if n < 100: return n - if n < 1000: return int(round(n / 50.0)) * 50 - return int(round(n / 100.0)) * 100 - - personal_info = "" # Wir machen es optional + personal_info = "" 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 ma > 0: - personal_info = f"bei über {round_number(ma)} Mitarbeitern" - except (ValueError, TypeError): - pass + if tech > 0: personal_info = f"bei rund {int(round(tech, -1))} 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 ma > 0: personal_info = f"bei über {int(round(ma, -2))} Mitarbeitern" + except (ValueError, TypeError): pass - # 4. Der finale, strategische und positiv formulierte Prompt + # 2. Der neue "Chain of Thought"-Prompt prompt_parts = [ - "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 der Lösung betont.", - "", - "--- Tonalität & Stil ---", - "- Formuliere als scharfsinnige Beobachtung, nicht als Problem ('Für ein Unternehmen wie X ist Y entscheidend, um Z zu erreichen').", - "- Der Satz muss direkt als erster Absatz in einer E-Mail an das Unternehmen funktionieren.", - "- Beziehe die Personalinfo (falls vorhanden) elegant in den Satz ein.", - "", - "--- 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 (viele Standorte/Partner):** Betone die Wichtigkeit der **'gleichbleibend hohen Servicequalität'** über alle Standorte hinweg.", - "3. **Reparaturservice:** Betone die Wichtigkeit der **'schnellen Reaktionszeiten'** und der **'Einhaltung von Service-Levels'**.", - "", - "--- Selbstkritik-Regel (WICHTIG) ---", - "Wenn die Beschreibung so allgemein ist, dass keine der Inferenz-Regeln spezifisch angewendet werden kann (z.B. reiner Handel, Online-Portal), antworte NUR mit dem Wort 'FEHLER_DATEN'.", - "", - "--- Unternehmenskontext ---", - f"Kurzname des Unternehmens: {display_name}", - f"KI-validierte Branche: {ki_branche}", + "Du bist ein B2B-Lösungsberater für Field Service Management. Deine Aufgabe ist es, aus Unternehmensdaten eine scharfsinnige Analyse abzuleiten und daraus einen perfekten, personalisierten Einleitungssatz für eine E-Mail zu formulieren.", + + "\n--- Denkprozess (Chain of Thought) ---", + "Gehe die folgenden Schritte durch und gib deine Analyse für jeden Schritt aus:", + "1. **Geschäftsmodell-Analyse:** Analysiere die Beschreibung und identifiziere die primäre Tätigkeit. Ist es (A) Hersteller von physischen Produkten/Anlagen, (B) ein Installateur/Dienstleister, der bei Kunden vor Ort arbeitet, oder (C) ein reiner Reparaturservice?", + "2. **Service-Relevanz:** Basierend auf Schritt 1, bewerte die Wahrscheinlichkeit eines signifikanten technischen Außendienstes (Hoch, Mittel, Niedrig, Keine).", + "3. **Hebel identifizieren:** Welcher operative Hebel ist für diese Art von Service am wichtigsten? (z.B. 'maximale Anlagenverfügbarkeit', 'gleichbleibend hohe Servicequalität', 'schnelle Reaktionszeiten').", + "4. **Pitch-Formulierung:** Basierend auf deiner Analyse, formuliere einen einzigen, positiv-beobachtenden Satz (20-35 Wörter), der diesen Hebel adressiert und für die E-Mail-Ansprache geeignet ist. Der Satz soll die Wichtigkeit der Prozessoptimierung betonen, nicht ein Problem anklagen.", + + "\n--- Unternehmenskontext ---", + f"Kurzname: {display_name}", + f"KI-Branche: {ki_branche}", f"Beschreibung: {final_beschreibung}", f"Personalinfo: {personal_info if personal_info else 'Keine Angabe'}", - "", - "--- Deine Aufgabe ---", - "Gib NUR den finalen, positiv formulierten Satz aus ODER das Wort 'FEHLER_DATEN'.", + + "\n--- Deine Ausgabe (antworte AUSSCHLIESSLICH in diesem exakten Format) ---", + "1. Geschäftsmodell-Analyse: ", + "2. Service-Relevanz: ", + "3. Hebel: ", + "4. FSM-Pitch: ", ] 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 (Grund: Mangelnde/unspezifische Daten).") - return "FEHLER (Mangelnde Daten)" - return fsm_pitch.strip().replace('"', '') + response = call_openai_chat(prompt, temperature=0.5, model="gpt-4o") + if not response: + return "FEHLER (API-Antwort leer)" + + # Wir geben die gesamte Chain-of-Thought-Analyse zurück. + # Die Formatierung für das Sheet machen wir hier. + formatted_response = response.replace("1. Geschäftsmodell-Analyse:", "**Analyse:**") + formatted_response = formatted_response.replace("2. Service-Relevanz:", "\n**Relevanz:**") + formatted_response = formatted_response.replace("3. Hebel:", "\n**Hebel:**") + formatted_response = formatted_response.replace("4. FSM-Pitch:", "\n\n**Pitch:**") + + return formatted_response.strip() except Exception as e: logger.error(f"Fehler bei der Generierung des FSM-Pitches für {company_name}: {e}") return "FEHLER (API-Fehler)"