bugfix
This commit is contained in:
@@ -533,33 +533,38 @@ class DataProcessor:
|
|||||||
# ==================== NEUE FUNKTION: process_verification_only ====================
|
# ==================== NEUE FUNKTION: process_verification_only ====================
|
||||||
def process_verification_only():
|
def process_verification_only():
|
||||||
"""
|
"""
|
||||||
Überarbeiteter Batch‑Prozess (Version 1.5.8, Modus 51):
|
Überarbeiteter Batch‑Prozess (Version 1.5.9, Modus 51):
|
||||||
- Ermittelt zunächst die letzte Zeile, in der in Spalte AO (Index 40) ein Zeitstempel steht.
|
- Startet die Verarbeitung ab Zeile 7 und sucht ab dort die erste Zeile, in der Spalte AO (Index 41) leer ist.
|
||||||
- Beginnt die Verarbeitung ab der nächsten Zeile.
|
- Ab dieser Zeile werden alle Zeilen in Paketen der Größe Config.BATCH_SIZE (z. B. 10 Zeilen) verarbeitet.
|
||||||
- Verarbeitet alle Zeilen ab diesem Startpunkt in Paketen der Größe Config.BATCH_SIZE (z. B. 10 Zeilen).
|
- Für jedes Batch wird ein aggregierter Prompt erstellt, an ChatGPT gesendet und die Antwort zeilenweise geparst.
|
||||||
- Für jedes Batch wird ein aggregierter Prompt erstellt, an ChatGPT gesendet und die Antwort
|
|
||||||
zeilenweise geparst.
|
|
||||||
- Die Ergebnisse werden in den Spalten S bis Y geschrieben:
|
- Die Ergebnisse werden in den Spalten S bis Y geschrieben:
|
||||||
S: Wiki-Validierung ("OK" oder "X")
|
S: Wiki-Validierung ("OK" oder "X")
|
||||||
T: Alternativer Wiki-Artikel (URL oder "Kein Wikipedia-Eintrag vorhanden.")
|
T: Alternativer Wiki-Artikel (URL oder "Kein Wikipedia-Eintrag vorhanden.")
|
||||||
U: Wiki-Erklärung / Begründung
|
U: Wiki-Erklärung / Begründung
|
||||||
V–Y: Platzhalter (leer)
|
V–Y: Platzhalter (leer)
|
||||||
- Umfassende Log-Ausgaben unterstützen die Fehlerdiagnose.
|
- Umfangreiche Log-Ausgaben unterstützen die Fehlerdiagnose.
|
||||||
"""
|
"""
|
||||||
debug_print("Starte Verifizierungsmodus (Modus 51) im Batch-Prozess (Version 1.5.8)...")
|
debug_print("Starte Verifizierungsmodus (Modus 51) im Batch-Prozess (Version 1.5.9)...")
|
||||||
|
|
||||||
# Bestimme, in welcher Zeile in Spalte AO zuletzt ein Zeitstempel vorhanden ist
|
# Bestimme ab Zeile 7 die erste Zeile, in der Spalte AO (Index 41) leer ist.
|
||||||
try:
|
gc = gspread.authorize(ServiceAccountCredentials.from_json_keyfile_name(
|
||||||
col_ao = main_sheet.col_values(41) # Spalte AO (1-basierter Index)
|
Config.CREDENTIALS_FILE, ["https://www.googleapis.com/auth/spreadsheets"]))
|
||||||
except Exception as e:
|
sh = gc.open_by_url(Config.SHEET_URL)
|
||||||
debug_print(f"Fehler beim Auslesen von Spalte AO: {e}")
|
main_sheet = sh.sheet1
|
||||||
col_ao = []
|
data = main_sheet.get_all_values()
|
||||||
last_filled_row = 1 # Header wird angenommen in Zeile 1
|
|
||||||
for idx, cell in enumerate(col_ao, start=1):
|
# Setze den Startindex: Beginne mindestens bei Zeile 7.
|
||||||
if cell.strip() != "":
|
start_row = None
|
||||||
last_filled_row = idx
|
for i in range(7, len(data) + 1):
|
||||||
start_row = last_filled_row + 1
|
row = data[i - 1]
|
||||||
debug_print(f"Letzter Zeitstempel in Spalte AO in Zeile {last_filled_row}. Verarbeitung startet ab Zeile {start_row}.")
|
# Prüfe, ob die Zeile weniger als 41 Spalten hat oder Spalte AO leer ist.
|
||||||
|
if len(row) < 41 or row[40].strip() == "":
|
||||||
|
start_row = i
|
||||||
|
break
|
||||||
|
if start_row is None:
|
||||||
|
debug_print("Keine Zeile ohne Zeitstempel in Spalte AO gefunden. Es wird nichts verarbeitet.")
|
||||||
|
return
|
||||||
|
debug_print(f"Verarbeitung startet ab Zeile {start_row} (erste Zeile ohne Zeitstempel in Spalte AO).")
|
||||||
|
|
||||||
# Abfrage: Wie viele Zeilen sollen insgesamt verarbeitet werden?
|
# Abfrage: Wie viele Zeilen sollen insgesamt verarbeitet werden?
|
||||||
try:
|
try:
|
||||||
@@ -568,31 +573,24 @@ def process_verification_only():
|
|||||||
debug_print(f"Fehler bei der Eingabe der Zeilenanzahl: {e}. Es werden alle verfügbaren Zeilen verarbeitet.")
|
debug_print(f"Fehler bei der Eingabe der Zeilenanzahl: {e}. Es werden alle verfügbaren Zeilen verarbeitet.")
|
||||||
total_rows = None
|
total_rows = None
|
||||||
|
|
||||||
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)
|
|
||||||
main_sheet = sh.sheet1
|
|
||||||
data = main_sheet.get_all_values()
|
|
||||||
available_total = len(data) - 1 # ohne Header
|
available_total = len(data) - 1 # ohne Header
|
||||||
# Begrenze die zu verarbeitenden Zeilen, falls total_rows vorgegeben ist
|
|
||||||
if total_rows is not None:
|
if total_rows is not None:
|
||||||
available_rows = min(total_rows, available_total)
|
available_rows = min(total_rows, available_total)
|
||||||
else:
|
else:
|
||||||
available_rows = available_total
|
available_rows = available_total
|
||||||
|
|
||||||
if start_row > available_rows + 1:
|
if start_row > available_rows + 1:
|
||||||
debug_print("Es gibt keine Zeilen ohne Zeitstempel, daher wird nichts verarbeitet.")
|
debug_print("Es gibt keine Zeilen ohne Zeitstempel ab dem Startpunkt. Es wird nichts verarbeitet.")
|
||||||
return
|
return
|
||||||
|
|
||||||
batch_size = Config.BATCH_SIZE # z. B. 10, einstellbar in Config
|
batch_size = Config.BATCH_SIZE # z. B. 10
|
||||||
batches = []
|
batches = []
|
||||||
row_numbers = []
|
row_numbers = []
|
||||||
|
|
||||||
# Iteriere ab start_row bis available_rows
|
# Verarbeitung ab start_row bis available_rows
|
||||||
for i, row in enumerate(data[start_row - 1:], start=start_row):
|
for i in range(start_row, available_rows + 2): # +1 wegen 1-basierter Index, +1 um bis available_rows einzubeziehen
|
||||||
if i > available_rows + 1:
|
row = data[i - 1]
|
||||||
break
|
# Da wir ab start_row starten, gehen wir davon aus, dass bisher keine Zeitstempel in AO vorhanden sind.
|
||||||
# Hier wird davon ausgegangen, dass ab start_row keine Zeitstempel in AO vorliegen.
|
|
||||||
entry_text = (
|
entry_text = (
|
||||||
f"Eintrag {i}:\n"
|
f"Eintrag {i}:\n"
|
||||||
f"Firmenname: {row[1] if len(row) > 1 else ''}\n"
|
f"Firmenname: {row[1] if len(row) > 1 else ''}\n"
|
||||||
@@ -605,146 +603,92 @@ def process_verification_only():
|
|||||||
batches.append(entry_text)
|
batches.append(entry_text)
|
||||||
row_numbers.append(i)
|
row_numbers.append(i)
|
||||||
if len(batches) == batch_size:
|
if len(batches) == batch_size:
|
||||||
aggregated_prompt = (
|
_process_batch(main_sheet, batches, row_numbers)
|
||||||
"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 das Ergebnis für jeden Eintrag im Format aus:\n"
|
|
||||||
"Eintrag <Zeilennummer>: <Antwort>\n"
|
|
||||||
"Regeln:\n"
|
|
||||||
"- Bei Übereinstimmung: 'OK'\n"
|
|
||||||
"- Bei Nichtübereinstimmung: 'Alternativer Wikipedia-Artikel vorgeschlagen: <URL> | X | <Begründung>'\n"
|
|
||||||
"- Falls kein Artikel gefunden wurde: 'Kein Wikipedia-Eintrag vorhanden.'\n\n"
|
|
||||||
)
|
|
||||||
aggregated_prompt += "\n".join(batches)
|
|
||||||
debug_print(f"Verarbeite Batch für Zeilen {row_numbers[0]} bis {row_numbers[-1]}.")
|
|
||||||
if tiktoken:
|
|
||||||
try:
|
|
||||||
enc = tiktoken.encoding_for_model(Config.TOKEN_MODEL)
|
|
||||||
debug_print(f"Token-Zahl für aktuellen Batch: {len(enc.encode(aggregated_prompt))}")
|
|
||||||
except Exception as e:
|
|
||||||
debug_print(f"Fehler beim Token-Counting: {e}")
|
|
||||||
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 für Verifizierung: {e}")
|
|
||||||
return
|
|
||||||
openai.api_key = api_key
|
|
||||||
try:
|
|
||||||
response = openai.ChatCompletion.create(
|
|
||||||
model=Config.TOKEN_MODEL,
|
|
||||||
messages=[{"role": "user", "content": aggregated_prompt}],
|
|
||||||
temperature=0.0
|
|
||||||
)
|
|
||||||
result = response.choices[0].message.content.strip()
|
|
||||||
debug_print(f"Aggregierte Antwort für Batch {row_numbers[0]}-{row_numbers[-1]}: {result}")
|
|
||||||
except Exception as e:
|
|
||||||
debug_print(f"Fehler bei der ChatGPT-Anfrage für Batch {row_numbers[0]}-{row_numbers[-1]}: {e}")
|
|
||||||
result = ""
|
|
||||||
answers = result.split("\n")
|
|
||||||
for current_row in row_numbers:
|
|
||||||
answer = "k.A."
|
|
||||||
for line in answers:
|
|
||||||
if line.strip().startswith(f"Eintrag {current_row}:"):
|
|
||||||
answer = line.split(":", 1)[1].strip()
|
|
||||||
break
|
|
||||||
if answer.upper() == "OK":
|
|
||||||
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:
|
|
||||||
wiki_confirm = ""
|
|
||||||
alt_article = answer
|
|
||||||
wiki_explanation = answer
|
|
||||||
try:
|
|
||||||
main_sheet.update(values=[[wiki_confirm]], range_name=f"S{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=[["", "", "", ""]], range_name=f"V{current_row}:Y{current_row}")
|
|
||||||
debug_print(f"Zeile {current_row} verifiziert: Antwort: {answer}")
|
|
||||||
except Exception as e:
|
|
||||||
debug_print(f"Fehler beim Updaten der Zeile {current_row}: {e}")
|
|
||||||
time.sleep(Config.RETRY_DELAY)
|
|
||||||
batches = []
|
batches = []
|
||||||
row_numbers = []
|
row_numbers = []
|
||||||
if batches:
|
if batches:
|
||||||
aggregated_prompt = (
|
_process_batch(main_sheet, batches, row_numbers)
|
||||||
"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 plausibel passt. "
|
|
||||||
"Gib das Ergebnis im Format aus:\n"
|
|
||||||
"Eintrag <Zeilennummer>: <Antwort>\n\n"
|
|
||||||
)
|
|
||||||
aggregated_prompt += "\n".join(batches)
|
|
||||||
debug_print(f"Verarbeite letztes Batch für Zeilen {row_numbers[0]} bis {row_numbers[-1]}.")
|
|
||||||
if tiktoken:
|
|
||||||
try:
|
|
||||||
enc = tiktoken.encoding_for_model(Config.TOKEN_MODEL)
|
|
||||||
debug_print(f"Token-Zahl für letztes Batch: {len(enc.encode(aggregated_prompt))}")
|
|
||||||
except Exception as e:
|
|
||||||
debug_print(f"Fehler beim Token-Counting im letzten Batch: {e}")
|
|
||||||
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 (Letztes Batch): {e}")
|
|
||||||
return
|
|
||||||
openai.api_key = api_key
|
|
||||||
try:
|
|
||||||
response = openai.ChatCompletion.create(
|
|
||||||
model=Config.TOKEN_MODEL,
|
|
||||||
messages=[{"role": "user", "content": aggregated_prompt}],
|
|
||||||
temperature=0.0
|
|
||||||
)
|
|
||||||
result = response.choices[0].message.content.strip()
|
|
||||||
debug_print(f"Aggregierte Antwort für letztes Batch: {result}")
|
|
||||||
except Exception as e:
|
|
||||||
debug_print(f"Fehler bei der ChatGPT-Anfrage für letztes Batch: {e}")
|
|
||||||
result = ""
|
|
||||||
answers = result.split("\n")
|
|
||||||
for current_row in row_numbers:
|
|
||||||
answer = "k.A."
|
|
||||||
for line in answers:
|
|
||||||
if line.strip().startswith(f"Eintrag {current_row}:"):
|
|
||||||
answer = line.split(":", 1)[1].strip()
|
|
||||||
break
|
|
||||||
if answer.upper() == "OK":
|
|
||||||
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:
|
|
||||||
wiki_confirm = ""
|
|
||||||
alt_article = answer
|
|
||||||
wiki_explanation = answer
|
|
||||||
try:
|
|
||||||
main_sheet.update(values=[[wiki_confirm]], range_name=f"S{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=[["", "", "", ""]], range_name=f"V{current_row}:Y{current_row}")
|
|
||||||
debug_print(f"Zeile {current_row} verifiziert: Antwort: {answer}")
|
|
||||||
except Exception as e:
|
|
||||||
debug_print(f"Fehler beim Updaten der Zeile {current_row}: {e}")
|
|
||||||
time.sleep(Config.RETRY_DELAY)
|
|
||||||
debug_print("Verifizierungs-Batch abgeschlossen.")
|
debug_print("Verifizierungs-Batch abgeschlossen.")
|
||||||
|
|
||||||
|
|
||||||
|
def _process_batch(main_sheet, batches, row_numbers):
|
||||||
|
"""
|
||||||
|
Hilfsfunktion: Bearbeitet einen Batch, indem ein aggregierter Prompt erstellt und
|
||||||
|
die aggregierte Antwort zeilenweise den entsprechenden Zeilennummern zugeordnet wird.
|
||||||
|
Die Ergebnisse werden in Spalten S bis Y geschrieben.
|
||||||
|
"""
|
||||||
|
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 das Ergebnis für jeden Eintrag im Format aus:\n"
|
||||||
|
"Eintrag <Zeilennummer>: <Antwort>\n"
|
||||||
|
"Regeln:\n"
|
||||||
|
"- Bei Übereinstimmung: 'OK'\n"
|
||||||
|
"- Bei Nichtübereinstimmung: 'Alternativer Wikipedia-Artikel vorgeschlagen: <URL> | X | <Begründung>'\n"
|
||||||
|
"- Falls kein Artikel gefunden wurde: 'Kein Wikipedia-Eintrag vorhanden.'\n\n"
|
||||||
|
)
|
||||||
|
aggregated_prompt += "\n".join(batches)
|
||||||
|
debug_print(f"Verarbeite Batch für Zeilen {row_numbers[0]} bis {row_numbers[-1]}.")
|
||||||
|
if tiktoken:
|
||||||
|
try:
|
||||||
|
enc = tiktoken.encoding_for_model(Config.TOKEN_MODEL)
|
||||||
|
debug_print(f"Token-Zahl für aktuellen Batch: {len(enc.encode(aggregated_prompt))}")
|
||||||
|
except Exception as e:
|
||||||
|
debug_print(f"Fehler beim Token-Counting: {e}")
|
||||||
|
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 für Verifizierung: {e}")
|
||||||
|
return
|
||||||
|
openai.api_key = api_key
|
||||||
|
try:
|
||||||
|
response = openai.ChatCompletion.create(
|
||||||
|
model=Config.TOKEN_MODEL,
|
||||||
|
messages=[{"role": "user", "content": aggregated_prompt}],
|
||||||
|
temperature=0.0
|
||||||
|
)
|
||||||
|
result = response.choices[0].message.content.strip()
|
||||||
|
debug_print(f"Aggregierte Antwort für Batch {row_numbers[0]}-{row_numbers[-1]}: {result}")
|
||||||
|
except Exception as e:
|
||||||
|
debug_print(f"Fehler bei der ChatGPT-Anfrage für Batch {row_numbers[0]}-{row_numbers[-1]}: {e}")
|
||||||
|
result = ""
|
||||||
|
answers = result.split("\n")
|
||||||
|
for current_row in row_numbers:
|
||||||
|
answer = "k.A."
|
||||||
|
for line in answers:
|
||||||
|
if line.strip().startswith(f"Eintrag {current_row}:"):
|
||||||
|
answer = line.split(":", 1)[1].strip()
|
||||||
|
break
|
||||||
|
if answer.upper() == "OK":
|
||||||
|
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:
|
||||||
|
wiki_confirm = ""
|
||||||
|
alt_article = answer
|
||||||
|
wiki_explanation = answer
|
||||||
|
try:
|
||||||
|
main_sheet.update(values=[[wiki_confirm]], range_name=f"S{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=[["", "", "", ""]], range_name=f"V{current_row}:Y{current_row}")
|
||||||
|
debug_print(f"Zeile {current_row} verifiziert: Antwort: {answer}")
|
||||||
|
except Exception as e:
|
||||||
|
debug_print(f"Fehler beim Updaten der Zeile {current_row}: {e}")
|
||||||
|
time.sleep(Config.RETRY_DELAY)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ==================== List Metatitel, Description und Überschriften aus Websiten aus ====================
|
# ==================== List Metatitel, Description und Überschriften aus Websiten aus ====================
|
||||||
def scrape_website_details(url):
|
def scrape_website_details(url):
|
||||||
|
|||||||
Reference in New Issue
Block a user