Files
Brancheneinstufung2/_legacy_gsheets_system/generate_knowledge_base.py
Floke 2c7bb262ef feat(company-explorer): Initial Web UI & Backend with Enrichment Flow
This commit introduces the foundational elements for the new "Company Explorer" web application, marking a significant step away from the legacy Google Sheets / CLI system.

Key changes include:
- Project Structure: A new  directory with separate  (FastAPI) and  (React/Vite) components.
- Data Persistence: Migration from Google Sheets to a local SQLite database () using SQLAlchemy.
- Core Utilities: Extraction and cleanup of essential helper functions (LLM wrappers, text utilities) into .
- Backend Services: , ,  for AI-powered analysis, and  logic.
- Frontend UI: Basic React application with company table, import wizard, and dynamic inspector sidebar.
- Docker Integration: Updated  and  for multi-stage builds and sideloading.
- Deployment & Access: Integrated into central Nginx proxy and dashboard, accessible via .

Lessons Learned & Fixed during development:
- Frontend Asset Loading: Addressed issues with Vite's  path and FastAPI's .
- TypeScript Configuration: Added  and .
- Database Schema Evolution: Solved  errors by forcing a new database file and correcting  override.
- Logging: Implemented robust file-based logging ().

This new foundation provides a powerful and maintainable platform for future B2B robotics lead generation.
2026-01-07 17:55:08 +00:00

149 lines
7.6 KiB
Python

