v1.3.16 – Modus 51 Verifizierung in Batch, Spaltenanpassungen für Wiki und Brancheneinordnung
Modus 51 wurde so angepasst, dass im Batch jeweils 10 Einträge aggregiert werden. Für jeden Eintrag wird aus ChatGPT das Ergebnis verarbeitet: – Spalte S erhält „OK“ (falls passend) oder bleibt leer. – Falls ein alternativer Artikel vorgeschlagen wird, wird die URL in Spalte U und die Begründung in Spalte V geschrieben; bei fehlendem Artikel wird in Spalte U „Kein Wikipedia-Eintrag vorhanden.“ eingetragen. Der Branchenvorschlag (basierend auf den Branchenangaben in Spalte G, H, O, R) wird in Spalte W geschrieben und das Konsistenzresultat in Spalte Y. Der Verifizierungs‑Timestamp wird in Spalte AO, die Version in Spalte AP und der Batch Token Count in Spalte AQ eingetragen.
This commit is contained in:
@@ -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: <vorgeschlagene Branche>\n"
|
||||
"Übereinstimmung: <OK oder X>\n"
|
||||
"Konsistenz: <OK oder X>\n"
|
||||
"Begründung: <Begründung bei Abweichung (leer, wenn OK)>"
|
||||
)
|
||||
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 <Zeilennummer>: <Antwort>\n"
|
||||
"Dabei gilt:\n"
|
||||
"- Wenn der Artikel passt, antworte mit 'OK'.\n"
|
||||
"- Wenn der Artikel nicht passt, antworte mit 'Alternativer Wikipedia-Artikel vorgeschlagen: <URL> | X | <Begründung>'.\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: <Antwort>"
|
||||
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 <Zeilennummer>: <Branchenvorschlag> | <Konsistenz (OK oder X)> | <Begründung>\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 <Zeilennummer>: <Antwort>\n"
|
||||
"Dabei gilt:\n"
|
||||
"- Wenn der Artikel passt, antworte mit 'OK'.\n"
|
||||
"- Wenn der Artikel unpassend ist, antworte mit 'Alternativer Wikipedia-Artikel vorgeschlagen: <URL> | X | <Begründung>'.\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)
|
||||
|
||||
Reference in New Issue
Block a user