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:43:36 +00:00
parent 5aad6082b1
commit 986dca714c

View File

@@ -1462,78 +1462,87 @@ class DataProcessor:
self.logger.info(f"FSM-Pitch-Generierung abgeschlossen. {processed_count} Zeilen bearbeitet.")
def reclassify_all_branches(self, start_sheet_row=None, limit=None):
def reclassify_all_branches(self, start_sheet_row=None, limit=None, batch_size=20):
"""
Führt für alle relevanten Zeilen eine neue Brancheneinstufung (v2.0) durch.
Dieser Modus ist ideal, um nach einer Änderung der Branchen-Definitionen
den gesamten Datenbestand zu aktualisieren.
Führt für alle relevanten Zeilen eine neue Brancheneinstufung (v2.0) in Batches durch.
"""
self.logger.info(f"Starte Modus 'reclassify_branches'. Bereich: {start_sheet_row or 'Start'}, Limit: {limit or 'Unbegrenzt'}")
self.logger.info(f"Starte Modus 'reclassify_branches' im Batch-Modus (Größe: {batch_size}). Bereich: {start_sheet_row or 'Start'}, Limit: {limit or 'Unbegrenzt'}")
if not self.sheet_handler.load_data():
return
all_data = self.sheet_handler.get_all_data_with_headers()
header_rows = self.sheet_handler._header_rows
effective_start = start_sheet_row if start_sheet_row is not None else header_rows + 1
tasks = []
for i in range(effective_start - 1, len(all_data)):
if limit is not None and len(tasks) >= limit:
break
row_data = all_data[i]
company_name = self._get_cell_value_safe(row_data, "CRM Name").strip()
if company_name:
tasks.append({'row_num': i + 1, 'data': row_data})
if not tasks:
self.logger.info("Keine Zeilen zur Neubewertung gefunden.")
return
self.logger.info(f"{len(tasks)} Zeilen für die Neubewertung der Branche identifiziert.")
all_sheet_updates = []
now_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
for task in tasks:
row_num = task['row_num']
row_data = task['data']
# Verarbeite die Tasks in Batches
for i in range(0, len(tasks), batch_size):
batch_tasks = tasks[i:i + batch_size]
self.logger.info(f"Verarbeite Batch {i//batch_size + 1}/{(len(tasks) + batch_size - 1)//batch_size} (Zeilen {batch_tasks[0]['row_num']} bis {batch_tasks[-1]['row_num']})...")
# Bereite die Daten für den Batch-Prompt vor
companies_data_for_prompt = []
for task in batch_tasks:
row_data = task['data']
companies_data_for_prompt.append({
"row_num": task['row_num'],
"name": self._get_cell_value_safe(row_data, "CRM Name"),
"summary": self._get_cell_value_safe(row_data, "Website Zusammenfassung"),
"wiki": self._get_cell_value_safe(row_data, "Wiki Absatz")
})
self.logger.debug(f"Bewerte Branche für Zeile {row_num}...")
# Rufe die neue Batch-Funktion auf
batch_results = evaluate_branches_batch(companies_data_for_prompt)
try:
result = evaluate_branche_chatgpt(
company_name=self._get_cell_value_safe(row_data, "CRM Name"),
website_summary=self._get_cell_value_safe(row_data, "Website Zusammenfassung"),
wiki_absatz=self._get_cell_value_safe(row_data, "Wiki Absatz")
)
if batch_results:
# Ordne die Ergebnisse den richtigen Zeilen zu
results_by_row = {res['row_num']: res for res in batch_results}
# Updates für die drei Zielspalten vorbereiten
all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Vorschlag Branche"]["index"] + 1)}{row_num}', 'values': [[result.get('branch')]]})
all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Branche Konfidenz"]["index"] + 1)}{row_num}', 'values': [[result.get('confidence')]]})
all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Begruendung Abweichung Branche"]["index"] + 1)}{row_num}', 'values': [[result.get('justification')]]})
# Auch den Timestamp aktualisieren
all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Timestamp letzte Pruefung"]["index"] + 1)}{row_num}', 'values': [[now_timestamp]]})
for task in batch_tasks:
row_num = task['row_num']
result = results_by_row.get(row_num)
if result:
all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Vorschlag Branche"]["index"] + 1)}{row_num}', 'values': [[result.get('Branche')]]})
all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Branche Konfidenz"]["index"] + 1)}{row_num}', 'values': [[result.get('Konfidenz')]]})
all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Begruendung Abweichung Branche"]["index"] + 1)}{row_num}', 'values': [[result.get('Begruendung')]]})
else:
self.logger.error(f"Kein Ergebnis für Zeile {row_num} im Batch-Resultat gefunden.")
all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Vorschlag Branche"]["index"] + 1)}{row_num}', 'values': [['FEHLER (Batch-Antwort)']]} )
# Timestamp immer setzen
all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Timestamp letzte Pruefung"]["index"] + 1)}{row_num}', 'values': [[now_timestamp]]})
else:
self.logger.error(f"Batch-Verarbeitung für Zeilen {batch_tasks[0]['row_num']} bis {batch_tasks[-1]['row_num']} fehlgeschlagen. Setze Fehlerstatus.")
for task in batch_tasks:
row_num = task['row_num']
all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Vorschlag Branche"]["index"] + 1)}{row_num}', 'values': [['FEHLER (Batch-API)']]} )
all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Timestamp letzte Pruefung"]["index"] + 1)}{row_num}', 'values': [[now_timestamp]]})
except Exception as e:
self.logger.error(f"FEHLER bei Branchen-Neubewertung für Zeile {row_num}: {e}")
all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Vorschlag Branche"]["index"] + 1)}{row_num}', 'values': [['FEHLER (Prozess)']]} )
# Batch-Update Logik (vereinfacht, um es hier zu zeigen)
if len(all_sheet_updates) >= 200: # 50 Zeilen * 4 Updates pro Zeile
self.logger.info(f"Sende Batch-Update für {len(all_sheet_updates)//4} Branchen...")
self.sheet_handler.batch_update_cells(all_sheet_updates)
all_sheet_updates = []
time.sleep(1)
# Letzten Batch senden
# Finalen Batch-Update senden
if all_sheet_updates:
self.logger.info(f"Sende finalen Batch-Update für {len(all_sheet_updates)//4} Branchen...")
self.logger.info(f"Sende finales Batch-Update für {len(tasks)} bewertete Branchen...")
self.sheet_handler.batch_update_cells(all_sheet_updates)
self.logger.info("Branchen-Neubewertung abgeschlossen.")
self.logger.info("Branchen-Neubewertung im Batch-Modus abgeschlossen.")
# ==========================================================================