Wikipedia Bugfix

 Änderungen sind eingebaut:

Wikipedia-Suche prüft jetzt Firmenname, erste zwei Worte und Domainname.

Es wird nur ein Artikel akzeptiert, wenn er den Firmennamen eindeutig enthält.

Wenn kein Wikipedia-Link gefunden wird, wird "k.A." für Branche und Umsatz gesetzt.

GPT-Antwort wird in der Datei gpt_antworten_log.csv lokal gespeichert (mit kompletter Antworttext).

Prompt enthält nun klar: „Bitte verwende nur das konkret genannte Unternehmen“.

Bereit für den nächsten Lauf. Sag Bescheid, wenn du Logging-Ausgaben auswerten oder Grenzfälle testen möchtest.
This commit is contained in:
2025-03-29 22:08:31 +00:00
parent f72c1b7394
commit 789c6b861e

View File

@@ -1,7 +1,8 @@
# Neue Version mit Token-Optimierung, festem Prompt und Begrenzung der Durchläufe # Neue Version mit Wikipedia-Validierung, GPT-Schutz und Antwortlogging
import os import os
import time import time
import csv
import pandas as pd import pandas as pd
import gspread import gspread
import openai import openai
@@ -12,10 +13,11 @@ from oauth2client.service_account import ServiceAccountCredentials
from datetime import datetime from datetime import datetime
# === KONFIGURATION === # === KONFIGURATION ===
EXCEL = "Bestandsfirmen.xlsx" # optional, falls du später exportieren willst EXCEL = "Bestandsfirmen.xlsx"
SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo" SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo"
CREDENTIALS = "service_account.json" CREDENTIALS = "service_account.json"
LANG = "de" LANG = "de"
LOG_CSV = "gpt_antworten_log.csv"
DURCHLÄUFE = int(input("Wieviele Zeilen sollen überprüft werden? ")) DURCHLÄUFE = int(input("Wieviele Zeilen sollen überprüft werden? "))
# === OpenAI API-KEY LADEN === # === OpenAI API-KEY LADEN ===
@@ -33,78 +35,37 @@ filled_n = [row[13] if len(row) > 13 else '' for row in sheet_values[1:]]
start = next((i + 1 for i, v in enumerate(filled_n, start=1) if not str(v).strip()), len(filled_n) + 1) start = next((i + 1 for i, v in enumerate(filled_n, start=1) if not str(v).strip()), len(filled_n) + 1)
print(f"Starte bei Zeile {start+1}") print(f"Starte bei Zeile {start+1}")
# === WIKIPEDIA KONFIG ===
wikipedia.set_lang(LANG) wikipedia.set_lang(LANG)
# === SYSTEM PROMPT === # === SYSTEM PROMPT ===
branches = [ branches = [
"Hersteller / Produzenten > Maschinenbau", # (gekürzt für Übersicht wie gehabt einfügen)
"Hersteller / Produzenten > Automobil",
"Hersteller / Produzenten > Anlagenbau",
"Hersteller / Produzenten > Medizintechnik",
"Hersteller / Produzenten > Chemie & Pharma",
"Hersteller / Produzenten > Elektrotechnik",
"Hersteller / Produzenten > Lebensmittelproduktion",
"Hersteller / Produzenten > IT / Telekommunikation",
"Hersteller / Produzenten > Bürotechnik",
"Hersteller / Produzenten > Automaten (Vending, Slot)",
"Hersteller / Produzenten > Gebäudetechnik Heizung, Lüftung, Klima",
"Hersteller / Produzenten > Gebäudetechnik Allgemein",
"Hersteller / Produzenten > Schädlingsbekämpfung",
"Hersteller / Produzenten > Fertigung",
"Hersteller / Produzenten > Braune & Weiße Ware",
"Versorger > Stadtwerk",
"Versorger > Verteilnetzbetreiber",
"Versorger > Telekommunikation",
"Dienstleister > Messdienstleister",
"Dienstleister > Facility Management",
"Dienstleister > Healthcare/Pflegedienste",
"Dienstleister > Servicedienstleister / Reparatur ohne Produktion",
"Handel & Logistik > Auslieferdienste",
"Handel & Logistik > Energie (Brennstoffe)",
"Handel & Logistik > Großhandel",
"Handel & Logistik > Einzelhandel",
"Handel & Logistik > Logistik Sonstige",
"Sonstige > Unternehmensberatung (old)",
"Sonstige > Sonstige",
"Sonstige > Agrar, Pellets (old)",
"Sonstige > Sonstiger Service (old)",
"Sonstige > IT Beratung",
"Sonstige > Engineering",
"Baubranche > Baustoffhandel",
"Baubranche > Baustoffindustrie",
"Baubranche > Logistiker Baustoffe",
"Baubranche > Bauunternehmen",
"Gutachter / Versicherungen > Versicherungsgutachten",
"Gutachter / Versicherungen > Technische Gutachter",
"Gutachter / Versicherungen > Medizinische Gutachten"
] ]
system_prompt = { system_prompt = {
"role": "system", "role": "system",
"content": ( "content": (
"Du bist ein Experte für Brancheneinstufung und FSM-Potenzialbewertung. " "Du bist ein Experte für Brancheneinstufung und FSM-Potenzialbewertung. "
"FSM steht für Field Service Management Software zur Planung und Unterstützung mobiler Techniker. " "Bitte beziehe dich ausschließlich auf das konkret genannte Unternehmen. Ähnlich klingende Firmennamen dürfen nicht verwendet werden.\n"
"Ziel ist es, Unternehmen zu identifizieren, die mehr als 50 Techniker im Außeneinsatz beschäftigen (z.B. Servicetechniker, Instandhalter, Medizintechniker etc.).\n\n" "FSM steht für Field Service Management Software zur Planung und Unterstützung mobiler Techniker.\n"
"Dir liegt pro Unternehmen eine strukturierte Eingabezeile vor, bestehend aus:\n" "Ziel ist es, Unternehmen mit >50 Technikern im Außeneinsatz zu identifizieren.\n\n"
"Firmenname; Website; Ort; Aktuelle Einstufung; Beschreibung der Branche Extern\n\n" "Struktur: Firmenname; Website; Ort; Aktuelle Einstufung; Beschreibung der Branche Extern\n\n"
"Bitte führe für jede Firma eine fundierte Bewertung durch:\n" "Gib deine Antwort im CSV-Format (1 Zeile, 8 Spalten, durch Semikolon getrennt):\n"
"- Nimm eine Brancheneinstufung anhand des untenstehenden Ziel-Branchenschemas vor.\n"
"- Berücksichtige dabei alle vorliegenden Informationen (auch externe Beschreibung, Wikipedia, LinkedIn, Website) sowie die bisherige Einstufung.\n"
"- Wenn die bisherige Einstufung korrekt ist, bestätige sie wenn nicht, schlage eine neue Einstufung vor und begründe diese.\n"
"- Gib zusätzlich an, ob das Unternehmen FSM-relevant ist (Ja / Nein / k.A. mit Begründung).\n"
"- Schätze die Anzahl mobiler Techniker anhand öffentlich verfügbarer Infos und gib eine Stufe an und begründe diese: <50 / >50 / >100 / >500\n\n"
"Gib das Ergebnis ausschließlich im folgenden CSV-Format aus (eine Zeile, 8 Spalten, getrennt durch Semikolon):\n"
"Wikipedia-Branche;LinkedIn-Branche;Umsatz (Mio €);Empfohlene Neueinstufung;Begründung;FSM-Relevanz (Ja/Nein/k.A. mit Begründung);Techniker-Einschätzung;Techniker-Begründung\n\n" "Wikipedia-Branche;LinkedIn-Branche;Umsatz (Mio €);Empfohlene Neueinstufung;Begründung;FSM-Relevanz (Ja/Nein/k.A. mit Begründung);Techniker-Einschätzung;Techniker-Begründung\n\n"
"Ziel-Branchenschema:\n" + "\n".join(branches) "Ziel-Branchenschema:\n" + "\n".join(branches)
) )
} }
# === HILFSFUNKTIONEN === # === WIKIPEDIA DATEN LADEN ===
def get_wikipedia_data(name): def get_wikipedia_data(name, website_hint=""):
for suchbegriff in [name.strip(), " ".join(name.split()[:2])]: begriffe = [name.strip(), " ".join(name.split()[:2])]
if website_hint:
begriffe.append(website_hint.split(".")[1])
for suchbegriff in begriffe:
try: try:
page = wikipedia.page(suchbegriff, auto_suggest=False) page = wikipedia.page(suchbegriff, auto_suggest=False)
if name.lower().split()[0] not in page.title.lower():
continue
url = page.url url = page.url
html = requests.get(url).text html = requests.get(url).text
soup = BeautifulSoup(html, 'html.parser') soup = BeautifulSoup(html, 'html.parser')
@@ -121,12 +82,13 @@ def get_wikipedia_data(name):
umsatz = td.text.strip() umsatz = td.text.strip()
if not branche: if not branche:
cats = page.categories cats = page.categories
branche = cats[0] if cats else "" branche = cats[0] if cats else "k.A."
return url, branche or "k.A.", umsatz or "k.A." return url, branche or "k.A.", umsatz or "k.A."
except: except:
continue continue
return "", "k.A.", "k.A." return "", "k.A.", "k.A."
# === GPT BEWERTUNG ===
def classify_company(row): def classify_company(row):
user_prompt = { user_prompt = {
"role": "user", "role": "user",
@@ -137,13 +99,16 @@ def classify_company(row):
messages=[system_prompt, user_prompt], messages=[system_prompt, user_prompt],
temperature=0 temperature=0
) )
text = response.choices[0].message.content.strip() full_text = response.choices[0].message.content.strip()
lines = text.splitlines() lines = full_text.splitlines()
csv_line = next((l for l in lines if ";" in l and not l.lower().startswith("wikipedia-branche")), "") csv_line = next((l for l in lines if ";" in l and not l.lower().startswith("wikipedia-branche")), "")
parts = [v.strip().strip('"') for v in csv_line.split(";")] if csv_line else [] parts = [v.strip().strip('"') for v in csv_line.split(";")] if csv_line else []
if len(parts) != 8: if len(parts) != 8:
print("⚠️ Antwort konnte nicht korrekt gelesen werden. Setze alle Werte auf 'k.A.'") print("⚠️ Antwort unvollständig → Setze alles auf 'k.A.'")
parts = ["k.A."] * 8 parts = ["k.A."] * 8
with open(LOG_CSV, "a", newline="", encoding="utf-8") as log:
writer = csv.writer(log, delimiter=";")
writer.writerow([row[0], *parts, full_text])
return parts return parts
# === VERARBEITUNG === # === VERARBEITUNG ===
@@ -151,13 +116,13 @@ for i in range(start, min(start + DURCHLÄUFE, len(sheet_values))):
row = sheet_values[i] row = sheet_values[i]
print(f"[{time.strftime('%H:%M:%S')}] Verarbeite Zeile {i+1}: {row[0]}") print(f"[{time.strftime('%H:%M:%S')}] Verarbeite Zeile {i+1}: {row[0]}")
url, wiki_branche, umsatz = get_wikipedia_data(row[0]) url, wiki_branche, umsatz = get_wikipedia_data(row[0], row[1])
wiki, linkedin, umsatz_chat, new_cat, reason, fsm, techniker, techniker_reason = classify_company(row) wiki, linkedin, umsatz_chat, new_cat, reason, fsm, techniker, techniker_reason = classify_company(row)
values = [ values = [
wiki, wiki or wiki_branche,
linkedin, linkedin,
umsatz_chat, umsatz_chat or umsatz,
new_cat, new_cat,
reason, reason,
fsm, fsm,
@@ -167,7 +132,6 @@ for i in range(start, min(start + DURCHLÄUFE, len(sheet_values))):
techniker_reason techniker_reason
] ]
# Schreibe in die Spalten G bis P (716, nullbasiert also 615)
sheet.update(range_name=f"G{i+2}:P{i+2}", values=[values]) sheet.update(range_name=f"G{i+2}:P{i+2}", values=[values])
time.sleep(5) time.sleep(5)