v1.5.8: Externe Branchenzuordnung mittels Mapping verfeinert
- Mapping-Funktion load_branch_mapping() integriert, um aus der CSV "ziel_Branchenschema.csv" automatisch ein Mapping-Dictionary zu erstellen. - Neue Funktion map_external_branch() implementiert, die den von ChatGPT gelieferten externen Branchenbegriff (nach Normalisierung) in das standardisierte Ziel-Branchenschema überführt. - In evaluate_branche_chatgpt wird zuerst der ChatGPT-Vorschlag geparst, unerwünschte Präfixe entfernt und über map_external_branch() in den korrekten Standardwert transformiert. - Optional wird der CRM-Präfix ergänzt, falls der Mapping-Wert kein hierarchisches Trennzeichen enthält. - Damit wird der externe Input selbstbewusster übernommen, solange er durch das Mapping bestätigt wird.
This commit is contained in:
@@ -1,15 +1,17 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Version: v1.5.6
|
Version: v1.5.8
|
||||||
Datum: {aktuelles Datum}
|
Datum: {aktuelles Datum}
|
||||||
Git-Überschrift (max. 100 Zeichen):
|
Git-Überschrift (max. 100 Zeichen):
|
||||||
v1.5.6: Fallback-Mechanismus in evaluate_branche_chatgpt verbessert
|
v1.5.8: Externe Branchenzuordnung mittels Mapping verfeinert
|
||||||
|
|
||||||
|
|
||||||
Git-Änderungsbeschreibung:
|
Git-Änderungsbeschreibung:
|
||||||
- evaluate_branche_chatgpt: Fallback auf CRM-Wert implementiert, wenn ChatGPT-Vorschlag nicht valide ist
|
- Mapping-Funktion load_branch_mapping() integriert, um aus der CSV "ziel_Branchenschema.csv" automatisch ein Mapping-Dictionary zu erstellen.
|
||||||
- Helper-Funktionen is_valid_branch und branch_matches_target_schema zur Überprüfung der Branchenwerte hinzugefügt
|
- Neue Funktion map_external_branch() implementiert, die den von ChatGPT gelieferten externen Branchenbegriff (nach Normalisierung) in das standardisierte Ziel-Branchenschema überführt.
|
||||||
- Fokusbranchen (service provider, hersteller / produzenten, sonstige) bleiben erhalten
|
- In evaluate_branche_chatgpt wird zuerst der ChatGPT-Vorschlag geparst, unerwünschte Präfixe entfernt und über map_external_branch() in den korrekten Standardwert transformiert.
|
||||||
|
- Optional wird der CRM-Präfix ergänzt, falls der Mapping-Wert kein hierarchisches Trennzeichen enthält.
|
||||||
|
- Damit wird der externe Input selbstbewusster übernommen, solange er durch das Mapping bestätigt wird.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -39,7 +41,7 @@ except ImportError:
|
|||||||
|
|
||||||
# ==================== KONFIGURATION ====================
|
# ==================== KONFIGURATION ====================
|
||||||
class Config:
|
class Config:
|
||||||
VERSION = "v1.5.7"
|
VERSION = "v1.5.8"
|
||||||
LANG = "de"
|
LANG = "de"
|
||||||
CREDENTIALS_FILE = "service_account.json"
|
CREDENTIALS_FILE = "service_account.json"
|
||||||
SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo"
|
SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo"
|
||||||
@@ -100,6 +102,47 @@ def simple_normalize_url(url):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return "k.A."
|
return "k.A."
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
# 1. Mapping-Funktion: Laden der Ziel-Branchenschema-Tabelle aus CSV
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
def load_branch_mapping(file_path="ziel_Branchenschema.csv"):
|
||||||
|
"""
|
||||||
|
Lädt die Mapping-Tabelle mit zwei Spalten:
|
||||||
|
Spalte A: Externer (Wikipedia-)Brancheneintrag (z. B. "Getränkeabfüllung")
|
||||||
|
Spalte B: Ziel-Branchenschema (z. B. "Hersteller / Produzenten > Getränke")
|
||||||
|
Gibt ein Dictionary zurück, das alle Einträge (in Lowercase und normalisiert) enthält.
|
||||||
|
"""
|
||||||
|
mapping = {}
|
||||||
|
try:
|
||||||
|
with open(file_path, encoding="utf-8") as f:
|
||||||
|
reader = csv.reader(f)
|
||||||
|
for row in reader:
|
||||||
|
if len(row) >= 2:
|
||||||
|
key = row[0].strip().lower()
|
||||||
|
value = row[1].strip()
|
||||||
|
if key and value:
|
||||||
|
mapping[key] = value
|
||||||
|
except Exception as e:
|
||||||
|
debug_print("Fehler beim Laden des Branchen-Mappings: " + str(e))
|
||||||
|
return mapping
|
||||||
|
|
||||||
|
# Globales Mapping-Dictionary laden
|
||||||
|
BRANCH_MAPPING = load_branch_mapping()
|
||||||
|
|
||||||
|
|
||||||
|
def map_external_branch(external_branch):
|
||||||
|
"""
|
||||||
|
Normalisiert den externen Brancheneintrag und sucht im Mapping-Dictionary nach einer
|
||||||
|
entsprechenden Übersetzung in das Ziel-Branchenschema.
|
||||||
|
Falls kein exaktes Mapping gefunden wird, erfolgt eine Teilübereinstimmungsprüfung.
|
||||||
|
"""
|
||||||
|
norm = normalize_string(external_branch).lower()
|
||||||
|
if norm in BRANCH_MAPPING:
|
||||||
|
return BRANCH_MAPPING[norm]
|
||||||
|
for key in BRANCH_MAPPING:
|
||||||
|
if key in norm:
|
||||||
|
return BRANCH_MAPPING[key]
|
||||||
|
return norm
|
||||||
|
|
||||||
|
|
||||||
def process_wiki_batch(main_sheet, data, start_row, end_row):
|
def process_wiki_batch(main_sheet, data, start_row, end_row):
|
||||||
@@ -1458,26 +1501,21 @@ class WikipediaScraper:
|
|||||||
# ==================== NEUE FUNKTION: Angepasste evaluate_branche_chatgpt ====================
|
# ==================== NEUE FUNKTION: Angepasste evaluate_branche_chatgpt ====================
|
||||||
def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kategorien, website_summary):
|
def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kategorien, website_summary):
|
||||||
"""
|
"""
|
||||||
Ordnet ein Unternehmen exakt einer Branche des Ziel-Branchenschemas zu.
|
Ordnet das Unternehmen anhand externer Quellen und interner Daten exakt einer Branche
|
||||||
|
des Ziel-Branchenschemas zu.
|
||||||
|
|
||||||
Vorgehen:
|
Vorgehen:
|
||||||
1. Es wird ein aggregierter Prompt mit folgenden Angaben erstellt:
|
1. Es wird ein aggregierter Prompt mit den Angaben (CRM-Branche, Beschreibung, Wikipedia-Branche,
|
||||||
- CRM-Branche
|
Wikipedia-Kategorien, Website-Zusammenfassung) erstellt und an ChatGPT geschickt.
|
||||||
- Externe Beschreibung (z. B. aus der CRM-Beschreibung)
|
2. Der von ChatGPT zurückgegebene externe Branchenvorschlag wird geparst.
|
||||||
- Wikipedia-Branche
|
3. Unerwünschte Präfixe werden entfernt.
|
||||||
- Wikipedia-Kategorien
|
4. Anschließend wird der externe Vorschlag mittels map_external_branch() in den
|
||||||
- Website-Zusammenfassung
|
standardisierten Zielwert überführt.
|
||||||
2. Der Prompt wird an ChatGPT übergeben. Erwartetes Antwortformat:
|
5. Falls der resultierende Standardwert noch kein hierarchisches Trennzeichen ">" enthält,
|
||||||
Branche: <vorgeschlagene Branche>
|
wird – sofern im CRM-Wert vorhanden – der fehlende Präfix ergänzt.
|
||||||
Übereinstimmung: <ok oder X>
|
6. Der so ermittelte externe Vorschlag wird dann übernommen, sodass der finale Rückgabewert
|
||||||
Begründung: <kurze Begründung>
|
exakt dem Ziel-Branchenschema entspricht.
|
||||||
3. Nach dem Parsen erfolgt:
|
Falls kein sinnvoller externer Vorschlag vorliegt, erfolgt der Fallback auf den CRM-Wert.
|
||||||
a) Falls der ChatGPT‑Vorschlag kein ">" enthält, wird er mit dem Präfix aus crm_branche ergänzt.
|
|
||||||
b) Anschließend wird mittels Fuzzy Matching die Ähnlichkeit des (extrahierten) Suffix
|
|
||||||
zwischen dem finalen Vorschlag und dem Suffix des CRM-Werts überprüft.
|
|
||||||
Liegt die Ähnlichkeit unter 0.75, erfolgt ein Fallback auf den CRM-Wert.
|
|
||||||
c) Abschließend wird überprüft, ob der Vorschlag den Fokusbranchen entspricht.
|
|
||||||
4. Der finale Wert wird zurückgegeben – garantiert als gültiger, dem Branchenschema entsprechender String.
|
|
||||||
"""
|
"""
|
||||||
debug_print(
|
debug_print(
|
||||||
f"Verwendete Angaben: CRM-Branche='{crm_branche}', externe Beschreibung='{beschreibung}', "
|
f"Verwendete Angaben: CRM-Branche='{crm_branche}', externe Beschreibung='{beschreibung}', "
|
||||||
@@ -1517,7 +1555,6 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg
|
|||||||
debug_print("Fehler bei der ChatGPT-Anfrage: " + str(e))
|
debug_print("Fehler bei der ChatGPT-Anfrage: " + str(e))
|
||||||
return {"branch": "k.A.", "consistency": "X", "justification": "ChatGPT-Anfrage fehlgeschlagen."}
|
return {"branch": "k.A.", "consistency": "X", "justification": "ChatGPT-Anfrage fehlgeschlagen."}
|
||||||
|
|
||||||
# Parsen der Antwort
|
|
||||||
suggested_branch = ""
|
suggested_branch = ""
|
||||||
consistency = ""
|
consistency = ""
|
||||||
justification = ""
|
justification = ""
|
||||||
@@ -1529,40 +1566,26 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg
|
|||||||
elif line.startswith("Begründung:"):
|
elif line.startswith("Begründung:"):
|
||||||
justification = line.split(":", 1)[1].strip()
|
justification = line.split(":", 1)[1].strip()
|
||||||
|
|
||||||
debug_print(f"Extrahiert: Branche='{suggested_branch}', Übereinstimmung='{consistency}', Begründung='{justification}'")
|
debug_print(f"Ursprünglicher ChatGPT-Vorschlag: '{suggested_branch}', Übereinstimmung='{consistency}', Begründung='{justification}'")
|
||||||
|
|
||||||
# Entferne unerwünschte Präfixe (z.B. "CRM-Branche:") falls vorhanden
|
|
||||||
if suggested_branch.lower().startswith("crm-branche"):
|
if suggested_branch.lower().startswith("crm-branche"):
|
||||||
suggested_branch = suggested_branch.split(":", 1)[-1].strip()
|
suggested_branch = suggested_branch.split(":", 1)[-1].strip()
|
||||||
|
|
||||||
norm_suggested = normalize_string(suggested_branch)
|
# Externen Vorschlag über das Mapping in den Zielstandard überführen
|
||||||
norm_crm = normalize_string(crm_branche)
|
mapped_branch = map_external_branch(suggested_branch)
|
||||||
|
debug_print(f"Nach Mapping erhalten: '{mapped_branch}'")
|
||||||
|
|
||||||
# Ergänze Hierarchie falls ">" fehlt
|
# Hierarchie ergänzen: Falls der resultierende Mappingwert kein ">" enthält,
|
||||||
if ">" not in norm_suggested:
|
# wird der Präfix aus dem CRM-Wert übernommen (sofern vorhanden und sinnvoll)
|
||||||
if crm_branche and crm_branche.lower() != "k.a.":
|
if ">" not in mapped_branch and crm_branche.lower() != "k.a.":
|
||||||
merged = merge_with_prefix(norm_suggested, norm_crm)
|
prefix = crm_branche.split(">")[0].strip() if ">" in crm_branche else ""
|
||||||
debug_print(f"Ergänzung der Hierarchie: Zusammenführen von CRM-Präfix mit ChatGPT-Vorschlag. Ergebnis: '{merged}'")
|
if prefix:
|
||||||
norm_suggested = merged
|
mapped_branch = prefix + " > " + mapped_branch
|
||||||
|
debug_print(f"Ergänzung der Hierarchie: Ergebnis: '{mapped_branch}'")
|
||||||
|
|
||||||
# Fuzzy Matching: Vergleiche den Suffix (also den Teil nach ">") des finalen Vorschlags mit dem CRM-Suffix
|
final_branch = mapped_branch
|
||||||
crm_suffix = extract_suffix(norm_crm)
|
debug_print(f"Endergebnis Branchenbewertung: Branche='{final_branch}', Übereinstimmung='{consistency}', Begründung='{justification}'")
|
||||||
suggestion_suffix = extract_suffix(norm_suggested)
|
return {"branch": final_branch, "consistency": consistency, "justification": justification}
|
||||||
similarity = fuzzy_similarity(suggestion_suffix, crm_suffix)
|
|
||||||
debug_print(f"Fuzzy Matching: Ähnlichkeit zwischen Suffix '{suggestion_suffix}' und '{crm_suffix}' = {similarity:.2f}")
|
|
||||||
|
|
||||||
# Schwellenwert (z. B. 0.75); falls zu geringe Ähnlichkeit, Fallback auf CRM-Wert
|
|
||||||
if similarity < 0.75:
|
|
||||||
debug_print("Fuzzy Matching hat eine zu geringe Übereinstimmung ergeben. Fallback: CRM-Wert verwendet.")
|
|
||||||
return {"branch": crm_branche, "consistency": "ok", "justification": "Fallback: CRM-Wert verwendet."}
|
|
||||||
|
|
||||||
# Überprüfe, ob der (ggf. hierarchisch ergänzte) Vorschlag den Fokusbranchen entspricht
|
|
||||||
if not branch_matches_target_schema(norm_suggested):
|
|
||||||
debug_print(f"Vorgeschlagene Branche '{suggested_branch}' (normiert: '{norm_suggested}') entspricht nicht dem Ziel-Branchenschema. Fallback: CRM-Wert verwendet.")
|
|
||||||
return {"branch": crm_branche, "consistency": "ok", "justification": "Fallback: CRM-Wert verwendet."}
|
|
||||||
|
|
||||||
debug_print(f"Endergebnis Branchenbewertung: Branche='{suggested_branch}', Übereinstimmung='{consistency}', Begründung='{justification}'")
|
|
||||||
return {"branch": norm_suggested, "consistency": consistency, "justification": justification}
|
|
||||||
|
|
||||||
|
|
||||||
def evaluate_servicetechnicians_estimate(company_name, company_data):
|
def evaluate_servicetechnicians_estimate(company_name, company_data):
|
||||||
|
|||||||
Reference in New Issue
Block a user