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 1d29e217d0
commit 9b682a8617

View File

@@ -1462,27 +1462,23 @@ class DataProcessor:
self.logger.info(f"FSM-Pitch-Generierung abgeschlossen. {processed_count} Zeilen bearbeitet.") 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. Führt für alle relevanten Zeilen eine neue Brancheneinstufung (v2.0) in Batches durch.
Dieser Modus ist ideal, um nach einer Änderung der Branchen-Definitionen
den gesamten Datenbestand zu aktualisieren.
""" """
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(): if not self.sheet_handler.load_data():
return return
all_data = self.sheet_handler.get_all_data_with_headers() all_data = self.sheet_handler.get_all_data_with_headers()
header_rows = self.sheet_handler._header_rows header_rows = self.sheet_handler._header_rows
effective_start = start_sheet_row if start_sheet_row is not None else header_rows + 1 effective_start = start_sheet_row if start_sheet_row is not None else header_rows + 1
tasks = [] tasks = []
for i in range(effective_start - 1, len(all_data)): for i in range(effective_start - 1, len(all_data)):
if limit is not None and len(tasks) >= limit: if limit is not None and len(tasks) >= limit:
break break
row_data = all_data[i] row_data = all_data[i]
company_name = self._get_cell_value_safe(row_data, "CRM Name").strip() company_name = self._get_cell_value_safe(row_data, "CRM Name").strip()
if company_name: if company_name:
@@ -1497,43 +1493,56 @@ class DataProcessor:
all_sheet_updates = [] all_sheet_updates = []
now_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") now_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
for task in tasks: # Verarbeite die Tasks in Batches
row_num = task['row_num'] 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'] 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: if batch_results:
result = evaluate_branche_chatgpt( # Ordne die Ergebnisse den richtigen Zeilen zu
company_name=self._get_cell_value_safe(row_data, "CRM Name"), results_by_row = {res['row_num']: res for res in batch_results}
website_summary=self._get_cell_value_safe(row_data, "Website Zusammenfassung"),
wiki_absatz=self._get_cell_value_safe(row_data, "Wiki Absatz")
)
# Updates für die drei Zielspalten vorbereiten for task in batch_tasks:
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')]]}) row_num = task['row_num']
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')]]}) result = results_by_row.get(row_num)
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 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]]}) 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: # Finalen Batch-Update senden
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
if all_sheet_updates: 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.sheet_handler.batch_update_cells(all_sheet_updates)
self.logger.info("Branchen-Neubewertung abgeschlossen.") self.logger.info("Branchen-Neubewertung im Batch-Modus abgeschlossen.")
# ========================================================================== # ==========================================================================