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 88f8ffb323
commit cf250fe4be

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 time
import csv
import pandas as pd
import gspread
import openai
@@ -12,10 +13,11 @@ from oauth2client.service_account import ServiceAccountCredentials
from datetime import datetime
# === 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"
CREDENTIALS = "service_account.json"
LANG = "de"
LOG_CSV = "gpt_antworten_log.csv"
DURCHLÄUFE = int(input("Wieviele Zeilen sollen überprüft werden? "))
# === 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)
print(f"Starte bei Zeile {start+1}")
# === WIKIPEDIA KONFIG ===
wikipedia.set_lang(LANG)
# === SYSTEM PROMPT ===
branches = [
"Hersteller / Produzenten > Maschinenbau",
"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"
# (gekürzt für Übersicht wie gehabt einfügen)
]
system_prompt = {
"role": "system",
"content": (
"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. "
"Ziel ist es, Unternehmen zu identifizieren, die mehr als 50 Techniker im Außeneinsatz beschäftigen (z.B. Servicetechniker, Instandhalter, Medizintechniker etc.).\n\n"
"Dir liegt pro Unternehmen eine strukturierte Eingabezeile vor, bestehend aus:\n"
"Firmenname; Website; Ort; Aktuelle Einstufung; Beschreibung der Branche Extern\n\n"
"Bitte führe für jede Firma eine fundierte Bewertung durch:\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"
"Bitte beziehe dich ausschließlich auf das konkret genannte Unternehmen. Ähnlich klingende Firmennamen dürfen nicht verwendet werden.\n"
"FSM steht für Field Service Management Software zur Planung und Unterstützung mobiler Techniker.\n"
"Ziel ist es, Unternehmen mit >50 Technikern im Außeneinsatz zu identifizieren.\n\n"
"Struktur: Firmenname; Website; Ort; Aktuelle Einstufung; Beschreibung der Branche Extern\n\n"
"Gib deine Antwort im CSV-Format (1 Zeile, 8 Spalten, durch Semikolon getrennt):\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)
)
}
# === HILFSFUNKTIONEN ===
def get_wikipedia_data(name):
for suchbegriff in [name.strip(), " ".join(name.split()[:2])]:
# === WIKIPEDIA DATEN LADEN ===
def get_wikipedia_data(name, website_hint=""):
begriffe = [name.strip(), " ".join(name.split()[:2])]
if website_hint:
begriffe.append(website_hint.split(".")[1])
for suchbegriff in begriffe:
try:
page = wikipedia.page(suchbegriff, auto_suggest=False)
if name.lower().split()[0] not in page.title.lower():
continue
url = page.url
html = requests.get(url).text
soup = BeautifulSoup(html, 'html.parser')
@@ -121,12 +82,13 @@ def get_wikipedia_data(name):
umsatz = td.text.strip()
if not branche:
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."
except:
continue
return "", "k.A.", "k.A."
# === GPT BEWERTUNG ===
def classify_company(row):
user_prompt = {
"role": "user",
@@ -137,13 +99,16 @@ def classify_company(row):
messages=[system_prompt, user_prompt],
temperature=0
)
text = response.choices[0].message.content.strip()
lines = text.splitlines()
full_text = response.choices[0].message.content.strip()
lines = full_text.splitlines()
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 []
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
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
# === VERARBEITUNG ===
@@ -151,13 +116,13 @@ for i in range(start, min(start + DURCHLÄUFE, len(sheet_values))):
row = sheet_values[i]
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)
values = [
wiki,
wiki or wiki_branche,
linkedin,
umsatz_chat,
umsatz_chat or umsatz,
new_cat,
reason,
fsm,
@@ -167,7 +132,6 @@ for i in range(start, min(start + DURCHLÄUFE, len(sheet_values))):
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])
time.sleep(5)