124 lines
4.8 KiB
Python
124 lines
4.8 KiB
Python
import sqlite3
|
|
import os
|
|
import json
|
|
import requests
|
|
import argparse
|
|
from dotenv import load_dotenv
|
|
|
|
# --- Configuration & Setup ---
|
|
load_dotenv(dotenv_path="/home/node/clawd/.env", override=True)
|
|
DB_PATH = "/home/node/clawd/repos/brancheneinstufung2/company_explorer_local.db"
|
|
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
|
|
|
|
|
class SniperGenerator:
|
|
def __init__(self, db_path=DB_PATH):
|
|
self.db_path = db_path
|
|
# TODO: Initialize Notion client to get Vertical/Persona data
|
|
# TODO: Load Marketing Report KPIs into memory
|
|
|
|
def get_lead_data(self, company_id):
|
|
"""Gathers all necessary data for a lead from the local DB."""
|
|
conn = sqlite3.connect(self.db_path)
|
|
conn.row_factory = sqlite3.Row
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("SELECT * FROM companies WHERE id = ?", (company_id,))
|
|
company_data = cursor.fetchone()
|
|
conn.close()
|
|
|
|
if not company_data:
|
|
return None
|
|
|
|
return dict(company_data)
|
|
|
|
def select_product_and_persona(self, company_data, target_role):
|
|
"""
|
|
Implements the '3+1' rule to decide which product to pitch.
|
|
Placeholder logic - will be replaced with Notion data.
|
|
"""
|
|
print(f"🎯 Selecting product for role '{target_role}' in industry '{company_data.get('industry_ai')}'...")
|
|
# Placeholder for the 3+1 logic
|
|
# if target_role in ["Wirtschaftl. Entscheider", "Infrastruktur-Verantw."]:
|
|
# return "Primary"
|
|
# if target_role == "Innovations-Treiber":
|
|
# return "Secondary"
|
|
# if target_role == "Operativer Entscheider":
|
|
# # Here we would check the "Ops Focus: Secondary?" checkbox from Notion
|
|
# return "Primary" # Default
|
|
|
|
# For now, we default to the primary product (Cleaning)
|
|
print("-> Defaulting to 'Primary Product' (Cleaning).")
|
|
return "Cleaning"
|
|
|
|
|
|
def generate_copy(self, company_id, target_role="Wirtschaftl. Entscheider"):
|
|
"""
|
|
Generates the 3-sentence sniper copy for a given company and role.
|
|
"""
|
|
# 1. Gather Data
|
|
lead_data = self.get_lead_data(company_id)
|
|
if not lead_data:
|
|
return "Error: Company data not found."
|
|
|
|
# 2. Decide on Product (using 3+1 rule)
|
|
product_to_pitch = self.select_product_and_persona(lead_data, target_role)
|
|
|
|
# 3. Get Social Proof KPIs (from Marketing Report)
|
|
# Placeholder - using hardcoded values from the report
|
|
kpis = {
|
|
"cost_reduction": "10-25%",
|
|
"time_saving": "20-40%"
|
|
}
|
|
|
|
# 4. Construct Master Prompt
|
|
# This is a simplified version for now
|
|
prompt = f"""
|
|
Du bist ein Weltklasse B2B-Stratege. Deine Aufgabe ist es, eine 3-Satz-E-Mail-Einleitung im '1,5°-Stil' zu erstellen.
|
|
|
|
**Regeln:**
|
|
- Satz 1 (Firma): Zeige, dass du das Geschäftsmodell und die zentrale Herausforderung verstanden hast. KEINE ZAHLEN, nur qualitative Größe.
|
|
- Satz 2 (Persona): Sprich den spezifischen Schmerz der Zielrolle an und verbinde ihn mit dem Produkt '{product_to_pitch}'.
|
|
- Satz 3 (Social Proof): Untermauere die Lösung mit einem konkreten KPI von Marktbegleitern.
|
|
|
|
**Daten:**
|
|
- Firma: {lead_data.get('name')}
|
|
- Branche (KI): {lead_data.get('industry_ai')}
|
|
- Standort: {lead_data.get('city')}
|
|
- Rolle: {target_role}
|
|
- KPI 1 (Kosten): {kpis['cost_reduction']}
|
|
- KPI 2 (Zeit): {kpis['time_saving']}
|
|
|
|
**Output:** Nur die 3 Sätze. Sonst nichts.
|
|
"""
|
|
|
|
# 5. Call Gemini API
|
|
print("📞 Calling Gemini to generate copy...")
|
|
headers = {"Content-Type": "application/json"}
|
|
payload = {"contents": [{"parts": [{"text": prompt}]}]}
|
|
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={GEMINI_API_KEY}"
|
|
|
|
try:
|
|
resp = requests.post(url, headers=headers, json=payload, timeout=20)
|
|
resp.raise_for_status()
|
|
result = resp.json()
|
|
copy_text = result['candidates'][0]['content']['parts'][0]['text'].strip()
|
|
return copy_text
|
|
except Exception as e:
|
|
return f"Error during Gemini call: {e}"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Generate sniper copy for a lead.")
|
|
parser.add_argument("company_id", type=int, help="The Company Explorer ID of the lead.")
|
|
parser.add_argument("--role", type=str, default="Wirtschaftl. Entscheider", help="The target persona/role.")
|
|
args = parser.parse_args()
|
|
|
|
sniper = SniperGenerator()
|
|
final_copy = sniper.generate_copy(args.company_id, args.role)
|
|
|
|
print("\n--- GENERATED SNIPER COPY ---")
|
|
print(final_copy)
|
|
print("-----------------------------\n")
|
|
|