Implementierung der Batch-Brancheneinstufung zur Kostenoptimierung

- FEATURE: Brancheneinstufung erfolgt nun in Batches (z.B. 20 Unternehmen pro API-Call), um die Token-Kosten drastisch zu senken.
- REFACTOR: Neue Funktion `evaluate_branches_batch` in `helpers.py` erstellt, die den komplexen Batch-Prompt generiert.
- REFACTOR: `reclassify_all_branches` in `data_processor.py` überarbeitet, um die Batch-Verarbeitung und das Ergebnis-Mapping zu steuern.
This commit is contained in:
2025-07-28 12:42:28 +00:00
parent 36e7ac157a
commit 1d29e217d0

View File

@@ -971,6 +971,97 @@ def evaluate_branche_chatgpt(company_name, website_summary, wiki_absatz):
"justification": f"Fehler bei der API-Kommunikation: {str(e)[:100]}" "justification": f"Fehler bei der API-Kommunikation: {str(e)[:100]}"
} }
def evaluate_branches_batch(companies_data):
"""
Führt eine kontextbasierte Brancheneinstufung für einen Batch von Unternehmen durch.
Sendet das Branchenschema nur einmal, um Kosten zu sparen.
Args:
companies_data (list): Eine Liste von Dictionaries, jedes mit 'row_num', 'name', 'summary', 'wiki'.
Returns:
list: Eine Liste von Dictionaries mit den Ergebnissen für jedes Unternehmen.
"""
logger = logging.getLogger(__name__)
# 1. Baue das ZIEL-BRANCHENSCHEMA als Textblock auf (wird nur einmal gesendet)
schema_text_parts = []
for i, (branch, details) in enumerate(Config.BRANCH_GROUP_MAPPING.items()):
schema_text_parts.append(f"{i+1}. Branche: {branch}")
if details.get("definition"):
schema_text_parts.append(f" Definition: {details['definition']}")
if details.get("beispiele"):
schema_text_parts.append(f" Beispiele: {details['beispiele']}")
ziel_branchenschema_text = "\n".join(schema_text_parts)
# 2. Baue die Liste der Unternehmensprofile für den Prompt auf
unternehmensprofile_text_parts = []
for i, company in enumerate(companies_data):
profil = [f"--- UNTERNEHMEN #{i+1} (Original-Zeilennummer: {company['row_num']}) ---"]
profil.append(f"- Name: {company.get('name', 'N/A')}")
if company.get('summary'):
profil.append(f"- Website-Zusammenfassung: {company['summary']}")
if company.get('wiki'):
profil.append(f"- Wikipedia-Auszug: {company['wiki']}")
unternehmensprofile_text_parts.append("\n".join(profil))
unternehmensprofile_text = "\n\n".join(unternehmensprofile_text_parts)
# 3. Baue den Master-Prompt zusammen
prompt_parts = [
"Du bist ein erfahrener Branchenanalyst. Deine Aufgabe ist es, eine Liste von Unternehmen präzise einer von 54 vordefinierten Branchenkategorien zuzuordnen. Nutze dafür ausschließlich das bereitgestellte ZIEL-BRANCHENSCHEMA.",
"\n--- ZIEL-BRANCHENSCHEMA (Deine einzig gültige Wissensbasis) ---",
ziel_branchenschema_text,
"\n--- ZU ANALYSIERENDE UNTERNEHMEN ---",
unternehmensprofile_text,
"\n--- DEINE AUFGABE ---",
f"Analysiere jedes der {len(companies_data)} Unternehmen Schritt für Schritt.",
"Vergleiche jedes Unternehmensprofil mit den Definitionen im ZIEL-BRANCHENSCHEMA.",
"Gib als Ergebnis eine JSON-Liste zurück, die exakt ein JSON-Objekt für jedes Unternehmen in der gleichen Reihenfolge enthält.",
"Jedes JSON-Objekt muss folgende Schlüssel haben: 'row_num', 'Branche', 'Konfidenz', 'Begruendung'.",
"Die 'row_num' muss exakt der 'Original-Zeilennummer' aus dem Input entsprechen.",
"Beispiel-Format für die Antwort: \n"
'''
[
{
"row_num": 123,
"Branche": "Maschinenbau",
"Konfidenz": "Hoch",
"Begruendung": "Das Unternehmen stellt komplexe Maschinen her, was der Definition entspricht."
},
{
"row_num": 456,
"Branche": "Facility Management",
"Konfidenz": "Mittel",
"Begruendung": "Bietet Dienstleistungen rund um Immobilien an, passt zur Definition."
}
]
'''
]
prompt = "\n".join(prompt_parts)
# 4. API-Aufruf
try:
response_str = call_openai_chat(prompt, temperature=0.0, model="gpt-4o", response_format_json=True)
if not response_str:
raise APIError("Keine Antwort von OpenAI erhalten.")
# Das Ergebnis sollte direkt eine Liste von Dictionaries sein
results_list = json.loads(response_str)
# Validierung, ob die Antwort eine Liste ist
if not isinstance(results_list, list):
logger.error(f"KI-Antwort ist keine Liste, sondern {type(results_list)}. Breche Batch ab.")
return None
return results_list
except Exception as e:
logger.error(f"Endgültiger FEHLER beim Batch-API-Aufruf: {e}")
return None
@retry_on_failure @retry_on_failure
def verify_wiki_article_chatgpt(company_name, parent_name, website, wiki_title, wiki_summary): def verify_wiki_article_chatgpt(company_name, parent_name, website, wiki_title, wiki_summary):
""" """