Implementiere ChatGPT-Branchenabgleich & Update Branch Mapping (v1.3.2)
Neue Funktion zur Branchenzuordnung hinzugefügt. ChatGPT bewertet basierend auf CRM, Wikipedia-Daten und Fokusbranchen. Spalten V, W und X werden entsprechend aktualisiert. Versionsnummer wurde auf v1.3.2 aktualisiert.
This commit is contained in:
@@ -14,7 +14,7 @@ import csv
|
||||
|
||||
# ==================== KONFIGURATION ====================
|
||||
class Config:
|
||||
VERSION = "v1.3.1" # v1.3.1: Validierung des Wikipedia-Artikels implementiert
|
||||
VERSION = "v1.3.3" # v1.3.3: Branchenabgleich per ChatGPT integriert, Ziel-Branchenschema inkl. aller gültigen Branchen eingebunden.
|
||||
LANG = "de"
|
||||
CREDENTIALS_FILE = "service_account.json"
|
||||
SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo"
|
||||
@@ -67,7 +67,7 @@ def normalize_company_name(name):
|
||||
]
|
||||
pattern = r'\b(' + '|'.join(forms) + r')\b'
|
||||
normalized = re.sub(pattern, '', name, flags=re.IGNORECASE)
|
||||
normalized = re.sub(r'[\-–]', ' ', normalized)
|
||||
normalized = re.sub(r'[\-–]', ' ', normalized)
|
||||
normalized = re.sub(r'\s+', ' ', normalized).strip()
|
||||
return normalized.lower()
|
||||
|
||||
@@ -161,7 +161,6 @@ def validate_article_with_chatgpt(crm_data, wiki_data):
|
||||
als CSV-Text und übermittelt diesen an die ChatGPT-API, um zu validieren,
|
||||
ob beide Datensätze zum selben Unternehmen gehören.
|
||||
"""
|
||||
# Erstelle den CSV-Text
|
||||
crm_headers = "Firmenname;Website;Ort;Beschreibung;Aktuelle Branche;Beschreibung Branche extern;Anzahl Techniker;Umsatz (CRM);Anzahl Mitarbeiter (CRM)"
|
||||
wiki_headers = "Wikipedia URL;Wikipedia Absatz;Wikipedia Branche;Wikipedia Umsatz;Wikipedia Mitarbeiter;Wikipedia Kategorien"
|
||||
prompt_text = (
|
||||
@@ -169,7 +168,7 @@ def validate_article_with_chatgpt(crm_data, wiki_data):
|
||||
"Die erste Zeile sind Daten aus unserem CRM-System, die zweite Zeile stammen aus Wikipedia. "
|
||||
"Vergleiche insbesondere den Firmennamen, den Ort und die Branche. Unterschiede im Umsatz können toleriert werden, "
|
||||
"solange sie im Rahmen von 10% liegen. Falls die Datensätze übereinstimmen, antworte ausschließlich mit 'OK'. "
|
||||
"Falls nicht, nenne bitte den wichtigsten Grund (z. B. abweichender Firmenname oder Ort). \n\n"
|
||||
"Falls nicht, nenne bitte den wichtigsten Grund (z. B. abweichender Firmenname oder Ort). \n\n"
|
||||
f"CRM-Daten:\n{crm_headers}\n{crm_data}\n\n"
|
||||
f"Wikipedia-Daten:\n{wiki_headers}\n{wiki_data}\n\n"
|
||||
"Antwort: "
|
||||
@@ -194,6 +193,95 @@ def validate_article_with_chatgpt(crm_data, wiki_data):
|
||||
debug_print(f"Fehler beim Validierungs-API-Aufruf: {e}")
|
||||
return "k.A."
|
||||
|
||||
# ==================== BRANCHENABGLEICH PER CHATGPT ====================
|
||||
def load_target_branches():
|
||||
try:
|
||||
with open("ziel_Branchenschema.csv", "r", encoding="utf-8") as csvfile:
|
||||
reader = csv.reader(csvfile)
|
||||
# Annahme: Jede Zeile enthält in der ersten Spalte einen gültigen Branchen-Namen
|
||||
branches = [row[0] for row in reader if row]
|
||||
return branches
|
||||
except Exception as e:
|
||||
debug_print(f"Fehler beim Laden des Ziel-Branchenschemas: {e}")
|
||||
return []
|
||||
|
||||
# Fokusbranchen-Liste (wie definiert)
|
||||
focus_branches = [
|
||||
"Gutachter / Versicherungen > Baugutachter",
|
||||
"Gutachter / Versicherungen > Technische Gutachten",
|
||||
"Gutachter / Versicherungen > Versicherungsgutachten",
|
||||
"Gutachter / Versicherungen > Medizinische Gutachten",
|
||||
"Hersteller / Produzenten > Anlagenbau",
|
||||
"Hersteller / Produzenten > Automaten (Vending, Slot)",
|
||||
"Hersteller / Produzenten > Gebäudetechnik Allgemein",
|
||||
"Hersteller / Produzenten > Gebäudetechnik Heizung, Lüftung, Klima",
|
||||
"Hersteller / Produzenten > Maschinenbau",
|
||||
"Hersteller / Produzenten > Medizintechnik",
|
||||
"Service provider (Dienstleister) > Aufzüge und Rolltreppen",
|
||||
"Service provider (Dienstleister) > Feuer- und Sicherheitssysteme",
|
||||
"Service provider (Dienstleister) > Servicedienstleister / Reparatur ohne Produktion",
|
||||
"Service provider (Dienstleister) > Facility Management",
|
||||
"Versorger > Telekommunikation"
|
||||
]
|
||||
|
||||
def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kategorien):
|
||||
# Lade das Ziel-Branchenschema
|
||||
target_branches = load_target_branches()
|
||||
target_branches_str = "\n".join(target_branches)
|
||||
focus_branches_str = "\n".join(focus_branches)
|
||||
try:
|
||||
with open("api_key.txt", "r") as f:
|
||||
api_key = f.read().strip()
|
||||
except Exception as e:
|
||||
debug_print(f"Fehler beim Lesen des API-Tokens: {e}")
|
||||
return {"branch": "k.A.", "consistency": "k.A.", "justification": "k.A."}
|
||||
openai.api_key = api_key
|
||||
|
||||
system_prompt = (
|
||||
"Du bist ein Experte im Field Service Management. Deine Aufgabe ist es, ein Unternehmen basierend auf folgenden Angaben einer Branche zuzuordnen.\n\n"
|
||||
f"CRM-Branche (Spalte F): {crm_branche}\n"
|
||||
f"Branchenbeschreibung (Spalte G): {beschreibung}\n"
|
||||
f"Wikipedia-Branche (Spalte N): {wiki_branche}\n"
|
||||
f"Wikipedia-Kategorien (Spalte Q): {wiki_kategorien}\n\n"
|
||||
"Das Ziel-Branchenschema umfasst ALLE gültigen Branchen, also sowohl Fokusbranchen als auch weitere Branchen (z. B. 'Housing > Sozialbau Unternehmen').\n"
|
||||
"Das vollständige Ziel-Branchenschema lautet:\n"
|
||||
f"{target_branches_str}\n\n"
|
||||
"Falls das Unternehmen mehreren Branchen zugeordnet werden könnte, wähle bitte bevorzugt eine Branche aus der folgenden Fokusliste, sofern zutreffend:\n"
|
||||
f"{focus_branches_str}\n\n"
|
||||
"Gewichtung der Angaben:\n"
|
||||
"1. Wikipedia-Branche (Spalte N) zusammen mit Wikipedia-Kategorien (Spalte Q) (höchste Priorität, wenn verifiziert)\n"
|
||||
"2. Branchenbeschreibung (Spalte G)\n"
|
||||
"3. CRM-Branche (Spalte F)\n\n"
|
||||
"Ordne das Unternehmen exakt einer der oben genannten Branchen zu (es dürfen keine zusätzlichen Branchen erfunden werden). "
|
||||
"Bitte antworte in folgendem Format (ohne zusätzliche Informationen):\n"
|
||||
"Branche: <vorgeschlagene Branche>\n"
|
||||
"Übereinstimmung: <ok oder X>\n"
|
||||
"Begründung: <kurze Begründung, falls abweichend, ansonsten leer>"
|
||||
)
|
||||
try:
|
||||
response = openai.ChatCompletion.create(
|
||||
model="gpt-3.5-turbo",
|
||||
messages=[{"role": "system", "content": system_prompt}],
|
||||
temperature=0.0
|
||||
)
|
||||
result = response.choices[0].message.content.strip()
|
||||
debug_print(f"Branchenabgleich ChatGPT Antwort: '{result}'")
|
||||
# Parsing der Antwort
|
||||
branch = "k.A."
|
||||
consistency = "k.A."
|
||||
justification = ""
|
||||
for line in result.split("\n"):
|
||||
if line.lower().startswith("branche:"):
|
||||
branch = line.split(":", 1)[1].strip()
|
||||
elif line.lower().startswith("übereinstimmung:"):
|
||||
consistency = line.split(":", 1)[1].strip()
|
||||
elif line.lower().startswith("begründung:"):
|
||||
justification = line.split(":", 1)[1].strip()
|
||||
return {"branch": branch, "consistency": consistency, "justification": justification}
|
||||
except Exception as e:
|
||||
debug_print(f"Fehler beim Aufruf der ChatGPT API für Branchenabgleich: {e}")
|
||||
return {"branch": "k.A.", "consistency": "k.A.", "justification": "k.A."}
|
||||
|
||||
# ==================== GOOGLE SHEET HANDLER ====================
|
||||
class GoogleSheetHandler:
|
||||
def __init__(self):
|
||||
@@ -468,6 +556,7 @@ class DataProcessor:
|
||||
dt_range = f"AH{row_num}"
|
||||
ver_range = f"AI{row_num}"
|
||||
print(f"\n[{datetime.now().strftime('%H:%M:%S')}] Verarbeite Zeile {row_num}: {company_name}")
|
||||
|
||||
article = self.wiki_scraper.search_company_article(company_name, website)
|
||||
if article:
|
||||
company_data = self.wiki_scraper.extract_company_data(article.url)
|
||||
@@ -481,6 +570,7 @@ class DataProcessor:
|
||||
'categories': 'k.A.',
|
||||
'full_infobox': 'k.A.'
|
||||
}
|
||||
|
||||
wiki_values = [
|
||||
"k.A.", # Vorschlag Wiki URL
|
||||
company_data.get('url', 'k.A.'),
|
||||
@@ -492,6 +582,7 @@ class DataProcessor:
|
||||
]
|
||||
self.sheet_handler.sheet.update(values=[wiki_values], range_name=wiki_update_range)
|
||||
time.sleep(1)
|
||||
|
||||
# Umsatz-Schätzung via ChatGPT (wie bisher)
|
||||
wiki_umsatz = company_data.get('umsatz', 'k.A.')
|
||||
if wiki_umsatz != "k.A.":
|
||||
@@ -499,28 +590,45 @@ class DataProcessor:
|
||||
else:
|
||||
chatgpt_umsatz = "k.A."
|
||||
self.sheet_handler.sheet.update(values=[[chatgpt_umsatz]], range_name=chatgpt_range)
|
||||
|
||||
# Umsatz-Abgleich (wie bisher)
|
||||
crm_umsatz = row_data[8] if len(row_data) > 8 else "k.A."
|
||||
abgleich_result = compare_umsatz_values(crm_umsatz, company_data.get('umsatz', 'k.A.'))
|
||||
self.sheet_handler.sheet.update(values=[[abgleich_result]], range_name=abgleich_range)
|
||||
# --- Neuer Validierungsschritt ---
|
||||
# Aggregiere CRM-Daten (B bis J) und Wikipedia-Daten (L bis Q) als CSV-Text
|
||||
|
||||
# Neuer Validierungsschritt (Firmenabgleich) – unverändert
|
||||
crm_data = ";".join(row_data[1:10])
|
||||
wiki_data = ";".join(row_data[11:17])
|
||||
valid_result = validate_article_with_chatgpt(crm_data, wiki_data)
|
||||
self.sheet_handler.sheet.update(values=[[valid_result]], range_name=valid_range)
|
||||
|
||||
# Neuer Branchenabgleich per ChatGPT:
|
||||
crm_branche = row_data[5] if len(row_data) > 5 else "k.A."
|
||||
beschreibung_branche = row_data[6] if len(row_data) > 6 else "k.A."
|
||||
wiki_branche = company_data.get('branche', 'k.A.')
|
||||
wiki_kategorien = company_data.get('categories', 'k.A.')
|
||||
branche_result = evaluate_branche_chatgpt(crm_branche, beschreibung_branche, wiki_branche, wiki_kategorien)
|
||||
|
||||
# Update der Spalten:
|
||||
# Spalte V: Vorschlag neue Branche
|
||||
# Spalte W: Konsistenzprüfung Branche (ok, wenn Übereinstimmung, sonst X)
|
||||
# Spalte X: Begründung bei Abweichung
|
||||
branche_v_range = f"V{row_num}"
|
||||
branche_w_range = f"W{row_num}"
|
||||
branche_x_range = f"X{row_num}"
|
||||
self.sheet_handler.sheet.update(values=[[branche_result["branch"]]], range_name=branche_v_range)
|
||||
self.sheet_handler.sheet.update(values=[[branche_result["consistency"]]], range_name=branche_w_range)
|
||||
self.sheet_handler.sheet.update(values=[[branche_result["justification"]]], range_name=branche_x_range)
|
||||
|
||||
# Timestamp und Version schreiben
|
||||
current_dt = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
self.sheet_handler.sheet.update(values=[[current_dt]], range_name=dt_range)
|
||||
self.sheet_handler.sheet.update(values=[[Config.VERSION]], range_name=ver_range)
|
||||
print(f"✅ Aktualisiert: URL: {company_data.get('url', 'k.A.')}, Absatz: {company_data.get('first_paragraph', 'k.A.')[:30]}..., "
|
||||
f"Branche: {company_data.get('branche', 'k.A.')}, Wikipedia Umsatz: {company_data.get('umsatz', 'k.A.')}, "
|
||||
f"Mitarbeiter: {company_data.get('mitarbeiter', 'k.A.')}, Kategorien: {company_data.get('categories', 'k.A.')}, "
|
||||
f"ChatGPT Umsatz: {chatgpt_umsatz}, Umsatz-Abgleich: {abgleich_result}, Validierung: {valid_result}")
|
||||
if MODE == "2":
|
||||
print("----- Vollständiger Infobox-Inhalt -----")
|
||||
print(company_data.get("full_infobox", "k.A."))
|
||||
print("----------------------------------------")
|
||||
|
||||
print(f"✅ Aktualisiert: URL: {company_data.get('url', 'k.A.')}, "
|
||||
f"Branche: {company_data.get('branche', 'k.A.')}, "
|
||||
f"ChatGPT Umsatz: {chatgpt_umsatz}, Umsatz-Abgleich: {abgleich_result}, "
|
||||
f"Validierung: {valid_result}, Branchenvorschlag: {branche_result['branch']}")
|
||||
time.sleep(Config.RETRY_DELAY)
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -541,4 +649,4 @@ if __name__ == "__main__":
|
||||
num_rows = None
|
||||
processor = DataProcessor()
|
||||
processor.process_rows(num_rows)
|
||||
print(f"\n✅ Wikipedia-Auswertung abgeschlossen ({Config.VERSION})")
|
||||
print(f"\n✅ Wikipedia-Auswertung abgeschlossen ({Config.VERSION})")
|
||||
|
||||
Reference in New Issue
Block a user