Compare commits
2 Commits
8dc947ae09
...
df80e37ffe
| Author | SHA1 | Date | |
|---|---|---|---|
| df80e37ffe | |||
| a0526a844e |
64
company-explorer/backend/scripts/debug_check_matrix_texts.py
Normal file
64
company-explorer/backend/scripts/debug_check_matrix_texts.py
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
|
||||
# Adjust the path to include the 'company-explorer' directory
|
||||
# This allows the script to find the 'backend' module
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
|
||||
|
||||
from backend.database import SessionLocal, Industry, Persona, MarketingMatrix
|
||||
|
||||
def check_texts_for_industry(industry_name: str):
|
||||
"""
|
||||
Fetches and prints the marketing matrix texts for all personas
|
||||
within a specific industry.
|
||||
"""
|
||||
db = SessionLocal()
|
||||
try:
|
||||
industry = db.query(Industry).filter(Industry.name == industry_name).first()
|
||||
|
||||
if not industry:
|
||||
print(f"Error: Industry '{industry_name}' not found.")
|
||||
# Suggest similar names
|
||||
all_industries = db.query(Industry.name).all()
|
||||
print("\nAvailable Industries:")
|
||||
for (name,) in all_industries:
|
||||
print(f"- {name}")
|
||||
return
|
||||
|
||||
entries = (
|
||||
db.query(MarketingMatrix)
|
||||
.join(Persona)
|
||||
.filter(MarketingMatrix.industry_id == industry.id)
|
||||
.order_by(Persona.id)
|
||||
.all()
|
||||
)
|
||||
|
||||
if not entries:
|
||||
print(f"No marketing texts found for industry: {industry_name}")
|
||||
return
|
||||
|
||||
print(f"--- NEW TEXTS FOR {industry_name} ---")
|
||||
for entry in entries:
|
||||
print(f"\nPERSONA: {entry.persona.name}")
|
||||
print(f"Subject: {entry.subject}")
|
||||
print(f"Intro: {entry.intro.replace(chr(10), ' ')}") # Replace newlines for cleaner one-line output
|
||||
|
||||
except Exception as e:
|
||||
print(f"An error occurred: {e}")
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Debug and check marketing matrix texts for a given industry.")
|
||||
parser.add_argument(
|
||||
"industry",
|
||||
type=str,
|
||||
nargs='?',
|
||||
default="Healthcare - Hospital",
|
||||
help="The name of the industry to check (e.g., 'Healthcare - Hospital'). Defaults to 'Healthcare - Hospital'."
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
check_texts_for_industry(args.industry)
|
||||
@@ -2,11 +2,12 @@ import os
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
from typing import Any # Hinzugefügt
|
||||
|
||||
# Add the backend directory to the Python path
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
# Add the company-explorer directory to the Python path
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
|
||||
|
||||
from backend.database import get_db, Company
|
||||
from backend.database import get_db, Company, Industry, Persona # Added Industry and Persona for full context
|
||||
from backend.services.classification import ClassificationService
|
||||
from backend.lib.logging_setup import setup_logging
|
||||
|
||||
@@ -15,30 +16,41 @@ from backend.lib.logging_setup import setup_logging
|
||||
setup_logging()
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def run_debug_analysis(company_id: int):
|
||||
def run_debug_analysis(company_identifier: Any, is_id: bool):
|
||||
"""
|
||||
Runs the full classification and enrichment process for a single company
|
||||
in the foreground and prints detailed results.
|
||||
"""
|
||||
logger.info(f"--- Starting Interactive Debug for Company ID: {company_id} ---")
|
||||
logger.info(f"--- Starting Interactive Debug for Company: {company_identifier} (by {'ID' if is_id else 'Name'}) ---")
|
||||
|
||||
db_session = next(get_db())
|
||||
|
||||
try:
|
||||
# 1. Fetch the company
|
||||
company = db_session.query(Company).filter(Company.id == company_id).first()
|
||||
if is_id:
|
||||
company = db_session.query(Company).filter(Company.id == company_identifier).first()
|
||||
else:
|
||||
company = db_session.query(Company).filter(Company.name == company_identifier).first()
|
||||
|
||||
if not company:
|
||||
logger.error(f"Company with ID {company_id} not found.")
|
||||
logger.error(f"Company with {'ID' if is_id else 'Name'} {company_identifier} not found.")
|
||||
# If by name, suggest similar names
|
||||
if not is_id:
|
||||
all_company_names = db_session.query(Company.name).limit(20).all()
|
||||
print("\nAvailable Company Names (first 20):")
|
||||
for (name,) in all_company_names:
|
||||
print(f"- {name}")
|
||||
return
|
||||
|
||||
logger.info(f"Found Company: {company.name}")
|
||||
logger.info(f"Found Company: {company.name} (ID: {company.id})")
|
||||
|
||||
# --- PRE-ANALYSIS STATE ---
|
||||
print("\n--- METRICS BEFORE ---")
|
||||
print(f"Calculated: {company.calculated_metric_value} {company.calculated_metric_unit}")
|
||||
print(f"Standardized: {company.standardized_metric_value} {company.standardized_metric_unit}")
|
||||
print(f"Opener 1 (Infra): {company.ai_opener}")
|
||||
print(f"Opener 2 (Ops): {company.ai_opener_secondary}")
|
||||
print("----------------------\n")
|
||||
|
||||
# 2. Instantiate the service
|
||||
@@ -59,14 +71,24 @@ def run_debug_analysis(company_id: int):
|
||||
print(f"Opener 2 (Ops): {updated_company.ai_opener_secondary}")
|
||||
print("---------------------")
|
||||
|
||||
logger.info(f"--- Interactive Debug Finished for Company ID: {company_id} ---")
|
||||
logger.info(f"--- Interactive Debug Finished for Company: {company.name} (ID: {company.id}) ---")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"An error occurred during analysis: {e}", exc_info=True)
|
||||
finally:
|
||||
db_session.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Run a single company analysis for debugging.")
|
||||
parser.add_argument("--id", type=int, default=1, help="The ID of the company to analyze.")
|
||||
parser.add_argument("--id", type=int, help="The ID of the company to analyze.")
|
||||
parser.add_argument("--company-name", type=str, help="The name of the company to analyze.")
|
||||
args = parser.parse_args()
|
||||
|
||||
run_debug_analysis(args.id)
|
||||
if args.id and args.company_name:
|
||||
parser.error("Please provide either --id or --company-name, not both.")
|
||||
elif args.id:
|
||||
run_debug_analysis(args.id, is_id=True)
|
||||
elif args.company_name:
|
||||
run_debug_analysis(args.company_name, is_id=False)
|
||||
else:
|
||||
parser.error("Please provide either --id or --company-name.")
|
||||
|
||||
@@ -112,9 +112,10 @@ PERSÖNLICHE HERAUSFORDERUNGEN DES ANSPRECHPARTNERS (PAIN POINTS):
|
||||
--- DEINE AUFGABE ---
|
||||
1. **Subject:** Formuliere eine kurze Betreffzeile (max. 6 Wörter). Richte sie **direkt an einem der persönlichen Pain Points** des Ansprechpartners oder dem zentralen Branchen-Pain. Sei scharfsinnig, nicht werblich.
|
||||
|
||||
2. **Introduction_Textonly:** Formuliere einen Einleitungstext (2-3 Sätze).
|
||||
- **Satz 1 (Die Brücke):** Knüpfe an die (uns unbekannte) operative Herausforderung an. Beschreibe subtil den Nutzen einer Lösung, ohne das Produkt (Roboter) plump zu nennen.
|
||||
- **Satz 2 (Die Relevanz):** Schaffe die Relevanz für die Zielperson, indem du das Thema mit einem ihrer persönlichen Pain Points verknüpfst (z.B. "Für Sie als {persona.name} ist dabei entscheidend...").
|
||||
2. **Introduction_Textonly:** Formuliere einen prägnanten Einleitungstext (max. 2 Sätze).
|
||||
- **WICHTIG:** Gehe davon aus, dass die spezifische Herausforderung des Kunden bereits im Satz davor [Opener] genannt wurde. **Wiederhole die Herausforderung NICHT.**
|
||||
- **Satz 1 (Die Lösung & der Gain):** Beginne direkt mit der Lösung. Nenne die im Kontext `FOKUS-PRODUKT` definierte **Produktkategorie** (z.B. "automatisierte Reinigungsroboter") und verbinde sie mit dem zentralen Nutzen (Gain) aus den `BRANCHEN-HERAUSFORDERUNGEN`. Beispiel: "Genau hier setzen unsere automatisierten Reinigungsroboter an, indem sie eine lückenlose und auditsichere Hygiene gewährleisten."
|
||||
- **Satz 2 (Die Relevanz):** Stelle die Relevanz für die Zielperson her, indem du einen ihrer `PERSÖNLICHE HERAUSFORDERUNGEN` adressierst. Beispiel: "Für Sie als Infrastruktur-Verantwortlicher bedeutet dies vor allem eine reibungslose Integration in bestehende Abläufe, ohne den Betrieb zu stören."
|
||||
|
||||
3. **Industry_References_Textonly:** Formuliere einen **strategischen Referenz-Block (ca. 2-3 Sätze)** nach folgendem Muster:
|
||||
- **Satz 1 (Social Proof):** Beginne direkt mit dem Nutzen, den vergleichbare Unternehmen in der Branche {industry.name} bereits erzielen. (Erfinde keine Firmennamen, sprich von "Führenden Einrichtungen" oder "Vergleichbaren Häusern").
|
||||
|
||||
@@ -247,10 +247,10 @@ HYGIENE-BEWEISE: <Die 1-2 aussagekräftigsten Sätze als Bullet Points (* Satz 1
|
||||
relevant_gains = extract_segment(raw_gains, "Secondary Product")
|
||||
|
||||
prompt = f"""
|
||||
Du bist ein scharfsinniger Marktbeobachter und Branchenexperte. Formuliere eine wertschätzende Einleitung (genau 2-3 Sätze) für ein Anschreiben an das Unternehmen {company.name}.
|
||||
Du bist ein scharfsinniger Marktbeobachter und Branchenexperte. Formuliere eine prägnante Einleitung (genau 2 Sätze) für ein Anschreiben an das Unternehmen {company.name}.
|
||||
|
||||
DEINE PERSONA:
|
||||
Ein anerkennender Branchenkenner, der eine scharfsinnige Beobachtung teilt. Dein Ton ist wertschätzend, professionell und absolut NICHT verkäuferisch.
|
||||
Ein direkter Branchenkenner, der eine relevante Beobachtung teilt. Dein Ton ist faktenbasiert, professionell und absolut NICHT verkäuferisch. Dein Ziel ist es, schnell zur operativen Herausforderung überzuleiten.
|
||||
|
||||
STRATEGISCHER HINTERGRUND (Nicht nennen!):
|
||||
Dieses Unternehmen wird kontaktiert, weil sein Geschäftsmodell perfekt zu folgendem Bereich passt: "{product_name}" ({product_desc}).
|
||||
@@ -258,10 +258,10 @@ Ziel des Schreibens ist es, die Branchen-Herausforderungen "{relevant_pains}" zu
|
||||
|
||||
DEINE AUFGABE:
|
||||
1. Firmenname kürzen: Kürze "{company.name}" sinnvoll (meist erste zwei Worte). Entferne UNBEDINGT Rechtsformen wie GmbH, AG, gGmbH, e.V. etc.
|
||||
2. Struktur: Genau 2 bis 3 flüssige Sätze.
|
||||
2. Struktur: Genau 2 flüssige Sätze. NICHT MEHR.
|
||||
3. Inhalt:
|
||||
- Satz 1: Eine wertschätzende Beobachtung zum Geschäftsmodell oder einem aktuellen Fokus des Unternehmens (siehe Analyse-Dossier).
|
||||
- Satz 2-3: Leite elegant zu einer spezifischen operativen Herausforderung über, die für das Unternehmen aufgrund seiner Größe oder Branche relevant ist (orientiere dich an "{relevant_pains}").
|
||||
- Satz 1: Eine faktenbasierte, relevante Beobachtung zum Geschäftsmodell oder einem aktuellen Fokus des Unternehmens (siehe Analyse-Dossier). Vermeide Lobhudelei und generische Floskeln.
|
||||
- Satz 2: Leite direkt und prägnant zu einer spezifischen operativen Herausforderung über, die für das Unternehmen aufgrund seiner Größe oder Branche relevant ist (orientiere dich an "{relevant_pains}").
|
||||
4. STRENGES VERBOT: Nenne KEIN Produkt ("{product_name}") und biete KEINE "Lösungen", "Hilfe" oder "Zusammenarbeit" an. Der Text soll eine reine Beobachtung bleiben.
|
||||
5. KEINE Anrede (kein "Sehr geehrte Damen und Herren", kein "Hallo").
|
||||
|
||||
@@ -269,7 +269,7 @@ KONTEXT (Analyse-Dossier):
|
||||
{context_text}
|
||||
|
||||
BEISPIEL-STIL:
|
||||
"Das Kreiskrankenhaus Weilburg leistet einen beeindruckenden Beitrag zur regionalen Patientenversorgung. Bei der lückenlosen Dokumentation und den strengen Hygienevorgaben im Klinikalltag stelle ich mir jedoch die Aufrechterhaltung höchster Standards bei gleichzeitigem Kostendruck als enorme operative Herausforderung vor."
|
||||
"Das Kreiskrankenhaus Weilburg leistet einen bedeutenden Beitrag zur regionalen Patientenversorgung. Bei der lückenlosen Dokumentation und den strengen Hygienevorgaben im Klinikalltag ist die Aufrechterhaltung höchster Standards jedoch eine enorme operative Herausforderung."
|
||||
|
||||
AUSGABE: Nur der fertige Text.
|
||||
"""
|
||||
|
||||
18
list_industries.py
Normal file
18
list_industries.py
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), "company-explorer"))
|
||||
from backend.database import SessionLocal, Industry
|
||||
|
||||
def list_industries():
|
||||
db = SessionLocal()
|
||||
try:
|
||||
industries = db.query(Industry.name).all()
|
||||
print("Available Industries:")
|
||||
for (name,) in industries:
|
||||
print(f"- {name}")
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
list_industries()
|
||||
37
read_matrix_entry.py
Normal file
37
read_matrix_entry.py
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), "company-explorer"))
|
||||
from backend.database import SessionLocal, Industry, Persona, MarketingMatrix
|
||||
|
||||
def read_specific_entry(industry_name: str, persona_name: str):
|
||||
db = SessionLocal()
|
||||
try:
|
||||
entry = (
|
||||
db.query(MarketingMatrix)
|
||||
.join(Industry)
|
||||
.join(Persona)
|
||||
.filter(Industry.name == industry_name, Persona.name == persona_name)
|
||||
.first()
|
||||
)
|
||||
|
||||
if not entry:
|
||||
print(f"No entry found for {industry_name} and {persona_name}")
|
||||
return
|
||||
|
||||
print("--- Generated Text ---")
|
||||
print(f"Industry: {industry_name}")
|
||||
print(f"Persona: {persona_name}")
|
||||
print("\n[Intro]")
|
||||
print(entry.intro)
|
||||
print("\n[Social Proof]")
|
||||
print(entry.social_proof)
|
||||
print("----------------------")
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
read_specific_entry("Healthcare - Hospital", "Infrastruktur-Verantwortlicher")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user