From 328525f930ece7088790c08231c125c5f904ef3f Mon Sep 17 00:00:00 2001 From: Floke Date: Tue, 8 Apr 2025 08:36:04 +0000 Subject: [PATCH] v1.4.2 Branchenbewertung im Batch, Wikipedia k.A.-Handling optimiert, Zeilenabfrage in Modus 51 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Alignment Demo (Zeilen A1–AQ5) exakt gemäß der vorgegebenen Ausgangsversion eingebaut. - Im Batch-Prozess (Modus 51) wird jetzt zusätzlich die Branchenbewertung (bis einschließlich Spalte Y) durchgeführt. - Spalte W: Chat Vorschlag Branche - Spalte X: Chat Konsistenz Branche - Spalte Y: Chat Begründung Abweichung Branche - Wenn der extrahierte Wikipedia-Artikel "k.A." enthält, wird nicht erneut nach einem Artikel gesucht; stattdessen bleibt der Wert "k.A.". - Vor Start im Batch (Modus 51) wird abgefragt, wie viele Zeilen verarbeitet werden sollen. - Weitere Schritte im Vollverarbeitungsmodus (insb. Mitarbeiter‑Schätzung und Kontaktsuche) sind vorerst noch nicht vollständig implementiert. --- brancheneinstufung.py | 232 ++++++++++++++++++++---------------------- 1 file changed, 112 insertions(+), 120 deletions(-) diff --git a/brancheneinstufung.py b/brancheneinstufung.py index 7209c295..a51d5b44 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -1,15 +1,19 @@ #!/usr/bin/env python3 """ -Version: v1.4.1 +Version: v1.4.2 Datum: {aktuelles Datum} Git-Überschrift (max. 100 Zeichen): -v1.4.1 Anpassung Spaltenzuordnung, erneute Suche bei k.A. und Zeilenabfrage im Modus 51 +v1.4.2 Branchenbewertung im Batch, Wikipedia k.A.-Handling optimiert, Zeilenabfrage in Modus 51 Git-Änderungsbeschreibung: -- Wikipedia-Daten werden nun von Spalte L bis R geschrieben (statt von K bis Q). -- Falls Wikipedia-Daten "k.A." liefern, wird eine erneute Suche durchgeführt und ChatGPT soll den Artikel recherchieren. -- Im Modus 51 wird nun abgefragt, wieviele Zeilen verarbeitet werden sollen. -- Konsistenzprüfung mit der Alignment Demo sichergestellt. +- Alignment Demo (Zeilen A1–AQ5) exakt gemäß der vorgegebenen Ausgangsversion eingebaut. +- Im Batch-Prozess (Modus 51) wird jetzt zusätzlich die Branchenbewertung (bis einschließlich Spalte Y) durchgeführt. + - Spalte W: Chat Vorschlag Branche + - Spalte X: Chat Konsistenz Branche + - Spalte Y: Chat Begründung Abweichung Branche +- Wenn der extrahierte Wikipedia-Artikel "k.A." enthält, wird nicht erneut nach einem Artikel gesucht; stattdessen bleibt der Wert "k.A.". +- Vor Start im Batch (Modus 51) wird abgefragt, wie viele Zeilen verarbeitet werden sollen. +- Weitere Schritte im Vollverarbeitungsmodus (insb. Mitarbeiter‑Schätzung und Kontaktsuche) sind vorerst noch nicht vollständig implementiert. """ import os @@ -34,7 +38,7 @@ except ImportError: # ==================== KONFIGURATION ==================== class Config: - VERSION = "v1.4.1" # Neue Version mit weiteren Anpassungen + VERSION = "v1.4.2" LANG = "de" CREDENTIALS_FILE = "service_account.json" SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo" @@ -179,7 +183,7 @@ def token_count(text): def prompt_overview(): prompts = [ ["Funktion", "Verwendeter Prompt"], - ["process_wiki_verification", "Bitte verifiziere den Wikipedia-Artikel für {company_name}. Wenn 'k.A.' vorliegt, suche selbstständig nach einem passenden Artikel (return 'Skipped (k.A.)' nur, wenn keine Daten gefunden werden)."], + ["process_wiki_verification", "Bitte verifiziere den Wikipedia-Artikel für {company_name}. Wenn 'k.A.' vorliegt, suche mit den vorliegenden Informationen nach einem passenden Artikel. (Nur 'Skipped (k.A.)', wenn wirklich keine Daten gefunden werden.)"], ["process_employee_estimation", "Schätze die Mitarbeiterzahl für {company_name} basierend auf Wikipedia-Daten. Bei 'k.A.' liefere 'Skipped (k.A.)'."], ["process_employee_consistency", "Vergleiche CRM-, Wiki- und ChatGPT-Mitarbeiterzahlen. Gib die prozentuale Differenz und eine Begründung zurück."], ["evaluate_umsatz_chatgpt", "Schätze den Umsatz in Mio. Euro für {company_name} basierend auf Wikipedia-Daten, antworte nur mit der Zahl."], @@ -197,6 +201,7 @@ def mark_processed(field): # ==================== NEUE FUNKTIONEN FÜR MITARBEITER ==================== def process_employee_estimation(company_name, wiki_first_paragraph, crm_employee): + # Wenn Wikipedia-Daten "k.A." liefern, wird nicht erneut gesucht – der Wert bleibt "k.A.". if wiki_first_paragraph.strip().lower() == "k.a.": return "Skipped (k.A.)" try: @@ -225,7 +230,7 @@ def process_employee_consistency(crm_employee, wiki_employee, chat_employee): # ==================== ALIGNMENT DEMO (Hauptblatt) ==================== def alignment_demo(sheet): new_headers = [ - [ # Zeile 1: Spaltenname + [ # Spaltenname "ReEval Flag", # A "CRM Name", # B "CRM Kurzform", # C @@ -246,7 +251,7 @@ def alignment_demo(sheet): "Wiki Kategorien", # R "Chat Wiki Konsistenzprüfung", # S "Chat Begründung Wiki Inkonsistenz", # T - "process_wiki_verification", # U + "Chat Vorschlag Wiki Artikel", # U "Begründung bei Abweichung", # V "Chat Vorschlag Branche", # W "Chat Konsistenz Branche", # X @@ -270,7 +275,7 @@ def alignment_demo(sheet): "Version", # AP "Tokens" # AQ ], - [ # Zeile 2: Quelle der Daten + [ # Quelle der Daten "CRM", "CRM", "CRM", "CRM", "CRM", "CRM", "CRM", "CRM", "CRM", "CRM", "CRM", "CRM", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "Chat GPT API", "Chat GPT API", "Chat GPT API", "Chat GPT API", "Chat GPT API", @@ -279,106 +284,108 @@ def alignment_demo(sheet): "LinkedIn (via SerpApi)", "LinkedIn (via SerpApi)", "LinkedIn (via SerpApi)", "LinkedIn (via SerpApi)", "System", "System", "System", "System", "System" ], - [ # Zeile 3: Feldkategorie - "Prozess", "Firmenname", "Firmenname", "Website", "Ort", "Beschreibung (Text)", "Branche", - "Branche", "Anzahl Servicetechniker", "Umsatz", "Anzahl Mitarbeiter", "Wikipedia Artikel URL", - "Wikipedia Artikel", "Beschreibung (Text)", "Branche", "Umsatz", "Anzahl Mitarbeiter", - "Kategorien (Text)", "Verifizierung", "Begründung bei Abweichung", "Wikipedia Artikel", - "Wikipedia Artikel", "Branche", "Branche", "Branche", "FSM Relevanz", "FSM Relevanz", - "Anzahl Mitarbeiter", "Anzahl Mitarbeiter", "Anzahl Mitarbeiter", "Anzahl Servicetechniker", - "Anzahl Servicetechniker", "Umsatz", "Umsatz", "Kontakte zur Firma", "Kontakte zur Firma", - "Kontakte zur Firma", "Kontakte zur Firma", "Timestamp", "Timestamp", "Timestamp", + [ # Feldkategorie + "Prozess", "Firmenname", "Firmenname", "Website", "Ort", "Beschreibung (Text)", + "Branche", "Branche", "Anzahl Servicetechniker", "Umsatz", "Anzahl Mitarbeiter", + "Wikipedia Artikel URL", "Wikipedia Artikel", "Beschreibung (Text)", "Branche", + "Umsatz", "Anzahl Mitarbeiter", "Kategorien (Text)", "Verifizierung", + "Begründung bei Abweichung", "Wikipedia Artikel", "Wikipedia Artikel", + "Branche", "Branche", "Branche", "FSM Relevanz", "FSM Relevanz", + "Anzahl Mitarbeiter", "Anzahl Mitarbeiter", "Anzahl Mitarbeiter", + "Anzahl Servicetechniker", "Anzahl Servicetechniker", "Umsatz", "Umsatz", + "Kontakte zur Firma", "Kontakte zur Firma", "Kontakte zur Firma", "Kontakte zur Firma", + "Timestamp", "Timestamp", "Timestamp", "Version des Skripts die verwendet wurde", "ChatGPT Tokens" ], - [ # Zeile 4: Formatbeschreibung + [ # Kurze Beschreibung "Systemspalte, irrelevant für den Prompt. Wird zur manuellen Neuprüfung genutzt.", - "Enthält den Firmennamen, ggf. normalisiert ohne Firmenformen.", + "Enthält den Firmennamen; Normalisierung (Entfernung von Firmenformen) erfolgt bei der Suche.", "Manuell gepflegte Kurzform, meist die ersten 2 Worte.", "Website des Unternehmens.", "Ort des Unternehmens.", "Kurze Beschreibung des Unternehmens.", "Aktuelle Branchenzuweisung gemäß Ziel-Branchenschema.", - "Externe Branchenbeschreibung (z. B. von Dealfront).", + "Externe Branchenbeschreibung (z.B. von Dealfront).", "Recherchierte Anzahl Servicetechniker.", "Umsatz in Mio. € (CRM).", "Anzahl Mitarbeiter (CRM).", "Vorgeschlagene Wikipedia URL (Ausgangspunkt).", "Wikipedia URL (Ergebnis der Suche).", "Erster Absatz des Wikipedia-Artikels.", - "Wikipedia-Branche – für Branchenabgleich.", + "Wikipedia-Branche – für den Branchenabgleich.", "Wikipedia-Umsatz – zur Validierung.", "Wikipedia-Mitarbeiterzahl – zur Validierung.", "Liste der Wikipedia-Kategorien.", - "\"OK\" oder \"X\" – Validierung Wikipedia.", + "\"OK\" oder \"X\" – Ergebnis der Wikipedia-Validierung.", "Begründung bei Inkonsistenz (Wiki).", - "process_wiki_verification: Alternativen Artikel vorschlagen; bei 'k.A.' muss selbst recherchiert werden.", - "Nicht genutzt – evtl. für zukünftige Funktionen.", - "Branchenzuordnung über ChatGPT – immer ausgeben.", - "Vergleich CRM-Branche vs. ChatGPT-Ergebnis (OK/X).", - "Begründung bei Abweichung in der Branchenzuordnung.", - "FSM-Relevanz (OK/X).", + "Chat-Vorschlag Wiki Artikel: Falls kein passender Artikel gefunden, alternativ vorschlagen.", + "Nicht genutzt, evtl. für zukünftige Funktionen.", + "Branchenvorschlag via ChatGPT (alternativer Vorschlag).", + "Vergleich: Übereinstimmung CRM vs. ChatGPT-Branche (OK/X).", + "Begründung bei abweichender Branchenzuordnung.", + "FSM-Relevanz: Bewertung, ob das Unternehmen für FSM geeignet ist (OK/X).", "Begründung zur FSM-Bewertung.", - "Schätzung Mitarbeiterzahl via ChatGPT (nur wenn Wiki-Daten fehlen).", - "Vergleich Mitarbeiterzahl: CRM vs. Wikipedia vs. ChatGPT (OK/X).", - "Begründung bei Abweichung (Prozentdifferenz).", - "Schätzung Servicetechniker via ChatGPT.", - "Begründung bei Abweichung zur Technikerzahl.", + "Schätzung Anzahl Mitarbeiter via ChatGPT (nur falls Wiki-Daten fehlen).", + "Vergleich CRM vs. Wiki vs. ChatGPT Mitarbeiterzahl (OK/X).", + "Begründung bei Mitarbeiterabweichung (Prozentdifferenz).", + "Schätzung Servicetechniker via ChatGPT (in Kategorien, z.B. <50, >100 etc.).", + "Begründung bei Abweichung der Technikerzahl.", "Schätzung Umsatz via ChatGPT.", "Begründung bei Umsatzabweichung.", "Anzahl Kontakte (Serviceleiter) gefunden.", "Anzahl Kontakte (IT-Leiter) gefunden.", "Anzahl Kontakte (Management) gefunden.", "Anzahl Kontakte (Disponent) gefunden.", - "Timestamp Kontaktsuche.", - "Timestamp Wikipedia-Suche.", - "Timestamp ChatGPT-Bewertung.", - "Skriptversion, die das Ergebnis erzeugt hat.", + "Timestamp der Kontaktsuche.", + "Timestamp der Wikipedia-Suche.", + "Timestamp der ChatGPT-Bewertung.", + "Ausgabe der Skriptversion, die das Ergebnis erzeugt hat.", "Token-Zählung (separat pro Modul)." ], - [ # Zeile 5: Aufgabe / Funktion + [ # Aufgabe / Funktion (exakte Vorgabe deiner Ausgangsversion) "Datenquelle", - "CRM-Daten (Firmenname)", - "CRM-Daten (Kurzform)", - "CRM-Daten (Website)", - "CRM-Daten (Ort)", - "CRM-Beschreibung", - "CRM-Branche", - "Externe Branchenbeschreibung", - "CRM-Anzahl Techniker", - "CRM-Umsatz", - "CRM-Anzahl Mitarbeiter", - "CRM Vorschlag Wiki URL (beibehalten, falls vorhanden)", - "Wiki URL (aus Wikipedia-Scraping)", - "Erster Absatz des Wikipedia-Artikels", - "Wikipedia-Branche (zur Validierung der Branchenzuordnung)", - "Wikipedia-Umsatz (zur Validierung)", - "Wikipedia-Mitarbeiterzahl (zur Validierung)", - "Wikipedia-Kategorien (zur weiteren Branchenanalyse)", - "Validierung: Prüft, ob Wikipedia-Daten mit CRM-Daten übereinstimmen (±30% Toleranz)", - "Bei Inkonsistenz: Begründung via ChatGPT (für Wikipedia)", - "process_wiki_verification: Falls kein passender Artikel gefunden oder 'k.A.' geliefert wird, selbstständig recherchieren.", - "Nicht genutzt (Zukunft).", - "Branchenvorschlag via ChatGPT (alternativer Vorschlag)", - "Vergleich: CRM-Branche vs. ChatGPT-Branche (OK/X)", - "Begründung bei Abweichung in der Branchenzuordnung", - "FSM-Relevanz: Bewertung, ob Unternehmen für FSM geeignet ist (OK/X)", - "Begründung zur FSM-Eignung", - "Schätzung Anzahl Mitarbeiter via ChatGPT", - "Vergleich: CRM vs. Wiki vs. ChatGPT (OK/X)", - "Begründung bei Abweichung der Mitarbeiterzahl", - "Schätzung Servicetechniker via ChatGPT (Kategorisierung)", - "Begründung bei Abweichung der Technikerzahl", - "Schätzung Umsatz via ChatGPT", - "Begründung bei Umsatzabweichung", - "LinkedIn-Kontaktsuche: Serviceleiter", - "LinkedIn-Kontaktsuche: IT-Leiter", - "LinkedIn-Kontaktsuche: Management", - "LinkedIn-Kontaktsuche: Disponent", - "Timestamp der Kontaktsuche", - "Timestamp der Wikipedia-Suche", - "Timestamp der ChatGPT-Bewertung", - "Skriptversion", - "Token-Zählung" + "Datenquelle", + "Datenquelle", + "Datenquelle", + "Datenquelle", + "Datenquelle", + "Datenquelle", + "Datenquelle", + "Datenquelle", + "Datenquelle", + "Datenquelle", + "Datenquelle", + "Wird durch Wikipedia Scraper bereitgestellt", + "Wird zunächst nicht verwendet, kann aber in einem späteren Schritt zum Vergleich mit der CRM-Beschreibung genutzt werden.", + "Wird u.a. zur finalen Ermittlung der Branche im Ziel-Branchenschema genutzt und mit der CRM-Branche bzw. CRM-Beschreibung Branche Extern verglichen. Stimmen alle drei Einstufungen grob überein, bestärkt dies die ursprüngliche Einstufung. Laufen diese Branchen weit auseinander, soll – sofern der Wikipedia-Artikel verifiziert ist – die Branche von Wikipedia als zuverlässigste Quelle bewertet werden, danach folgen CRM-Beschreibung Branche Extern und CRM-Branche an dritter Stelle.", + "Wird u.a. mit CRM-Umsatz zur Validierung des Unternehmens verglichen bzw. zur Bewertung der Größe / Einschätzung der Technikerzahl bzw. Relevanz für FSM genutzt.", + "Wird u.a. mit CRM-Anzahl Mitarbeiter zur Validierung des Unternehmens verglichen bzw. zur Bewertung der Größe / Einschätzung der Technikerzahl bzw. FSM-Relevanz genutzt.", + "Wenn Wiki-Branche nicht gepflegt ist, wird dieses Feld zur finalen Ermittlung der Branche im Ziel-Branchenschema genutzt und mit CRM-Branche bzw. CRM-Beschreibung Branche Extern verglichen.", + "\"Es soll durch ChatGPT geprüft werden, ob anhand der vorliegenden Daten bestätigt werden kann, dass der Wikipedia-Eintrag das Unternehmen sicher beschreibt. Dabei können alle Daten (Website, Umsatz, Mitarbeiterzahl etc.) berücksichtigt werden. Eine gewisse Toleranz (±30%) ist erlaubt. Insbesondere bei Konzernstrukturen muss großzügig bewertet werden. Abweichungen sollen in der Spalte 'Chat Begründung Wiki Inkonsistenz' begründet werden.\"", + "\"Liegt eine Inkonsistenz zwischen dem gefundenen Wikipedia-Artikel und dem Unternehmen vor, so soll dies kurz begründet werden. Wurde der Artikel als unpassend identifiziert, soll ChatGPT einen alternativen Wikipedia-Artikel vorschlagen und in Spalte 'Chat Vorschlag Wiki Artikel' ausgeben.\"", + "\"Sollte durch die Wikipedia-Suche kein Artikel gefunden werden oder als unpassend bewertet werden, soll ChatGPT eigenständig nach einem passenden Artikel recherchieren. Der gefundene Artikel muss vom als unpassend bewerteten Artikel abweichen. Wird kein passender Artikel gefunden, soll 'kein Artikel verfügbar' ausgegeben werden.\"", + "XXX derzeit nicht verwendet, wird vermutlich gelöscht xxx", + "\"ChatGPT soll anhand der vorliegenden Informationen prüfen, welcher Branche des Ziel-Branchenschemas das Unternehmen am ehesten zugeordnet werden kann. Das Ziel-Branchenschema darf nicht verändert werden, sondern die Vorschläge müssen exakt diesem Schema entsprechen.\"", + "Die in Spalte CRM festgelegte Branche soll mit der von ChatGPT ermittelten Branche in 'Chat Vorschlag Branche' verglichen werden.", + "Weicht die von ChatGPT ermittelte Branche von der in CRM vorliegenden ab, soll ChatGPT die Abweichung kurz begründen.", + "ChatGPT soll anhand der vorliegenden Daten prüfen, ob das Unternehmen für den Einsatz einer Field Service Management Lösung geeignet ist.", + "Die in 'Chat Begründung für FSM Relevanz' angegebene Begründung soll zur Bewertung der FSM-Eignung herangezogen werden.", + "Nur wenn kein Wikipedia-Eintrag vorhanden ist, soll ChatGPT basierend auf öffentlich verfügbaren Informationen die Mitarbeiterzahl schätzen. Falls keine Schätzung möglich ist, wird 'keine Schätzung möglich' ausgegeben.", + "Entspricht die durch ChatGPT ermittelte Mitarbeiterzahl ungefähr den in CRM und Wikipedia ermittelten Werten (±30%), wird 'OK' ausgegeben, andernfalls 'X' und eine Begründung in 'Chat Begründung Abweichung Mitarbeiterzahl'.", + "Weicht die von ChatGPT geschätzte Mitarbeiterzahl signifikant von den CRM- oder Wikipedia-Werten ab, soll dies kurz begründet werden.", + "ChatGPT soll auf Basis öffentlich zugänglicher Informationen eine Schätzung der Anzahl Servicetechniker abgeben (Kategorisierung: 0, <50, >100, >200, >500). Bei Abweichungen von den recherchierten Werten soll 'X' ausgegeben werden, ansonsten 'OK'.", + "Weicht die von ChatGPT geschätzte Technikerzahl von den CRM-Werten ab, soll dies begründet werden.", + "Nur wenn kein Wikipedia-Eintrag vorhanden ist, soll ChatGPT den Umsatz anhand der Unternehmenswebsite oder anderer Daten schätzen. Bei fehlender Schätzung soll 'keine Schätzung möglich' ausgegeben werden.", + "ChatGPT soll signifikante Umsatzabweichungen zwischen den Schätzungen von Chat, Wikipedia und CRM begründen. Stimmen die Werte (±30%) überein, wird 'OK' ausgegeben.", + "Über SerpAPI wird zusammen mit der in 'CRM Kurzform' enthaltenen Information nach 'Serviceleiter' gesucht.", + "Über SerpAPI wird zusammen mit 'CRM Kurzform' nach 'Leiter IT' etc. gesucht.", + "Über SerpAPI wird zusammen mit 'CRM Kurzform' nach 'Geschäftsführer' etc. gesucht.", + "Über SerpAPI wird zusammen mit 'CRM Kurzform' erneut nach 'Serviceleiter' etc. gesucht.", + "Wenn die Kontaktsuche gestartet wird, wird der erste Eintrag ohne Zeitstempel in dieser Spalte gesucht; Zeilen mit vorhandenem Zeitstempel werden übersprungen.", + "Wenn die Wikipedia-Suche gestartet wird, wird der erste Eintrag ohne Zeitstempel in dieser Spalte gesucht; Zeilen mit vorhandenem Zeitstempel werden übersprungen.", + "Wenn die ChatGPT-Bewertung gestartet wird, wird der erste Eintrag ohne Zeitstempel in dieser Spalte gesucht; Zeilen mit vorhandenem Zeitstempel werden übersprungen.", + "Wird durch das System befüllt", + "Wird durch tiktoken berechnet" ] ] header_range = "A1:AQ5" @@ -578,21 +585,19 @@ class WikipediaScraper: # ==================== VERIFIZIERUNGS-MODUS (Modus 51) ==================== def process_verification_only(rows_limit=None): debug_print("Starte Verifizierungsmodus (Modus 51) im Batch-Prozess...") - # Wenn kein Limit angegeben ist, den Benutzer fragen: if rows_limit is None: try: rows_limit = int(input("Wie viele Zeilen sollen im Batch verarbeitet werden? ")) except Exception: rows_limit = Config.BATCH_SIZE gc = gspread.authorize(ServiceAccountCredentials.from_json_keyfile_name( - Config.CREDENTIALS_FILE, ["https://www.googleapis.com/auth/spreadsheets"])) + Config.CREDENTIALS_FILE, ["https://www.googleapis.com/auth/spreadsheets"])) sh = gc.open_by_url(Config.SHEET_URL) main_sheet = sh.sheet1 data = main_sheet.get_all_values() batch_entries = [] row_indices = [] for i, row in enumerate(data[1:], start=2): - # Bedingung: Wenn Spalte 25 (Index 24) leer ist if len(row) <= 25 or row[24].strip() == "": entry_text = f"Eintrag {i}:\nFirmenname: {row[1] if len(row)>1 else ''}\nCRM-Beschreibung: {row[7] if len(row)>7 else ''}\nWikipedia-URL: {row[11] if len(row)>11 and row[11].strip() not in ['', 'k.A.'] else 'k.A.'}\nWiki-Absatz: {row[12] if len(row)>12 else 'k.A.'}\nWiki-Kategorien: {row[16] if len(row)>16 else 'k.A.'}\n-----\n" batch_entries.append(entry_text) @@ -604,10 +609,8 @@ def process_verification_only(rows_limit=None): return aggregated_prompt = ("Du bist ein Experte in der Verifizierung von Wikipedia-Artikeln für Unternehmen. " "Für jeden der folgenden Einträge prüfe, ob der vorhandene Wikipedia-Artikel (URL, Absatz, Kategorien) plausibel passt. " - "Gib für jeden Eintrag das Ergebnis im Format aus:\nEintrag : \n" - "Dabei gilt:\n- Wenn der Artikel passt, antworte mit 'OK'.\n" - "- Wenn der Artikel unpassend ist, antworte mit 'Alternativer Wikipedia-Artikel vorgeschlagen: | X | '.\n" - "- Wenn kein Artikel gefunden wurde, antworte mit 'Kein Wikipedia-Eintrag vorhanden.'\n\n") + "Gib das Ergebnis für jeden Eintrag im Format aus:\nEintrag : \n" + "Dabei gelten folgende Regeln:\n- Bei Übereinstimmung: 'OK'\n- Bei Nichtübereinstimmung: 'Alternativer Wikipedia-Artikel vorgeschlagen: | X | '\n- Falls kein Artikel gefunden wurde: 'Kein Wikipedia-Eintrag vorhanden.'\n\n") aggregated_prompt += "\n".join(batch_entries) debug_print("Aggregierter Prompt für Verifizierungs-Batch erstellt.") agg_token_count = "n.v." @@ -663,7 +666,15 @@ def process_verification_only(rows_limit=None): main_sheet.update(values=[[wiki_confirm]], range_name=f"S{row_num}") main_sheet.update(values=[[alt_article]], range_name=f"U{row_num}") main_sheet.update(values=[[wiki_explanation]], range_name=f"V{row_num}") - # Aktualisiere zusätzlich Branchenabgleich, Tokens, Timestamps etc. + # Hier: Branchenbewertung hinzufügen (bis Spalte Y) + crm_branch = data[row_num-1][6] if len(data[row_num-1]) > 6 else "k.A." + ext_branch = data[row_num-1][7] if len(data[row_num-1]) > 7 else "k.A." + wiki_branch = data[row_num-1][14] if len(data[row_num-1]) > 14 else "k.A." + wiki_cats = data[row_num-1][17] if len(data[row_num-1]) > 17 else "k.A." + branch_result = evaluate_branche_chatgpt(crm_branch, ext_branch, wiki_branch, wiki_cats) + main_sheet.update(values=[[branch_result["branch"]]], range_name=f"W{row_num}") + main_sheet.update(values=[[branch_result["consistency"]]], range_name=f"X{row_num}") + main_sheet.update(values=[[branch_result["justification"]]], range_name=f"Y{row_num}") current_dt = datetime.now().strftime("%Y-%m-%d %H:%M:%S") main_sheet.update(values=[[current_dt]], range_name=f"AO{row_num}") main_sheet.update(values=[[Config.VERSION]], range_name=f"AP{row_num}") @@ -711,7 +722,7 @@ class DataProcessor: if len(row) <= 40 or row[40].strip() == "": self._process_single_row(i, row, process_wiki=False, process_chatgpt=True) elif MODE == "51": - process_verification_only() # Es wird nun immer nach der Anzahl der zu verarbeitenden Zeilen gefragt. + process_verification_only() elif MODE == "8": process_batch_token_count() else: @@ -728,7 +739,7 @@ class DataProcessor: def _process_single_row(self, row_num, row_data, process_wiki=True, process_chatgpt=True): company_name = row_data[1] if len(row_data) > 1 else "" website = row_data[2] if len(row_data) > 2 else "" - # Wir wollen die Wikipedia-Daten in Spalte L bis R schreiben + # Wikipedia-Daten werden in Spalte L bis R geschrieben wiki_update_range = f"L{row_num}:R{row_num}" dt_wiki_range = f"AN{row_num}" # Wikipedia Timestamp dt_chat_range = f"AO{row_num}" # ChatGPT Timestamp @@ -736,10 +747,9 @@ class DataProcessor: print(f"\n[{datetime.now().strftime('%H:%M:%S')}] Verarbeite Zeile {row_num}: {company_name}") current_dt = datetime.now().strftime("%Y-%m-%d %H:%M:%S") company_data = {} - # Wikipedia-Verarbeitung (nur, wenn Timestamp noch nicht gesetzt) + # Wikipedia-Verarbeitung: Falls Timestamp nicht gesetzt if process_wiki: if len(row_data) <= 39 or row_data[39].strip() == "": - # Falls CRM Vorschlag Wiki URL bereits vorhanden ist, nutze diesen Wert aus Spalte L (row_data[11]) if len(row_data) > 11 and row_data[11].strip() not in ["", "k.A."]: wiki_url = row_data[11].strip() try: @@ -759,21 +769,8 @@ class DataProcessor: 'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'categories': 'k.A.', 'full_infobox': 'k.A.' } - # Wenn der ermittelte first_paragraph "k.A." liefert, versuche erneut, einen Artikel zu suchen! - if company_data.get('first_paragraph', 'k.A.').strip().lower() == "k.a.": - debug_print("Wikipedia first_paragraph zeigt 'k.A.' – starte erneute Suche...") - article = self.wiki_scraper.search_company_article(company_name, website) - if article: - company_data = self.wiki_scraper.extract_company_data(article.url) - else: - company_data = { - 'url': 'k.A.', 'first_paragraph': 'k.A.', 'branche': 'k.A.', - 'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'categories': 'k.A.', - 'full_infobox': 'k.A.' - } - # Zusammenstellen der 7 Werte: - # 0: CRM Vorschlag Wiki URL (bestehend aus row_data[11]), - # 1: Wiki URL, 2: Wiki Absatz, 3: Wiki Branche, 4: Wiki Umsatz, 5: Wiki Mitarbeiter, 6: Wiki Kategorien + # Hier: _NICHT_ erneut suchen, wenn first_paragraph "k.A." ist – wir belassen diesen Wert, + # sodass später ChatGPT via process_wiki_verification alternative Vorschläge liefern kann. wiki_values = [ row_data[11] if len(row_data) > 11 and row_data[11].strip() not in ["", "k.A."] else "k.A.", company_data.get('url', 'k.A.'), @@ -795,7 +792,6 @@ class DataProcessor: self.sheet_handler.sheet.update(values=[[abgleich_result]], range_name=f"AG{row_num}") crm_data = ";".join(row_data[1:10]) wiki_data_str = ";".join(row_data[11:18]) - # Umbenennung: validate_article_with_chatgpt -> process_wiki_verification valid_result = process_wiki_verification(crm_data, wiki_data_str) self.sheet_handler.sheet.update(values=[[valid_result]], range_name=f"R{row_num}") fsm_result = evaluate_fsm_suitability(company_name, company_data) @@ -819,7 +815,6 @@ class DataProcessor: self.sheet_handler.sheet.update(values=[[emp_consistency]], range_name=f"AC{row_num}") revenue_result = evaluate_umsatz_chatgpt(company_name, company_data.get('umsatz', 'k.A.')) self.sheet_handler.sheet.update(values=[[revenue_result]], range_name=f"AG{row_num}") - # Token-Zählung pro Modul wiki_tokens = token_count(str(company_data.get('first_paragraph', ''))) chat_tokens = token_count(crm_data + wiki_data_str) emp_tokens = token_count(str(emp_estimate)) @@ -830,10 +825,7 @@ class DataProcessor: debug_print(f"Zeile {row_num}: ChatGPT-Timestamp bereits gesetzt – überspringe ChatGPT-Auswertung.") self.sheet_handler.sheet.update(values=[[current_dt]], range_name=ver_range) self.sheet_handler.sheet.update(values=[[Config.VERSION]], range_name=ver_range) - debug_print(f"✅ Aktualisiert: URL: {company_data.get('url', 'k.A.')}, " - f"Branche: {company_data.get('branche', 'k.A.')}, Umsatz-Abgleich: {abgleich_result}, " - f"Validierung: {valid_result}, FSM: {fsm_result['suitability']}, " - f"Servicetechniker-Schätzung: {st_estimate}") + debug_print(f"✅ Aktualisiert: URL: {company_data.get('url', 'k.A.')}, Branche: {company_data.get('branche', 'k.A.')}, Umsatz-Abgleich: {abgleich_result}, Validierung: {valid_result}, FSM: {fsm_result['suitability']}, Servicetechniker-Schätzung: {st_estimate}") time.sleep(Config.RETRY_DELAY) # ==================== ALIGNMENT DEMO FÜR HAUPTBLATT UND CONTACTS ==================== @@ -975,8 +967,8 @@ def process_wiki_verification(crm_data, wiki_data_str): prompt_text = ( "Bitte überprüfe, ob die folgenden beiden Datensätze grundsätzlich zum gleichen Unternehmen gehören. " "Vergleiche insbesondere den Firmennamen, den Ort und die Branche. " - "Antworte mit 'OK', wenn die Daten übereinstimmen. Falls nicht, gib eine kurze Begründung aus. " - "Falls ein Wikipedia-Artikel mit 'k.A.' geliefert wird, ignoriere ihn und antworte mit 'Skipped (k.A.)'.\n\n" + "Antworte mit 'OK', wenn die Daten übereinstimmen, andernfalls gib eine kurze Begründung aus. " + "Falls in den Wikipedia-Daten 'k.A.' steht, soll ChatGPT auf Basis der vorliegenden Informationen einen alternativen Artikel vorschlagen.\n\n" f"CRM-Daten:\n{crm_data}\n\n" f"Wikipedia-Daten:\n{wiki_data_str}\n\n" "Antwort: " @@ -1127,8 +1119,7 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg f"Wikipedia-Branche (Spalte N): {wiki_branche}\n" f"Wikipedia-Kategorien (Spalte Q): {wiki_kategorien}\n\n" + additional_instruction + - "Das Ziel-Branchenschema umfasst ALLE gültigen Branchen. " - "Ordne das Unternehmen exakt einer Branche zu. " + "Das Ziel-Branchenschema umfasst ALLE gültigen Branchen. Ordne das Unternehmen exakt einer Branche zu. " "Antworte im Format:\nBranche: \nÜbereinstimmung: \nBegründung: ." ) try: @@ -1230,6 +1221,7 @@ def process_batch_token_count(): time.sleep(Config.RETRY_DELAY) debug_print("Batch Token Count abgeschlossen.") + # ==================== MAIN-FUNKTION ==================== def main(): global MODE, LOG_FILE