import sys import os import json import argparse from typing import List # Setup Environment sys.path.append(os.path.join(os.path.dirname(__file__), "../../")) from backend.database import SessionLocal, Industry, Persona, MarketingMatrix # --- Configuration --- MODEL = "gpt-4o" def generate_prompt(industry: Industry, persona: Persona) -> str: """ Builds the prompt for the AI to generate the marketing texts. Combines Industry context with Persona specific pains/gains. """ # Safely load JSON lists try: persona_pains = json.loads(persona.pains) if persona.pains else [] persona_gains = json.loads(persona.gains) if persona.gains else [] except: persona_pains = [persona.pains] if persona.pains else [] persona_gains = [persona.gains] if persona.gains else [] industry_pains = industry.pains if industry.pains else "Allgemeine Effizienzprobleme" prompt = f""" Du bist ein erfahrener B2B-Copywriter für Robotik-Lösungen (Reinigung, Transport, Service). Ziel: Erstelle personalisierte E-Mail-Textbausteine für einen Outreach. --- KONTEXT --- ZIELBRANCHE: {industry.name} BRANCHEN-KONTEXT: {industry.description or 'Keine spezifische Beschreibung'} BRANCHEN-PAINS: {industry_pains} ZIELPERSON (ARCHETYP): {persona.name} PERSÖNLICHE PAINS (Herausforderungen): {chr(10).join(['- ' + p for p in persona_pains])} GEWÜNSCHTE GAINS (Ziele): {chr(10).join(['- ' + g for g in persona_gains])} --- AUFGABE --- Erstelle ein JSON-Objekt mit genau 3 Textbausteinen. Tonalität: Professionell, lösungsorientiert, auf den Punkt. Keine Marketing-Floskeln ("Game Changer"). 1. "subject": Betreffzeile (Max 6 Wörter). Muss neugierig machen und einen Pain adressieren. 2. "intro": Einleitungssatz (1-2 Sätze). Verbinde die Branchen-Herausforderung mit der persönlichen Rolle des Empfängers. Zeige Verständnis für seine Situation. 3. "social_proof": Ein Satz, der Vertrauen aufbaut. Nenne generische Erfolge (z.B. "Unternehmen in der {industry.name} senken so ihre Kosten um 15%"), da wir noch keine spezifischen Logos nennen dürfen. --- FORMAT --- {{ "subject": "...", "intro": "...", "social_proof": "..." }} """ return prompt def mock_openai_call(prompt: str): """Simulates an API call for dry runs.""" print(f"\n--- [MOCK] GENERATING PROMPT ---\n{prompt[:300]}...\n--------------------------------") return { "subject": "[MOCK] Effizienzsteigerung in der Produktion", "intro": "[MOCK] Als Produktionsleiter wissen Sie, wie teuer Stillstand ist. Unsere Roboter helfen.", "social_proof": "[MOCK] Ähnliche Betriebe sparten 20% Kosten." } def real_openai_call(prompt: str): # This would link to the actual OpenAI client # For now, we keep it simple or import from a lib import openai from backend.config import settings if not settings.OPENAI_API_KEY: raise ValueError("OPENAI_API_KEY not set") client = openai.OpenAI(api_key=settings.OPENAI_API_KEY) response = client.chat.completions.create( model=MODEL, response_format={"type": "json_object"}, messages=[{"role": "user", "content": prompt}], temperature=0.7 ) return json.loads(response.choices[0].message.content) def run_matrix_generation(dry_run: bool = True, force: bool = False): db = SessionLocal() try: industries = db.query(Industry).all() personas = db.query(Persona).all() print(f"Found {len(industries)} Industries and {len(personas)} Personas.") print(f"Mode: {'DRY RUN (No API calls, no DB writes)' if dry_run else 'LIVE'}") total_combinations = len(industries) * len(personas) processed = 0 for ind in industries: for pers in personas: processed += 1 print(f"[{processed}/{total_combinations}] Check: {ind.name} x {pers.name}") # Check existing existing = db.query(MarketingMatrix).filter( MarketingMatrix.industry_id == ind.id, MarketingMatrix.persona_id == pers.id ).first() if existing and not force: print(f" -> Skipped (Already exists)") continue # Generate prompt = generate_prompt(ind, pers) if dry_run: result = mock_openai_call(prompt) else: try: result = real_openai_call(prompt) except Exception as e: print(f" -> API ERROR: {e}") continue # Write to DB (only if not dry run) if not dry_run: if not existing: new_entry = MarketingMatrix( industry_id=ind.id, persona_id=pers.id, subject=result.get("subject"), intro=result.get("intro"), social_proof=result.get("social_proof") ) db.add(new_entry) print(f" -> Created new entry.") else: existing.subject = result.get("subject") existing.intro = result.get("intro") existing.social_proof = result.get("social_proof") print(f" -> Updated entry.") db.commit() except Exception as e: print(f"Error: {e}") finally: db.close() if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--live", action="store_true", help="Actually call OpenAI and write to DB") parser.add_argument("--force", action="store_true", help="Overwrite existing matrix entries") args = parser.parse_args() run_matrix_generation(dry_run=not args.live, force=args.force)