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:
@@ -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 (7–16, nullbasiert also 6–15)
|
|
||||||
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)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user