diff --git a/helpers.py b/helpers.py index 498fb7b9..d9b75465 100644 --- a/helpers.py +++ b/helpers.py @@ -1031,12 +1031,12 @@ def generate_fsm_pitch( techniker_bucket_ml, ): """ - Generiert einen FSM-Pitch mittels eines "Chain of Thought"-Ansatzes, um die Qualität - und Relevanz der Ausgabe zu maximieren (v2.2.8). + Generiert einen FSM-Pitch mittels eines "Few-Shot"-Ansatzes, der auf exzellenten + Beispielen basiert, um eine aktive, pointierte Tonalität zu gewährleisten (v2.2.9). """ logger = logging.getLogger(__name__) - # 1. Datenaufbereitung (bleibt gleich) + # 1. Datenaufbereitung beschreibung_kombiniert = [] if website_summary and '**GESCHÄFTSMODELL**' in website_summary: try: @@ -1052,55 +1052,53 @@ def generate_fsm_pitch( if not final_beschreibung: return "FEHLER (Mangelnde Daten)" + # 2. Namenswahl und 3. Personalinfo display_name = company_short_name if company_short_name and company_short_name.lower() != 'k.a.' else company_name personal_info = "" try: tech = int(anzahl_techniker or 0) ma = int(anzahl_ma or 0) - 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" + if tech > 0: personal_info = f"Ihre rund {int(round(tech, -1))} Servicetechniker" + elif techniker_bucket_ml and 'k.a.' not in techniker_bucket_ml.lower(): personal_info = f"Ihre schätzungsweise {techniker_bucket_ml} Servicetechniker" + elif ma > 0: personal_info = f"Ihre über {int(round(ma, -2))} Mitarbeiter" except (ValueError, TypeError): pass - # 2. Der neue "Chain of Thought"-Prompt + # 4. Der finale "Few-Shot"-Prompt prompt_parts = [ - "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}", + "Du bist ein exzellenter B2B-Stratege und Texter. Deine Aufgabe ist es, für ein Unternehmen einen hochpersonalisierten und scharfsinnigen Einleitungssatz für eine E-Mail zu formulieren, der deren zentrale operative Herausforderung im Außendienst adressiert.", + "", + "--- Denkprozess ---", + "1. **Identifiziere die Kern-Service-Tätigkeit:** Was tun die mobilen Teams des Unternehmens? (z.B. Installationen, Wartung, Reparatur).", + "2. **Quantifiziere die Herausforderung:** Verbinde die Tätigkeit mit der Unternehmensgröße oder der Anzahl der Anlagen/Kunden.", + "3. **Formuliere den Satz:** Schreibe einen aktiven Satz, der mit 'UNTERNEHMENSNAME steht vor der Herausforderung...' beginnt. Der Satz muss die Tätigkeit, die Skalierung und das Geschäftsziel (z.B. Kundenzufriedenheit, Effizienz) verbinden.", + "4. **Nutze den Kurznamen:** Verwende IMMER den bereitgestellten 'Kurzname des Unternehmens', nicht die volle Firmierung.", + "", + "--- Exzellente Beispiele für den Zielsatz ---", + "Beispiel 1: 1KOMMA5° steht vor der Herausforderung, mit einer begrenzten Anzahl von Servicetechnikern die steigende Nachfrage nach schnellen und effizienten Installationen von integrierten Energielösungen zu bewältigen, um Kundenzufriedenheit sicherzustellen.", + "Beispiel 2: 2G Energy steht vor der Herausforderung, ihre 200 Servicetechniker effizient zu koordinieren, um die zunehmende Nachfrage nach Vor-Ort-Service und digitaler Wartung bei über 8.500 installierten Modulen weltweit zeitnah zu erfüllen.", + "Beispiel 3: Angesichts Ihrer Spezialisierung auf die Entwicklung und Herstellung von Highend-Produktionsanlagen für kritische Industrien, ist die präzise Projektplanung und -umsetzung durch Ihre über 450 Mitarbeiter der Schlüssel zum Erfolg.", + "", + "--- Selbstkritik ---", + "Wenn die Beschreibung keine konkrete Service-Tätigkeit erkennen lässt (z.B. reiner Handel, Online-Portal), antworte NUR mit dem Wort 'FEHLER_DATEN'.", + "", + "--- Unternehmenskontext für deine Aufgabe ---", + f"Kurzname des Unternehmens: {display_name}", + f"KI-validierte Branche: {ki_branche}", f"Beschreibung: {final_beschreibung}", - f"Personalinfo: {personal_info if personal_info else 'Keine Angabe'}", - - "\n--- Deine Ausgabe (antworte AUSSCHLIESSLICH in diesem exakten Format) ---", - "1. Geschäftsmodell-Analyse: ", - "2. Service-Relevanz: ", - "3. Hebel: ", - "4. FSM-Pitch: ", + f"Personalinfo für den Satz: {personal_info if personal_info else 'Keine Angabe'}", + "", + "--- Deine Ausgabe ---", + "Gib NUR den finalen, perfekt formulierten Satz aus ODER das Wort 'FEHLER_DATEN'.", ] prompt = "\n".join(prompt_parts) try: - 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() + 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('"', '') except Exception as e: logger.error(f"Fehler bei der Generierung des FSM-Pitches für {company_name}: {e}") return "FEHLER (API-Fehler)"