diff --git a/brancheneinstufung.py b/brancheneinstufung.py index 569d5e98..8ffb1991 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -14,11 +14,11 @@ import csv try: import tiktoken except ImportError: - tiktoken = None # Falls tiktoken nicht installiert ist + tiktoken = None # ==================== KONFIGURATION ==================== class Config: - VERSION = "v1.3.15" # v1.3.15: Modus 51 für verifizierte Wikipedia-Artikel in Batches, Ausgabe in Spalten W, X, Y und Token-Zahl in AQ. + VERSION = "v1.3.16" # v1.3.16: Modus 51 implementiert mit separaten Spalten für Wiki-Confirm, alternative Wiki URL, Branchenvorschlag etc. LANG = "de" CREDENTIALS_FILE = "service_account.json" SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo" @@ -29,8 +29,8 @@ class Config: DEBUG = True WIKIPEDIA_SEARCH_RESULTS = 5 HTML_PARSER = "html.parser" - BATCH_SIZE = 10 # Batch-Größe für Verifizierungsmodus - TOKEN_MODEL = "gpt-3.5-turbo" # Für tiktoken + BATCH_SIZE = 10 + TOKEN_MODEL = "gpt-3.5-turbo" # ==================== RETRY-DECORATOR ==================== def retry_on_failure(func): @@ -212,7 +212,7 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg f"Wikipedia-Kategorien: {wiki_kategorien}\n\n" "Gib aus:\n" "Branche: \n" - "Übereinstimmung: \n" + "Konsistenz: \n" "Begründung: " ) try: @@ -236,7 +236,7 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg for line in result.split("\n"): if line.lower().startswith("branche:"): branch = line.split(":", 1)[1].strip() - elif line.lower().startswith("übereinstimmung:"): + elif line.lower().startswith("konsistenz:"): consistency = line.split(":", 1)[1].strip() elif line.lower().startswith("begründung:"): justification = line.split(":", 1)[1].strip() @@ -246,15 +246,12 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg return {"branch": "k.A.", "consistency": "k.A.", "justification": "k.A."} def evaluate_fsm_suitability(company_name, company_data): - # In Modus 51 wird diese Funktion nicht aufgerufen. return {"suitability": "n.v.", "justification": ""} def evaluate_servicetechnicians_estimate(company_name, company_data): - # In Modus 51 wird diese Funktion nicht aufgerufen. return "n.v." def evaluate_servicetechnicians_explanation(company_name, st_estimate, company_data): - # In Modus 51 wird diese Funktion nicht aufgerufen. return "n.v." def map_internal_technicians(value): @@ -291,7 +288,6 @@ def search_linkedin_contact(company_name, website, position_query): except Exception as e: debug_print("Fehler beim Lesen des SerpAPI-Schlüssels: " + str(e)) return None - # Nutze ggf. die Kurzform aus Spalte C, falls vorhanden. search_name = company_name query = f'site:linkedin.com/in "{position_query}" "{search_name}"' debug_print(f"Erstelle LinkedIn-Query: {query}") @@ -368,16 +364,15 @@ def count_linkedin_contacts(company_name, website, position_query): # ==================== VERIFIZIERUNGS-MODUS (Modus 51) ==================== def _process_verification_row(row_num, row_data): """ - Aggregiert die relevanten Informationen eines Eintrags für die Verifizierung. - Erwartete Spalten (0-basiert): - B: Firmenname - F: CRM-Beschreibung - M: Wiki URL - N: Wiki Absatz - R: Wiki Kategorien + Aggregiert relevante Informationen für die Verifizierung: + - Firmenname (Spalte B) + - CRM-Beschreibung (Spalte G) + - Wikipedia-URL (Spalte M) + - Wikipedia-Absatz (Spalte N) + - Wikipedia-Kategorien (Spalte R) """ company_name = row_data[1] if len(row_data) > 1 else "" - crm_description = row_data[5] if len(row_data) > 5 else "" + crm_description = row_data[6] if len(row_data) > 6 else "" wiki_url = row_data[12] if len(row_data) > 12 else "k.A." wiki_absatz = row_data[13] if len(row_data) > 13 else "k.A." wiki_categories = row_data[17] if len(row_data) > 17 else "k.A." @@ -392,15 +387,17 @@ def _process_verification_row(row_num, row_data): def process_verification_only(): """ - Verifizierungsmodus (Modus 51) im Batch-Prozess. - Es werden jeweils Config.BATCH_SIZE (z.B. 10) Einträge aggregiert. - Für jeden Eintrag werden folgende Spalten aktualisiert: - - Spalte W: Branchenvorschlag von ChatGPT - - Spalte X: Konsistenzprüfung (OK oder X) - - Spalte Y: Begründung bei Abweichung - - Spalte AQ: Token-Zahl des aggregierten Prompts (gleich für alle Einträge des Batches) - - Spalte Z: Verifizierungs-Timestamp - - Spalte AA: Version + Modus 51: Verifizierung (Wikipedia + Brancheneinordnung) im Batch-Modus. + Verarbeitet jeweils Config.BATCH_SIZE Einträge, bei denen noch keine Wiki-Verifizierung (Spalte S) vorliegt. + Ergebnisse: + - Spalte S: Wiki Confirm (OK, falls Artikel passt) + - Spalte U: Alternative Wiki-URL (falls Artikel nicht passt oder keiner gefunden wurde) + - Spalte V: Erklärung (Begründung) + - Spalte W: Branchenvorschlag (ChatGPT, basierend auf Spalten G, H, O, R) + - Spalte Y: Branchenkonsistenz (OK oder X inkl. Begründung) + - Spalte AQ: Token Count des Batch-Prompts (gleich für alle Einträge) + - Spalte AO: Verifizierungs-Timestamp + - Spalte AP: Versionsnummer """ debug_print("Starte Verifizierungsmodus (Modus 51) im Batch-Prozess...") gc = gspread.authorize(ServiceAccountCredentials.from_json_keyfile_name( @@ -411,9 +408,9 @@ def process_verification_only(): batch_size = Config.BATCH_SIZE batch_entries = [] row_indices = [] - # Wir prüfen hier Spalte Y (Index 24); wenn leer, dann ist der Eintrag noch nicht verifiziert. + # Prüfe Spalte S (Index 18): wenn leer, verarbeite for i, row in enumerate(data[1:], start=2): - if len(row) <= 25 or row[24].strip() == "": + if len(row) <= 19 or row[18].strip() == "": entry_text = _process_verification_row(i, row) batch_entries.append(entry_text) row_indices.append(i) @@ -422,17 +419,16 @@ def process_verification_only(): if not batch_entries: debug_print("Keine Einträge für die Verifizierung gefunden.") return - - aggregated_prompt = ("Du bist ein Experte im Bereich Unternehmensverifizierung. " - "Für jeden der folgenden Einträge prüfe, ob der vorhandene Wikipedia-Artikel (URL, Absatz, Kategorien) plausibel zum Unternehmen passt. " - "Falls ja, antworte für den Eintrag im Format:\n" - "Eintrag X: OK\n" - "Falls nein, schlage einen alternativen Wikipedia-Artikel vor (als URL) und gib die Gründe an, " - "aber gib nicht denselben Artikel zurück, der bereits vorliegt. " - "Wenn kein Artikel gefunden werden kann, antworte mit 'k.A.'\n\n") + 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 an:\n" + "Eintrag : \n" + "Dabei gilt:\n" + "- Wenn der Artikel passt, antworte mit 'OK'.\n" + "- Wenn der Artikel nicht passt, antworte mit 'Alternativer Wikipedia-Artikel vorgeschlagen: | X | '.\n" + "- Falls überhaupt kein Artikel gefunden wurde, antworte mit 'Kein Wikipedia-Eintrag vorhanden.'\n\n") aggregated_prompt += "\n".join(batch_entries) debug_print("Aggregierter Prompt für Verifizierungs-Batch erstellt.") - # Zähle die Token (falls tiktoken verfügbar) token_count = "n.v." if tiktoken: try: @@ -441,7 +437,6 @@ def process_verification_only(): debug_print(f"Token-Zahl für Batch: {token_count}") except Exception as e: debug_print(f"Fehler beim Token-Counting: {e}") - # Sende den aggregierten Prompt an ChatGPT try: with open("api_key.txt", "r") as f: api_key = f.read().strip() @@ -460,8 +455,6 @@ def process_verification_only(): except Exception as e: debug_print(f"Fehler bei der ChatGPT Anfrage für Verifizierung: {e}") return - - # Wir erwarten, dass ChatGPT für jeden Eintrag eine Zeile liefert im Format "Eintrag X: " answers = result.split("\n") for idx, row_num in enumerate(row_indices): answer = "k.A." @@ -469,23 +462,45 @@ def process_verification_only(): if line.strip().startswith(f"Eintrag {row_num}:"): answer = line.split(":", 1)[1].strip() break - # Falls die Antwort "OK" lautet, setze in Spalte X "OK" und Spalte Y leer; - # ansonsten in Spalte X "X" und Spalte Y den Vorschlag. + # Verarbeitung der Wiki-Verifizierung: + # Falls Antwort "OK", schreibe in Spalte S (Wiki Confirm) "OK", Spalte U bleibt leer. + # Falls Antwort "Kein Wikipedia-Eintrag vorhanden.", schreibe diesen Text in Spalte U. + # Falls Antwort mit "Alternativer Wikipedia-Artikel vorgeschlagen:" beginnt, extrahiere URL und Begründung. if answer.upper() == "OK": - branch_suggestion = "OK" - consistency = "OK" - justification = "" + wiki_confirm = "OK" + alt_article = "" + explanation = "" + elif answer.startswith("Alternativer Wikipedia-Artikel vorgeschlagen:"): + parts = answer.split(":", 1)[1].split("|") + alt_article = parts[0].strip() if len(parts) > 0 else "k.A." + explanation = parts[2].strip() if len(parts) > 2 else "" + wiki_confirm = "X" + elif answer.upper() == "KEIN WIKIPEDIA-EINTRAG VORHANDEN.": + wiki_confirm = "" + alt_article = "Kein Wikipedia-Eintrag vorhanden." + explanation = "" else: - branch_suggestion = answer # hier wird der alternative Artikel (URL) als Vorschlag verwendet - consistency = "X" - justification = answer # oder ggf. eine ausführlichere Begründung; hier wird derselbe Text genutzt - main_sheet.update(values=[[branch_suggestion]], range_name=f"W{row_num}") - main_sheet.update(values=[[consistency]], range_name=f"X{row_num}") - main_sheet.update(values=[[justification]], range_name=f"Y{row_num}") - # Schreibe den Token-Count in Spalte AQ (gleich für alle Einträge dieses Batches) + wiki_confirm = "" + alt_article = answer + explanation = answer + # Schreibe Ergebnisse: + 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=[[explanation]], range_name=f"V{row_num}") + # Branchenvorschlag: Nutze die Branchenangaben aus Spalte G, H, O, R (Indices 6,7,14,17) + crm_branch = row_data[6] if len(row_data) > 6 else "k.A." + ext_branch = row_data[7] if len(row_data) > 7 else "k.A." + wiki_branch = row_data[14] if len(row_data) > 14 else "k.A." + wiki_cats = row_data[17] if len(row_data) > 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"Y{row_num}") + # Schreibe Token Count in Spalte AQ main_sheet.update(values=[[str(token_count)]], range_name=f"AQ{row_num}") - main_sheet.update(values=[[datetime.now().strftime('%Y-%m-%d %H:%M:%S')]], range_name=f"Z{row_num}") - main_sheet.update(values=[[Config.VERSION]], range_name=f"AA{row_num}") + # Schreibe Timestamp in Spalte AO und Version in Spalte AP + 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}") debug_print(f"Zeile {row_num} verifiziert: Antwort: {answer}") time.sleep(Config.RETRY_DELAY) debug_print("Verifizierungs-Batch abgeschlossen.") @@ -501,9 +516,10 @@ class GoogleSheetHandler: creds = ServiceAccountCredentials.from_json_keyfile_name(Config.CREDENTIALS_FILE, scope) self.sheet = gspread.authorize(creds).open_by_url(Config.SHEET_URL).sheet1 self.sheet_values = self.sheet.get_all_values() - def get_start_index(self, column_index=39): + def get_start_index(self, column_index=40): """ - column_index=39 für Wiki (Spalte AN), column_index=40 für ChatGPT (Spalte AO) + column_index=40 für ChatGPT-Timestamp (Spalte AO), + column_index=41 für alternative Runner. """ filled_n = [row[column_index] if len(row) > column_index else '' for row in self.sheet_values[1:]] return next((i + 1 for i, v in enumerate(filled_n, start=1) if not str(v).strip()), len(filled_n) + 1) @@ -529,30 +545,30 @@ def alignment_demo(sheet): "Spalte P (Wikipedia Umsatz)", "Spalte Q (Wikipedia Mitarbeiter)", "Spalte R (Wikipedia Kategorien)", - "Spalte S (Konsistenzprüfung)", - "Spalte T (Begründung bei Inkonsistenz)", - "Spalte U (Vorschlag Wiki Artikel ChatGPT)", - "Spalte V (Konsistenzprüfung Branche)", - "Spalte W (Vorschlag neue Branche)", # Wird in Modus 51 als Branchenvorschlag genutzt - "Spalte X (Konsistenzprüfung – OK oder X)", - "Spalte Y (Begründung Abweichung)", - "Spalte Z (Timestamp Verifizierung)", - "Spalte AA (Version)", - "Spalte AB (Schätzung Anzahl Mitarbeiter)", - "Spalte AC (Konsistenzprüfung Mitarbeiterzahl)", - "Spalte AD (Einschätzung Anzahl Servicetechniker)", - "Spalte AE (Begründung bei Abweichung Techniker)", - "Spalte AF (Schätzung Umsatz ChatGPT)", - "Spalte AG (Begründung Umsatz ChatGPT)", - "Spalte AH (Wikipedia-Timestamp)", - "Spalte AI (ChatGPT-Timestamp)", + "Spalte S (Wiki Confirm)", + "Spalte T (Wiki Erklärung – nicht genutzt)", + "Spalte U (Alternative Wiki URL)", + "Spalte V (Wiki Begründung)", + "Spalte W (Branchenvorschlag)", + "Spalte X (Branchenergebnis – Konsistenzprüfung)", + "Spalte Y (Branchenerklärung)", + "Spalte Z (Timestamp – wird nicht genutzt)", + "Spalte AA (FSM Relevanz – nicht genutzt)", + "Spalte AB (Begründung FSM – nicht genutzt)", + "Spalte AC (Schätzung Mitarbeiter – nicht genutzt)", + "Spalte AD (Einschätzung Techniker – nicht genutzt)", + "Spalte AE (Begründung Techniker – nicht genutzt)", + "Spalte AF (Schätzung Umsatz ChatGPT – nicht genutzt)", + "Spalte AG (Begründung Umsatz ChatGPT – nicht genutzt)", + "Spalte AH (Wikipedia-Timestamp – nicht genutzt)", + "Spalte AI (ChatGPT-Timestamp – nicht genutzt)", "Spalte AJ (Kontakt: Serviceleiter gefunden)", "Spalte AK (Kontakt: IT-Leiter gefunden)", "Spalte AL (Kontakt: Management gefunden)", "Spalte AM (Kontakt: Disponent gefunden)", - "Spalte AN (Contact Search Timestamp)", - "Spalte AO (Wikipedia Timestamp – für regulären Wiki-Runner)", - "Spalte AP (ChatGPT Timestamp – für regulären ChatGPT-Runner)", + "Spalte AN (Contact Search Timestamp – nicht genutzt)", + "Spalte AO (Verifizierung Timestamp)", + "Spalte AP (Version)", "Spalte AQ (Token Count Batch)" ] header_range = "A11200:AQ11200" @@ -741,74 +757,71 @@ class WikipediaScraper: continue return None -# ==================== DATA PROCESSOR ==================== -class DataProcessor: +# ==================== GOOGLE SHEET HANDLER ==================== +class GoogleSheetHandler: def __init__(self): - self.sheet_handler = GoogleSheetHandler() - self.wiki_scraper = WikipediaScraper() - def process_rows(self, num_rows=None): - if MODE == "2": - print("Re-Evaluierungsmodus: Verarbeitung aller Zeilen mit 'x' in Spalte A.") - for i, row in enumerate(self.sheet_handler.sheet_values[1:], start=2): - if row[0].strip().lower() == "x": - self._process_single_row(i, row) - elif MODE == "3": - print("Alignment-Demo-Modus: Schreibe neue Spaltenüberschriften in Zeile 11200.") - alignment_demo(self.sheet_handler.sheet) - else: - start_index = self.sheet_handler.get_start_index(40) # Standardmäßig ChatGPT-Timestamp (Spalte AO) - print(f"Starte bei Zeile {start_index+1}") - rows_processed = 0 - for i, row in enumerate(self.sheet_handler.sheet_values[1:], start=2): - if i < start_index: - continue - if num_rows is not None and rows_processed >= num_rows: - break - self._process_single_row(i, row) - rows_processed += 1 - def _process_single_row(self, row_num, row_data): - company_name = row_data[1] if len(row_data) > 1 else "" - website = row_data[3] if len(row_data) > 3 else "" - wiki_update_range = f"L{row_num}:R{row_num}" # Angenommen, hier kommen Wiki-Daten rein - # Falls in Spalte L bereits ein Wiki-URL steht, nutze diese - if len(row_data) > 11 and row_data[11].strip() not in ["", "k.A."]: - wiki_url = row_data[11].strip() - try: - company_data = self.wiki_scraper.extract_company_data(wiki_url) - except Exception as e: - debug_print(f"Fehler beim Laden des vorgeschlagenen Wikipedia-Artikels: {e}") - article = self.wiki_scraper.search_company_article(company_name, website) - company_data = self.wiki_scraper.extract_company_data(article.url) if article else { - 'url': 'k.A.', 'first_paragraph': 'k.A.', 'branche': 'k.A.', - 'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'categories': 'k.A.', - 'full_infobox': 'k.A.' - } - else: - article = self.wiki_scraper.search_company_article(company_name, website) - company_data = self.wiki_scraper.extract_company_data(article.url) if article else { - 'url': 'k.A.', 'first_paragraph': 'k.A.', 'branche': 'k.A.', - 'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'categories': 'k.A.', - 'full_infobox': 'k.A.' - } - wiki_values = [ - company_data.get('url', 'k.A.'), - company_data.get('first_paragraph', 'k.A.'), - company_data.get('branche', 'k.A.'), - company_data.get('umsatz', 'k.A.'), - company_data.get('mitarbeiter', 'k.A.'), - company_data.get('categories', 'k.A.') - ] - self.sheet_handler.sheet.update(values=[wiki_values], range_name=wiki_update_range) - time.sleep(3) - # Weitere Verarbeitung (z.B. Umsatz-Abgleich, Brancheneinordnung etc.) würden hier erfolgen, - # aber im regulären Modus 1 werden auch FSM und Techniker verarbeitet – das ist hier nicht Teil von Modus 51. - # Deshalb bleibt dieser Teil unberührt. - current_dt = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - # Aktualisiere Timestamp und Version in den entsprechenden Spalten (z.B. in Spalte AP für ChatGPT-Timestamp) - self.sheet_handler.sheet.update(values=[[current_dt]], range_name=f"AP{row_num}") - self.sheet_handler.sheet.update(values=[[Config.VERSION]], range_name=f"AQ{row_num}") - debug_print(f"Zeile {row_num} verarbeitet.") - time.sleep(Config.RETRY_DELAY) + self.sheet = None + self.sheet_values = [] + self._connect() + def _connect(self): + scope = ["https://www.googleapis.com/auth/spreadsheets"] + creds = ServiceAccountCredentials.from_json_keyfile_name(Config.CREDENTIALS_FILE, scope) + self.sheet = gspread.authorize(creds).open_by_url(Config.SHEET_URL).sheet1 + self.sheet_values = self.sheet.get_all_values() + def get_start_index(self, column_index=40): + filled_n = [row[column_index] if len(row) > column_index else '' for row in self.sheet_values[1:]] + return next((i + 1 for i, v in enumerate(filled_n, start=1) if not str(v).strip()), len(filled_n) + 1) + +# ==================== ALIGNMENT DEMO (Modus 3) ==================== +def alignment_demo(sheet): + new_headers = [ + "Spalte A (ReEval Flag)", + "Spalte B (Firmenname)", + "Spalte C (Kurzform Firmenname)", + "Spalte D (Website)", + "Spalte E (Ort)", + "Spalte F (Beschreibung)", + "Spalte G (Aktuelle Branche)", + "Spalte H (Beschreibung Branche extern)", + "Spalte I (Anzahl Techniker CRM)", + "Spalte J (Umsatz CRM)", + "Spalte K (Anzahl Mitarbeiter CRM)", + "Spalte L (Vorschlag Wiki URL)", + "Spalte M (Wikipedia URL)", + "Spalte N (Wikipedia Absatz)", + "Spalte O (Wikipedia Branche)", + "Spalte P (Wikipedia Umsatz)", + "Spalte Q (Wikipedia Mitarbeiter)", + "Spalte R (Wikipedia Kategorien)", + "Spalte S (Wiki Confirm)", + "Spalte T (Wiki Erklärung – nicht genutzt)", + "Spalte U (Alternative Wiki URL)", + "Spalte V (Wiki Begründung)", + "Spalte W (Branchenvorschlag)", + "Spalte X (Branchenkonsistenz)", + "Spalte Y (Branchenerklärung)", + "Spalte Z (nicht genutzt)", + "Spalte AA (FSM Relevanz – nicht genutzt)", + "Spalte AB (Begründung FSM – nicht genutzt)", + "Spalte AC (Schätzung Mitarbeiter – nicht genutzt)", + "Spalte AD (Einschätzung Techniker – nicht genutzt)", + "Spalte AE (Begründung Techniker – nicht genutzt)", + "Spalte AF (Schätzung Umsatz ChatGPT – nicht genutzt)", + "Spalte AG (Begründung Umsatz ChatGPT – nicht genutzt)", + "Spalte AH (Wikipedia-Timestamp – nicht genutzt)", + "Spalte AI (ChatGPT-Timestamp – nicht genutzt)", + "Spalte AJ (Kontakt: Serviceleiter gefunden)", + "Spalte AK (Kontakt: IT-Leiter gefunden)", + "Spalte AL (Kontakt: Management gefunden)", + "Spalte AM (Kontakt: Disponent gefunden)", + "Spalte AN (Contact Search Timestamp – nicht genutzt)", + "Spalte AO (Verifizierung Timestamp)", + "Spalte AP (Version)", + "Spalte AQ (Token Count Batch)" + ] + header_range = "A11200:AQ11200" + sheet.update(values=[new_headers], range_name=header_range) + print("Alignment-Demo abgeschlossen: Neue Spaltenüberschriften in Zeile 11200 geschrieben.") # ==================== MODUS 51: VERIFIZIERUNG (BATCH) ==================== def process_verification_only(): @@ -821,9 +834,9 @@ def process_verification_only(): batch_size = Config.BATCH_SIZE batch_entries = [] row_indices = [] - # Prüfe hier Spalte Y (Index 24); wenn leer, dann verifizieren. + # Prüfe Spalte S (Index 18): wenn leer, verarbeite den Eintrag for i, row in enumerate(data[1:], start=2): - if len(row) <= 25 or row[24].strip() == "": + if len(row) <= 19 or row[18].strip() == "": entry_text = _process_verification_row(i, row) batch_entries.append(entry_text) row_indices.append(i) @@ -832,11 +845,14 @@ def process_verification_only(): if not batch_entries: debug_print("Keine Einträge für die Verifizierung gefunden.") return - aggregated_prompt = ("Du bist ein Experte im Bereich Unternehmensverifizierung. " - "Für jeden der folgenden Einträge prüfe, ob der vorhandene Wikipedia-Artikel plausibel zum Unternehmen passt. " - "Gib für jeden Eintrag das Ergebnis in folgendem Format aus:\n" - "Eintrag : | | \n" - "Wenn der Artikel passt, antworte mit 'OK'. Falls nicht, schlage einen alternativen Artikel (als URL) vor.\n\n") + 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:\n" + "Eintrag : \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") aggregated_prompt += "\n".join(batch_entries) debug_print("Aggregierter Prompt für Verifizierungs-Batch erstellt.") token_count = "n.v." @@ -872,20 +888,45 @@ def process_verification_only(): if line.strip().startswith(f"Eintrag {row_num}:"): answer = line.split(":", 1)[1].strip() break + # Verarbeitung der Wiki-Verifizierung: + # Falls Antwort "OK": In Spalte S (Wiki Confirm) "OK", Spalte U leer. + # Falls Antwort "Kein Wikipedia-Eintrag vorhanden.": In Spalte U dieser Text, Spalte S bleibt leer. + # Falls Antwort mit "Alternativer Wikipedia-Artikel vorgeschlagen:" beginnt, extrahiere URL und Begründung. if answer.upper() == "OK": - branch_suggestion = "OK" - consistency = "OK" - justification = "" + wiki_confirm = "OK" + alt_article = "" + wiki_explanation = "" + elif answer.upper() == "KEIN WIKIPEDIA-EINTRAG VORHANDEN.": + wiki_confirm = "" + alt_article = "Kein Wikipedia-Eintrag vorhanden." + wiki_explanation = "" + elif answer.startswith("Alternativer Wikipedia-Artikel vorgeschlagen:"): + parts = answer.split(":", 1)[1].split("|") + alt_article = parts[0].strip() if len(parts) > 0 else "k.A." + wiki_explanation = parts[2].strip() if len(parts) > 2 else "" + wiki_confirm = "X" else: - branch_suggestion = answer - consistency = "X" - justification = answer - main_sheet.update(values=[[branch_suggestion]], range_name=f"W{row_num}") - main_sheet.update(values=[[consistency]], range_name=f"X{row_num}") - main_sheet.update(values=[[justification]], range_name=f"Y{row_num}") + wiki_confirm = "" + alt_article = answer + wiki_explanation = answer + # Schreibe Ergebnisse für Wiki-Verifizierung: + 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}") + # Branchenvorschlag: Nutze Branchenangaben aus Spalte G (Index 6), H (7), O (14) und R (17) + 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"Y{row_num}") + # Schreibe Token Count in Spalte AQ main_sheet.update(values=[[str(token_count)]], range_name=f"AQ{row_num}") - main_sheet.update(values=[[datetime.now().strftime('%Y-%m-%d %H:%M:%S')]], range_name=f"Z{row_num}") - main_sheet.update(values=[[Config.VERSION]], range_name=f"AA{row_num}") + # Schreibe Timestamp in Spalte AO und Version in Spalte AP + 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}") debug_print(f"Zeile {row_num} verifiziert: Antwort: {answer}") time.sleep(Config.RETRY_DELAY) debug_print("Verifizierungs-Batch abgeschlossen.") @@ -990,16 +1031,14 @@ if __name__ == "__main__": processor = DataProcessor() processor.process_rows() elif MODE == "4": - # Wiki-runner: Startindex anhand Spalte AN (Index 39) gh = GoogleSheetHandler() - start_index = gh.get_start_index(39) + start_index = gh.get_start_index(39) # Wiki-Timestamp (Spalte AN) debug_print(f"Wiki-Modus: Starte bei Zeile {start_index+1}") processor = DataProcessor() processor.process_rows() elif MODE == "5": - # ChatGPT-runner: Startindex anhand Spalte AO (Index 40) gh = GoogleSheetHandler() - start_index = gh.get_start_index(40) + start_index = gh.get_start_index(40) # ChatGPT-Timestamp (Spalte AO) debug_print(f"ChatGPT-Modus: Starte bei Zeile {start_index+1}") processor = DataProcessor() processor.process_rows() @@ -1008,7 +1047,6 @@ if __name__ == "__main__": elif MODE == "7": process_contacts() elif MODE == "8": - # Batch-Token-Zählung: Aggregiere 10 Zeilen und zähle Token gc = gspread.authorize(ServiceAccountCredentials.from_json_keyfile_name( Config.CREDENTIALS_FILE, ["https://www.googleapis.com/auth/spreadsheets"])) sh = gc.open_by_url(Config.SHEET_URL)