generate_marketing_text.py hinzugefügt
This commit is contained in:
152
generate_marketing_text.py
Normal file
152
generate_marketing_text.py
Normal file
@@ -0,0 +1,152 @@
|
||||
# generate_marketing_text.py
|
||||
|
||||
import os
|
||||
import yaml
|
||||
import logging
|
||||
import time
|
||||
import openai
|
||||
import json
|
||||
import pandas as pd
|
||||
import argparse
|
||||
from config import Config
|
||||
|
||||
# --- Konfiguration ---
|
||||
KNOWLEDGE_BASE_FILE = "marketing_wissen.yaml"
|
||||
OUTPUT_FILE = "marketing_text_blocks.xlsx" # Excel ist besser für lange Texte
|
||||
MODEL_TO_USE = "gpt-4o"
|
||||
|
||||
# --- Logging einrichten ---
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
|
||||
def call_openai_with_retry(prompt, max_retries=3, delay=5):
|
||||
"""Ruft die OpenAI API mit Retry-Logik auf und erwartet eine JSON-Antwort."""
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
logging.info(f"Sende Prompt an OpenAI (Versuch {attempt + 1}/{max_retries})...")
|
||||
response = openai.ChatCompletion.create(
|
||||
model=MODEL_TO_USE,
|
||||
response_format={"type": "json_object"}, # Fordert explizit JSON an
|
||||
messages=[{"role": "user", "content": prompt}],
|
||||
temperature=0.6,
|
||||
max_tokens=1024
|
||||
)
|
||||
content = response.choices[0].message['content'].strip()
|
||||
return json.loads(content) # Direkt als JSON-Objekt zurückgeben
|
||||
except json.JSONDecodeError as e:
|
||||
logging.error(f"Fehler beim Parsen der JSON-Antwort von OpenAI: {e}")
|
||||
logging.debug(f"Rohe Antwort: {content}")
|
||||
except Exception as e:
|
||||
logging.error(f"Fehler bei OpenAI-API-Aufruf: {e}")
|
||||
|
||||
if attempt < max_retries - 1:
|
||||
logging.info(f"Warte {delay} Sekunden vor dem nächsten Versuch...")
|
||||
time.sleep(delay)
|
||||
else:
|
||||
logging.error("Maximale Anzahl an Wiederholungen erreicht.")
|
||||
return None
|
||||
|
||||
def build_prompt(branch_name, branch_data, position_name, position_data):
|
||||
"""Baut den finalen Master-Prompt zusammen."""
|
||||
|
||||
branch_pain_points = "\n".join([f"- {p}" for p in branch_data.get('pain_points', [])])
|
||||
position_pain_points = "\n".join([f"- {p}" for p in position_data.get('pains_DE', [])])
|
||||
|
||||
return "\n".join([
|
||||
"Du bist ein kompetenter Lösungsberater auf Augenhöhe. Du verstehst die Herausforderungen einer Branche und einer spezifischen Management-Rolle und kannst elegant aufzeigen, wie Technologie diese lösen kann.",
|
||||
"AUFGABE: Erstelle 2 Textblöcke (Subject, Introduction_Textonly) für eine E-Mail. Die Texte müssen so formuliert sein, dass sie nahtlos an einen vorausgehenden, unternehmensspezifischen Satz anknüpfen, der eine operative Service-Herausforderung beschreibt.",
|
||||
"\n--- UNSERE LÖSUNG (ZUR ORIENTIERUNG FÜR DICH) ---",
|
||||
"- Wir bieten eine Software zur intelligenten, automatischen Einsatzplanung (unsere Kernkompetenz).",
|
||||
"- Wir bieten eine mobile App für die Techniker im Außendienst.",
|
||||
"\n--- KONTEXT ---",
|
||||
f"ZIELBRANCHE: {branch_name}",
|
||||
f"BRANCHEN-HERAUSFORDERUNGEN (PAIN POINTS):\n{branch_pain_points}",
|
||||
f"\nANSPRECHPARTNER: {position_name}",
|
||||
f"PERSÖNLICHE HERAUSFORDERUNGEN DES ANSPRECHPARTNERS (PAIN POINTS):\n{position_pain_points}",
|
||||
"\n--- DEINE AUFGABE ---",
|
||||
"1. **Subject:** Formuliere eine kurze, prägnante Betreffzeile (max. 5 Wörter), die ein Kernthema aufgreift.",
|
||||
"2. **Introduction_Textonly:** Formuliere einen Einleitungstext (2 Sätze) nach dem folgenden Muster:",
|
||||
" - **Satz 1 (Die Brücke & Lösungs-Andeutung):** Knüpfe an die (uns unbekannte) Herausforderung an. Formuliere, dass die Lösung in einer **intelligenten Planung** oder der **digitalen Unterstützung der Techniker** liegt. Wähle den Aspekt (Planung vs. Mobile), der am besten zu den Branchen-Pain-Points passt.",
|
||||
" - **Satz 2 (Die Relevanz für die Position):** Schaffe die Relevanz für die Zielperson, indem du das Thema mit einem ihrer persönlichen Pain Points verknüpfst.",
|
||||
"\n--- BEISPIEL FÜR EINEN PERFEKTEN OUTPUT (Kombination Anlagenbau & IT) ---",
|
||||
'''
|
||||
{
|
||||
"Subject": "Optimierung der Service-Einsatzplanung",
|
||||
"Introduction_Textonly": "Konkret geht es darum, die Koordination Ihrer komplexen Service-Einsätze durch eine intelligente Software zur Einsatzplanung zu optimieren. Für Sie als IT-Leiter ist dabei sicher die nahtlose und sichere Integration in Ihre bestehende ERP-Landschaft von entscheidender Bedeutung."
|
||||
}
|
||||
''',
|
||||
"\nErstelle jetzt das JSON-Objekt für die oben genannte Kombination aus Branche und Ansprechpartner."
|
||||
])
|
||||
|
||||
def main(specific_branch=None):
|
||||
"""Hauptfunktion zur Generierung der Marketing-Texte."""
|
||||
logging.info("Starte die Generierung der Marketing-Textblöcke...")
|
||||
|
||||
Config.load_api_keys()
|
||||
openai.api_key = Config.API_KEYS.get('openai')
|
||||
if not openai.api_key:
|
||||
logging.critical("OpenAI API Key nicht gefunden. Skript wird beendet.")
|
||||
return
|
||||
|
||||
try:
|
||||
with open(KNOWLEDGE_BASE_FILE, 'r', encoding='utf-8') as f:
|
||||
knowledge_base = yaml.safe_load(f)
|
||||
except FileNotFoundError:
|
||||
logging.critical(f"FEHLER: Die Wissensbasis '{KNOWLEDGE_BASE_FILE}' wurde nicht gefunden.")
|
||||
return
|
||||
|
||||
results = []
|
||||
|
||||
target_branches = knowledge_base.get('Branchen', {})
|
||||
if specific_branch:
|
||||
if specific_branch in target_branches:
|
||||
logging.info(f"Fokus auf einzelne Branche: {specific_branch}")
|
||||
target_branches = {specific_branch: target_branches[specific_branch]}
|
||||
else:
|
||||
logging.error(f"FEHLER: Die angegebene Branche '{specific_branch}' wurde in der Wissensbasis nicht gefunden.")
|
||||
return
|
||||
|
||||
positions = knowledge_base.get('Positionen', {})
|
||||
|
||||
for branch_name, branch_data in target_branches.items():
|
||||
for position_key, position_data in positions.items():
|
||||
logging.info(f"--- Generiere Texte für: Branche='{branch_name}', Position='{position_key}' ---")
|
||||
|
||||
prompt = build_prompt(branch_name, branch_data, position_data.get('name_DE', position_key), position_data)
|
||||
|
||||
# Hier könnten wir noch eine DE/EN Schleife einbauen, für den Moment nur DE
|
||||
generated_json = call_openai_with_retry(prompt)
|
||||
|
||||
if generated_json:
|
||||
results.append({
|
||||
'Branch Detail': branch_name,
|
||||
'Department': position_key,
|
||||
'Language': 'DE',
|
||||
'Subject': generated_json.get('Subject', 'FEHLER BEI GENERIERUNG'),
|
||||
'Introduction_Textonly': generated_json.get('Introduction_Textonly', 'FEHLER BEI GENERIERUNG'),
|
||||
'Industry References (Text only)': branch_data.get('references_DE', '')
|
||||
})
|
||||
else:
|
||||
results.append({
|
||||
'Branch Detail': branch_name,
|
||||
'Department': position_key,
|
||||
'Language': 'DE',
|
||||
'Subject': 'FEHLER: KI-Antwort war ungültig',
|
||||
'Introduction_Textonly': 'FEHLER: KI-Antwort war ungültig',
|
||||
'Industry References (Text only)': branch_data.get('references_DE', '')
|
||||
})
|
||||
time.sleep(2) # Pause zur Schonung der API
|
||||
|
||||
# Ergebnisse in eine Excel-Datei schreiben
|
||||
if results:
|
||||
df = pd.DataFrame(results)
|
||||
df.to_excel(OUTPUT_FILE, index=False)
|
||||
logging.info(f"\nErfolgreich! {len(results)} Textvarianten wurden in '{OUTPUT_FILE}' gespeichert.")
|
||||
else:
|
||||
logging.info("Keine Textvarianten wurden generiert.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generiert Marketing-Textblöcke basierend auf der Wissensbasis.")
|
||||
parser.add_argument("--branch", type=str, help="Generiert Texte nur für diese eine Branche.")
|
||||
args = parser.parse_args()
|
||||
|
||||
main(specific_branch=args.branch)
|
||||
Reference in New Issue
Block a user