Rollback auf 1.5.4

This commit is contained in:
2025-04-14 06:23:24 +00:00
parent c9e659d952
commit 2346282b93

View File

@@ -107,7 +107,9 @@ def process_wiki_batch(main_sheet, data, start_row, end_row):
""" """
Batch-Prozess für Wikipedia-Verifizierung (Wiki-Modus): Batch-Prozess für Wikipedia-Verifizierung (Wiki-Modus):
- Verarbeitet alle Zeilen von start_row bis end_row in Gruppen (Batchgröße = Config.BATCH_SIZE). - Verarbeitet alle Zeilen von start_row bis end_row in Gruppen (Batchgröße = Config.BATCH_SIZE).
- Ergebnisse werden in den Spalten S bis Y geschrieben. - Für jeden Batch wird ein aggregierter Prompt erstellt und an ChatGPT geschickt.
- Die Aggregat-Ergebnisse werden zeilenweise in Spalte S (Wiki-Validierung), T (alternativer Wiki-Artikel),
U (Wiki-Erklärung) und VY (Platzhalter) geschrieben.
""" """
batch_size = Config.BATCH_SIZE batch_size = Config.BATCH_SIZE
batches = [] batches = []
@@ -133,14 +135,12 @@ def process_wiki_batch(main_sheet, data, start_row, end_row):
_process_batch(main_sheet, batches, row_numbers) _process_batch(main_sheet, batches, row_numbers)
debug_print("Wiki batch processing completed.") debug_print("Wiki batch processing completed.")
def process_website_batch(main_sheet, data, start_row, end_row): def process_website_batch(main_sheet, data, start_row, end_row):
""" """
Batch-Prozess für Website-Scraping (Website-Modus): Batch-Prozess für Website-Scraping (Website-Modus):
- Für jede Zeile von start_row bis end_row werden Website-Rohtext (get_website_raw) und - Für jede Zeile von start_row bis end_row wird, falls eine CRM-Website vorhanden ist,
Zusammenfassung (summarize_website_content) abgerufen. get_website_raw aufgerufen, um den Rohtext abzurufen, und summarize_website_content zur Zusammenfassung.
- Ergebnisse werden in Spalte AR (Rohtext) und AS (Zusammenfassung) geschrieben. - Die Ergebnisse werden in Spalte AR (Website Rohtext) und AS (Website Zusammenfassung) geschrieben.
- Am Ende jeder Zeile wird der Zeitstempel (Spalte AO) und Version (Spalte AP) gesetzt.
""" """
for i in range(start_row, end_row + 1): for i in range(start_row, end_row + 1):
row = data[i - 1] row = data[i - 1]
@@ -153,24 +153,19 @@ def process_website_batch(main_sheet, data, start_row, end_row):
try: try:
main_sheet.update(values=[[raw_text]], range_name=f"AR{i}") main_sheet.update(values=[[raw_text]], range_name=f"AR{i}")
main_sheet.update(values=[[summary]], range_name=f"AS{i}") main_sheet.update(values=[[summary]], range_name=f"AS{i}")
current_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") debug_print(f"Zeile {i}: Website-Daten aktualisiert.")
main_sheet.update(values=[[current_timestamp]], range_name=f"AO{i}")
main_sheet.update(values=[[Config.VERSION]], range_name=f"AP{i}")
debug_print(f"Zeile {i}: Website-Daten aktualisiert | Zeitstempel: {current_timestamp}, Version: {Config.VERSION}")
except Exception as e: except Exception as e:
debug_print(f"Fehler beim Updaten der Website-Daten in Zeile {i}: {e}") debug_print(f"Fehler beim Updaten der Website-Daten in Zeile {i}: {e}")
time.sleep(Config.RETRY_DELAY) time.sleep(Config.RETRY_DELAY)
debug_print("Website batch processing completed.") debug_print("Website batch processing completed.")
def process_branch_batch(main_sheet, data, start_row, end_row): def process_branch_batch(main_sheet, data, start_row, end_row):
""" """
Batch-Prozess für Brancheneinschätzung (Branch-Modus): Batch-Prozess für Brancheneinschätzung (Branch-Modus):
- Für jede Zeile von start_row bis end_row werden relevante Felder ausgelesen und - Für jede Zeile von start_row bis end_row werden die relevanten Felder für die Brancheneinschätzung ausgelesen.
evaluate_branche_chatgpt aufgerufen. - Es werden evaluate_branche_chatgpt aufgerufen, die das Branchenergebnis als Dictionary zurückgibt.
- Das Ergebnis (Dictionary mit "branch", "consistency", "justification") wird in - Die Ergebnisse werden in Spalte W (Chat Vorschlag Branche), X (Chat Konsistenz Branche)
Spalte W (Branch), X (Konsistenz) und Y (Begründung) geschrieben. und Y (Chat Begründung Abweichung Branche) geschrieben.
- Für jede verarbeitete Zeile werden zudem der Zeitstempel (Spalte AO) und Version (Spalte AP) gesetzt.
""" """
for i in range(start_row, end_row + 1): for i in range(start_row, end_row + 1):
row = data[i - 1] row = data[i - 1]
@@ -178,30 +173,25 @@ def process_branch_batch(main_sheet, data, start_row, end_row):
beschreibung = row[7] if len(row) > 7 else "" beschreibung = row[7] if len(row) > 7 else ""
wiki_branche = row[14] if len(row) > 14 else "" wiki_branche = row[14] if len(row) > 14 else ""
wiki_kategorien = row[17] if len(row) > 17 else "" wiki_kategorien = row[17] if len(row) > 17 else ""
# Website Zusammenfassung aus Spalte AS (Index 45, wenn vorhanden)
website_summary = row[44] if len(row) > 44 else "" website_summary = row[44] if len(row) > 44 else ""
result = evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kategorien, website_summary) result = evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kategorien, website_summary)
try: try:
main_sheet.update(values=[[result["branch"]]], range_name=f"W{i}") main_sheet.update(values=[[result["branch"]]], range_name=f"W{i}")
main_sheet.update(values=[[result["consistency"]]], range_name=f"X{i}") main_sheet.update(values=[[result["consistency"]]], range_name=f"X{i}")
main_sheet.update(values=[[result["justification"]]], range_name=f"Y{i}") main_sheet.update(values=[[result["justification"]]], range_name=f"Y{i}")
current_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") debug_print(f"Zeile {i}: Branch-Einschätzung aktualisiert: {result}")
main_sheet.update(values=[[current_timestamp]], range_name=f"AO{i}")
main_sheet.update(values=[[Config.VERSION]], range_name=f"AP{i}")
debug_print(f"Zeile {i}: Branch-Einschätzung aktualisiert: {result} | Zeitstempel: {current_timestamp}, Version: {Config.VERSION}")
except Exception as e: except Exception as e:
debug_print(f"Fehler beim Updaten der Branch-Daten in Zeile {i}: {e}") debug_print(f"Fehler beim Updaten der Branch-Daten in Zeile {i}: {e}")
time.sleep(Config.RETRY_DELAY) time.sleep(Config.RETRY_DELAY)
debug_print("Branch batch processing completed.") debug_print("Branch batch processing completed.")
def run_dispatcher(mode, row_limit=None): def run_dispatcher(mode, row_limit=None):
""" """
Dispatcher-Funktion: Dispatcher-Funktion:
- Ermittelt ab Zeile 7 die erste Zeile, in der in Spalte AO (Index 41) kein Zeitstempel steht. - Ermittelt aus dem Google Sheet ab Zeile 7 die erste Zeile, in der in Spalte AO (Index 41) kein Zeitstempel steht.
- Legt den zu verarbeitenden Bereich fest: Ab diesem Startpunkt werden row_limit Zeilen (falls angegeben) - Legt den zu verarbeitenden Bereich fest: ab diesem Startpunkt werden row_limit Zeilen (falls angegeben) verarbeitet.
verarbeitet. - Basierend auf dem Modus-Parameter (wiki, website, branch, combined) werden die entsprechenden Batch-Prozesse gestartet.
- Basierend auf dem mode-Parameter ("wiki", "website", "branch", "combined") werden die entsprechenden
Batch-Prozesse gestartet.
""" """
debug_print(f"Starte Dispatcher im Modus '{mode}' mit row_limit={row_limit}.") debug_print(f"Starte Dispatcher im Modus '{mode}' mit row_limit={row_limit}.")
gc = gspread.authorize(ServiceAccountCredentials.from_json_keyfile_name( gc = gspread.authorize(ServiceAccountCredentials.from_json_keyfile_name(
@@ -759,8 +749,7 @@ def _process_batch(main_sheet, batches, row_numbers):
""" """
Hilfsfunktion: Bearbeitet einen Batch, indem ein aggregierter Prompt erstellt und Hilfsfunktion: Bearbeitet einen Batch, indem ein aggregierter Prompt erstellt und
die aggregierte Antwort zeilenweise den entsprechenden Zeilennummern zugeordnet wird. die aggregierte Antwort zeilenweise den entsprechenden Zeilennummern zugeordnet wird.
Die Ergebnisse werden in den Spalten S bis Y geschrieben, und anschließend wird Die Ergebnisse werden in Spalten S bis Y geschrieben.
für jede Zeile der aktuelle Zeitstempel (Spalte AO) sowie die Versionsnummer (Spalte AP) eingetragen.
""" """
aggregated_prompt = ( aggregated_prompt = (
"Du bist ein Experte in der Verifizierung von Wikipedia-Artikeln für Unternehmen. " "Du bist ein Experte in der Verifizierung von Wikipedia-Artikeln für Unternehmen. "
@@ -827,11 +816,7 @@ def _process_batch(main_sheet, batches, row_numbers):
main_sheet.update(values=[[alt_article]], range_name=f"T{current_row}") main_sheet.update(values=[[alt_article]], range_name=f"T{current_row}")
main_sheet.update(values=[[wiki_explanation]], range_name=f"U{current_row}") main_sheet.update(values=[[wiki_explanation]], range_name=f"U{current_row}")
main_sheet.update(values=[["", "", "", ""]], range_name=f"V{current_row}:Y{current_row}") main_sheet.update(values=[["", "", "", ""]], range_name=f"V{current_row}:Y{current_row}")
# Neu: Setze Zeitstempel in Spalte AO und Version in Spalte AP debug_print(f"Zeile {current_row} verifiziert: Antwort: {answer}")
current_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
main_sheet.update(values=[[current_timestamp]], range_name=f"AO{current_row}")
main_sheet.update(values=[[Config.VERSION]], range_name=f"AP{current_row}")
debug_print(f"Zeile {current_row} verifiziert: Antwort: {answer} | Zeitstempel: {current_timestamp}, Version: {Config.VERSION}")
except Exception as e: except Exception as e:
debug_print(f"Fehler beim Updaten der Zeile {current_row}: {e}") debug_print(f"Fehler beim Updaten der Zeile {current_row}: {e}")
time.sleep(Config.RETRY_DELAY) time.sleep(Config.RETRY_DELAY)
@@ -1406,21 +1391,17 @@ 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):
# Ziel-Branchenschema laden (BOM entfernen)
def load_target_branches(): def load_target_branches():
try: try:
with open("ziel_Branchenschema.csv", "r", encoding="utf-8-sig") as csvfile: with open("ziel_Branchenschema.csv", "r", encoding="utf-8") as csvfile:
reader = csv.reader(csvfile) reader = csv.reader(csvfile)
# Nimm alle Einträge (Spalte 0), ohne leere Zeilen branches = [row[0] for row in reader if row]
branches = [row[0].strip() for row in reader if row and row[0].strip()]
return branches return branches
except Exception as e: except Exception as e:
debug_print(f"Fehler beim Laden des Ziel-Branchenschemas: {e}") debug_print(f"Fehler beim Laden des Ziel-Branchenschemas: {e}")
return [] return []
target_branches = load_target_branches() target_branches = load_target_branches()
target_branches_str = "\n".join(target_branches) target_branches_str = "\n".join(target_branches)
# Definierte Fokusbranchen (wie bisher)
focus_branches = [ focus_branches = [
"Gutachter / Versicherungen > Baugutachter", "Gutachter / Versicherungen > Baugutachter",
"Gutachter / Versicherungen > Technische Gutachten", "Gutachter / Versicherungen > Technische Gutachten",
@@ -1439,8 +1420,6 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg
"Versorger > Telekommunikation" "Versorger > Telekommunikation"
] ]
focus_branches_str = "\n".join(focus_branches) focus_branches_str = "\n".join(focus_branches)
# API-Key laden
try: try:
with open("api_key.txt", "r") as f: with open("api_key.txt", "r") as f:
api_key = f.read().strip() api_key = f.read().strip()
@@ -1449,7 +1428,7 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg
return {"branch": "k.A.", "consistency": "k.A.", "justification": "k.A."} return {"branch": "k.A.", "consistency": "k.A.", "justification": "k.A."}
openai.api_key = api_key openai.api_key = api_key
# Fallback: Wenn kein Wikipedia-Artikel vorhanden, verwende Website-Zusammenfassung # Falls kein Wikipedia-Artikel vorliegt, nutze die Website-Zusammenfassung als Fallback für die Branchenbeschreibung
if wiki_branche.strip().lower() == "k.a.": if wiki_branche.strip().lower() == "k.a.":
debug_print("Kein Wikipedia-Artikel vorhanden verwende Website-Zusammenfassung als Branchenbeschreibung-Fallback.") debug_print("Kein Wikipedia-Artikel vorhanden verwende Website-Zusammenfassung als Branchenbeschreibung-Fallback.")
used_description = website_summary used_description = website_summary
@@ -1457,7 +1436,6 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg
used_description = beschreibung used_description = beschreibung
debug_print(f"Verwendete Angaben: CRM-Branche='{crm_branche}', externe Beschreibung='{beschreibung}', Wiki-Branche='{wiki_branche}', Wiki-Kategorien='{wiki_kategorien}'") debug_print(f"Verwendete Angaben: CRM-Branche='{crm_branche}', externe Beschreibung='{beschreibung}', Wiki-Branche='{wiki_branche}', Wiki-Kategorien='{wiki_kategorien}'")
# System-Prompt erstellen
system_prompt = ( 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" "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 if crm_branche.strip() != '' else 'k.A.'}\n" f"CRM-Branche (Spalte F): {crm_branche if crm_branche.strip() != '' else 'k.A.'}\n"
@@ -1473,7 +1451,8 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg
"1. Wikipedia-Branche (Spalte N) zusammen mit Wikipedia-Kategorien (Spalte Q) (höchste Priorität, wenn verifiziert, ansonsten erhöhte Gewichtung der Kategorien)\n" "1. Wikipedia-Branche (Spalte N) zusammen mit Wikipedia-Kategorien (Spalte Q) (höchste Priorität, wenn verifiziert, ansonsten erhöhte Gewichtung der Kategorien)\n"
"2. Branchenbeschreibung (Spalte G) (hier wird die Website-Zusammenfassung genutzt, wenn kein Wikipedia-Artikel vorhanden ist)\n" "2. Branchenbeschreibung (Spalte G) (hier wird die Website-Zusammenfassung genutzt, wenn kein Wikipedia-Artikel vorhanden ist)\n"
"3. CRM-Branche (Spalte F)\n\n" "3. CRM-Branche (Spalte F)\n\n"
"Ordne das Unternehmen exakt einer der oben genannten Branchen zu (keine zusätzlichen Branchen erfinden). Bitte antworte im Format:\n" "Ordne das Unternehmen exakt einer der oben genannten Branchen zu (keine zusätzlichen Branchen erfinden). "
"Bitte antworte im Format:\n"
"Branche: <vorgeschlagene Branche>\nÜbereinstimmung: <ok oder X>\nBegründung: <kurze Begründung, falls abweichend, ansonsten leer>" "Branche: <vorgeschlagene Branche>\nÜbereinstimmung: <ok oder X>\nBegründung: <kurze Begründung, falls abweichend, ansonsten leer>"
) )
@@ -1485,48 +1464,39 @@ def evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kateg
) )
result = response.choices[0].message.content.strip() result = response.choices[0].message.content.strip()
debug_print(f"Branchenabgleich ChatGPT Antwort: '{result}'") debug_print(f"Branchenabgleich ChatGPT Antwort: '{result}'")
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()
# Zuerst prüfen, ob der ChatGPT-Vorschlag überhaupt zum Ziel-Branchenschema gehört
if branch.lower() not in [tb.lower() for tb in target_branches]:
justification = "Vorgeschlagene Branche entspricht nicht dem Ziel-Branchenschema."
branch = "k.A."
consistency = "X"
else:
# Vergleiche die normierten Werte der CRM-Branche und des ChatGPT-Vorschlags
norm_crm = normalize_company_name(crm_branche)
norm_branch = normalize_company_name(branch)
debug_print(f"Vergleich normierter Werte: CRM='{norm_crm}' vs. ChatGPT='{norm_branch}'")
if norm_crm and norm_branch == norm_crm:
justification = ""
consistency = "ok"
else:
consistency = "X"
debug_print(f"Endergebnis Branchenbewertung: Branche='{branch}', Übereinstimmung='{consistency}', Begründung='{justification}'")
return {"branch": branch, "consistency": consistency, "justification": justification}
except Exception as e: except Exception as e:
debug_print(f"Fehler beim Aufruf der ChatGPT API für Branchenabgleich: {e}") debug_print(f"Fehler beim Aufruf der ChatGPT API für Branchenabgleich: {e}")
return {"branch": "k.A.", "consistency": "k.A.", "justification": "k.A."} return {"branch": "k.A.", "consistency": "k.A.", "justification": "k.A."}
# Ergebnisse parsen
chat_branch = None
chat_consistency = None
chat_justification = ""
for line in result.split("\n"):
lower_line = line.lower()
if lower_line.startswith("branche:"):
chat_branch = line.split(":", 1)[1].strip()
elif lower_line.startswith("übereinstimmung:"):
chat_consistency = line.split(":", 1)[1].strip()
elif lower_line.startswith("begründung:"):
chat_justification = line.split(":", 1)[1].strip()
# Überprüfung: Wird ein Branch vorgeschlagen und ist dieser im Ziel-Schema enthalten?
valid = False
if chat_branch:
# Vergleiche normiert
norm_chat = normalize_company_name(chat_branch)
norm_targets = [normalize_company_name(tb) for tb in target_branches]
if norm_chat and norm_chat in norm_targets:
valid = True
if not valid:
# Falls der Vorschlag nicht im Schema enthalten ist, gebe klar die Fehlermeldung zurück
debug_print("Vorgeschlagene Branche entspricht nicht dem Ziel-Branchenschema.")
return {"branch": "k.A.", "consistency": "X", "justification": "Vorgeschlagene Branche entspricht nicht dem Ziel-Branchenschema."}
else:
# Wenn der ChatGPT-Vorschlag gültig ist, vergleichen wir ihn mit der normierten CRM-Branche
norm_crm = normalize_company_name(crm_branche)
norm_chat = normalize_company_name(chat_branch)
debug_print(f"Vergleich normierter Werte: CRM='{norm_crm}' vs. ChatGPT='{norm_chat}'")
if norm_crm and norm_crm == norm_chat:
chat_consistency = "ok"
chat_justification = ""
else:
chat_consistency = "X"
debug_print(f"Endergebnis Branchenbewertung: Branche='{chat_branch}', Übereinstimmung='{chat_consistency}', Begründung='{chat_justification}'")
return {"branch": chat_branch, "consistency": chat_consistency, "justification": chat_justification}