# generate_knowledge_base.py
import os
import yaml
import logging
import time
import openai
from config import Config # Wir nutzen die Config für den API-Schlüssel
# --- Konfiguration ---
# HIER BITTE IHRE FOKUSBRANCHEN EINTRAGEN
# Diese Namen sollten mit den Keys im BRANCH_GROUP_MAPPING aus config.py übereinstimmen.
FOKUS_BRANCHEN = [
"Medizintechnik",
"Anlagenbau",
"Facility Management",
"Maschinenbau",
"IT / Telekommunikation" # Beispiel, bitte anpassen
]
POSITIONEN = {
"IT": "IT-Leiter",
"Management / GF / C-Level": "Geschäftsführer / C-Level",
"Finanzen": "Finanzleiter / CFO",
"Procurement / Einkauf": "Einkaufsleiter",
"Field Service Management": "Leiter Kundenservice / Field Service"
}
OUTPUT_FILE = "marketing_wissen_entwurf.yaml"
# 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."""
for attempt in range(max_retries):
try:
logging.info(f"Sende Prompt an OpenAI (Versuch {attempt + 1}/{max_retries})...")
response = openai.ChatCompletion.create(
model="gpt-4-turbo", # Oder ein anderes Modell Ihrer Wahl
messages=[{"role": "user", "content": prompt}],
temperature=0.5,
max_tokens=500
)
content = response.choices[0].message['content'].strip()
return 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. Breche ab.")
return None
def generate_pain_points_prompt(branch_name):
"""Erstellt den Prompt zur Generierung von Pain Points für eine Branche."""
return "\n".join([
"Du bist ein Top-Strategieberater mit Branchen-Expertise bei einer führenden Unternehmensberatung. Du analysierst die operativen Kernprozesse von Unternehmen und identifizierst die entscheidenden Hebel für Effizienzsteigerungen im Außendienst.",
f"Branche: {branch_name}",
"\n--- Denkprozess (Chain of Thought) ---",
"1. Versetze dich in ein typisches Unternehmen dieser Branche.",
"2. Was sind die häufigsten, sich wiederholenden Aufgaben, die mobile Techniker dort ausführen (z.B. Wartung, Reparatur, Installation, Inspektion)?",
"3. Welche spezifischen Probleme und Engpässe treten bei der Planung und Durchführung DIESER Aufgaben auf? Denke an Regularien, Kundenanforderungen, technische Komplexität und wirtschaftlichen Druck.",
"4. Formuliere aus diesen Problemen 5 prägnante, operative 'Pain Points', die sich auf den Service-Außendienst beziehen.",
"\n--- Aufgabe ---",
"Gib eine Liste von genau 5 Pain Points für die angegebene Branche aus. Formuliere sie als Herausforderungen aus Sicht des Unternehmens.",
"Gib das Ergebnis ausschließlich als saubere YAML-Liste unter dem Schlüssel 'pain_points:' aus. KEINE weiteren Einleitungen oder Kommentare.",
"\n--- Beispiel für den gewünschten Output-Stil (Branche: Aufzüge und Rolltreppen) ---",
"""
pain_points:
- "Sicherstellung der gesetzlich vorgeschriebenen, regelmäßigen Sicherheitsüberprüfungen und deren lückenlose Dokumentation."
- "Minimierung der Ausfallzeiten von Aufzügen in hochfrequentierten Gebäuden durch extrem schnelle Reaktionszeiten bei Störungen."
- "Effiziente Routenplanung, um die Vielzahl an dezentral verteilten Anlagen mit minimalem Fahrtaufwand abzudecken."
- "Bereitstellung von technischer Dokumentation und spezifischen Wartungsplänen für hunderte verschiedene Modelle direkt vor Ort."
- "Management von Ersatzteilen und deren Verfügbarkeit im Servicefahrzeug."
"""
])
def generate_position_focus_prompt(position_name):
"""Erstellt den Prompt zur Generierung des Fokus-Textes für eine Position."""
return "\n".join([
"Du bist ein erfahrener B2B-Vertriebs-Coach. Du formulierst Kernaussagen, die den spezifischen Blickwinkel unterschiedlicher Entscheidungsträger treffen.",
f"Position: {position_name}",
"\n--- Aufgabe ---",
"Formuliere EINEN EINZIGEN Satz, der den typischen Fokus oder das Hauptinteresse dieser Position in Bezug auf die Optimierung von Serviceprozessen beschreibt.",
"Dieser Satz wird später in einer E-Mail verwendet, beginnend mit 'Für Sie als...'. Formuliere den Satz so, dass er dort direkt passt.",
"Beispiel für 'Geschäftsführer': 'stehen vermutlich die Steigerung der Effizienz, die Kundenzufriedenheit und die Skalierbarkeit Ihrer Serviceprozesse im Vordergrund.'",
"Gib NUR den reinen Satz ohne Anführungszeichen oder einleitende Phrasen aus."
])
def main():
"""Hauptfunktion zur Generierung der Wissensbasis."""
logging.info("Starte die Generierung der Wissensbasis für Marketing-Texte...")
# API-Schlüssel laden
Config.load_api_keys()
openai.api_key = Config.API_KEYS.get('openai')
if not openai.api_key:
logging.critical("OpenAI API Key nicht in config.py gefunden. Skript wird beendet.")
return
knowledge_base = {'Branchen': {}, 'Positionen': {}}
# 1. Pain Points für jede Fokusbranche generieren
logging.info(f"Generiere Pain Points für {len(FOKUS_BRANCHEN)} Fokusbranchen...")
for branch in FOKUS_BRANCHEN:
logging.info(f"--- Verarbeite Branche: {branch} ---")
prompt = generate_pain_points_prompt(branch)
response_text = call_openai_with_retry(prompt)
if response_text:
try:
# Versuche, den YAML-Teil zu parsen
parsed_yaml = yaml.safe_load(response_text)
knowledge_base['Branchen'][branch] = {
'pain_points': parsed_yaml.get('pain_points', ['FEHLER: Konnte Pain Points nicht parsen.']),
'references_DE': '[HIER DEUTSCHE REFERENZKUNDEN EINTRAGEN]',
'references_GB': '[HIER ENGLISCHE REFERENZKUNDEN EINTRAGEN]'
}
except yaml.YAMLError as e:
logging.error(f"Fehler beim Parsen der YAML-Antwort für {branch}: {e}")
knowledge_base['Branchen'][branch] = {'pain_points': [f'PARSING-FEHLER: {response_text}']}
time.sleep(2) # Kurze Pause, um Rate-Limits zu vermeiden
# 2. Fokus für jede Position generieren
logging.info(f"\nGeneriere Fokus-Texte für {len(POSITIONEN)} Positionen...")
for key, name in POSITIONEN.items():
logging.info(f"--- Verarbeite Position: {name} ---")
prompt = generate_position_focus_prompt(name)
response_text = call_openai_with_retry(prompt)
if response_text:
knowledge_base['Positionen'][key] = {
'focus_DE': response_text,
'focus_GB': '[HIER ENGLISCHE ÜBERSETZUNG DES FOKUS-SATZES EINTRAGEN]'
}
time.sleep(2)
# 3. Ergebnis in YAML-Datei speichern
try:
with open(OUTPUT_FILE, 'w', encoding='utf-8') as f:
yaml.dump(knowledge_base, f, allow_unicode=True, sort_keys=False, width=120)
logging.info(f"\nErfolgreich! Die Wissensbasis wurde in '{OUTPUT_FILE}' gespeichert.")
logging.info("BITTE ÜBERPRÜFEN SIE DIESE DATEI UND PASSEN SIE SIE NACH BEDARF AN.")
except Exception as e:
logging.error(f"Fehler beim Speichern der YAML-Datei: {e}")
if __name__ == "__main__":
main()