v1.2.0 - Bugfix & Robuste Branchen-Regel-Erkennung
- Bugfix: Behebt den Fehler, bei dem keine branchenspezifischen Regeln generiert wurden, weil die Schwellenwerte zu restriktiv waren. - Die Schwellenwerte für die minimale Sample-Anzahl und die prozentuale Branchen-Reinheit wurden gelockert und sind nun am Anfang des Skripts konfigurierbar. - Verbessertes Logging: Das Skript gibt nun detailliert Auskunft, warum ein Department als branchenspezifisch eingestuft oder warum es verworfen wurde.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# knowledge_base_builder.py
|
||||
|
||||
__version__ = "v1.1.0"
|
||||
__version__ = "v1.2.0"
|
||||
|
||||
import logging
|
||||
import json
|
||||
@@ -17,13 +17,10 @@ EXACT_MATCH_OUTPUT_FILE = "exact_match_map.json"
|
||||
KEYWORD_RULES_OUTPUT_FILE = "keyword_rules.json"
|
||||
|
||||
DEPARTMENT_PRIORITIES = {
|
||||
# --- Tier 1: Ultra-spezifische Nischen (höchste Priorität) ---
|
||||
"Fuhrparkmanagement": 1,
|
||||
"Legal": 1,
|
||||
"Baustofflogistik": 1,
|
||||
"Baustoffherstellung": 1,
|
||||
|
||||
# --- Tier 2: Kern-Fachbereiche (sortiert nach Kontakthäufigkeit) ---
|
||||
"Field Service Management / Kundenservice": 2,
|
||||
"IT": 3,
|
||||
"Production Maintenance / Wartung Produktion": 4,
|
||||
@@ -32,21 +29,14 @@ DEPARTMENT_PRIORITIES = {
|
||||
"Supply Chain Management": 7,
|
||||
"Finanzen": 8,
|
||||
"Technik": 8,
|
||||
|
||||
# --- Tier 3: Übergreifende & Allgemeine Funktionen ---
|
||||
"Management / GF / C-Level": 10,
|
||||
"Logistik": 11,
|
||||
"Vertrieb": 12,
|
||||
"Transportwesen": 13,
|
||||
|
||||
# --- Tier 4: Auffang-Kategorien (niedrigste Priorität) ---
|
||||
"Berater": 20,
|
||||
"Undefined": 99
|
||||
}
|
||||
|
||||
# NEU: Definition von Branchen-Gruppen für die kontextsensitive Regelerstellung
|
||||
# Key: Ein einfaches, normalisiertes Schlüsselwort für die Gruppe
|
||||
# Value: Eine Liste von d365_branch_detail Werten aus Ihrer config.py
|
||||
BRANCH_GROUP_RULES = {
|
||||
"bau": [
|
||||
"Baustoffhandel", "Baustoffindustrie",
|
||||
@@ -63,8 +53,12 @@ BRANCH_GROUP_RULES = {
|
||||
"Braune & Weiße Ware", "Fenster / Glas", "Getränke", "Möbel", "Agrar, Pellets"
|
||||
]
|
||||
}
|
||||
# Schwellenwert: Wenn >X% der Jobtitel eines Departments in einer Branchengruppe liegen, wird es spezifisch
|
||||
BRANCH_SPECIFICITY_THRESHOLD = 0.8
|
||||
|
||||
# --- NEU: Angepasste und konfigurierbare Schwellenwerte ---
|
||||
# Ein Department muss mindestens so viele Einträge haben, um eine Branchen-Regel zu bekommen.
|
||||
MIN_SAMPLES_FOR_BRANCH_RULE = 5
|
||||
# Wenn >X% der Jobtitel eines Departments in EINER Branchengruppe liegen, gilt es als spezifisch.
|
||||
BRANCH_SPECIFICITY_THRESHOLD = 0.7
|
||||
|
||||
STOP_WORDS = {
|
||||
'manager', 'leiter', 'head', 'lead', 'senior', 'junior', 'direktor', 'director',
|
||||
@@ -77,12 +71,7 @@ STOP_WORDS = {
|
||||
|
||||
|
||||
def build_knowledge_base():
|
||||
"""
|
||||
Hauptfunktion zur Erstellung der Wissensbasis.
|
||||
Liest Rohdaten, analysiert sie und erstellt JSON-Dateien für exakte und Keyword-basierte Übereinstimmungen.
|
||||
Erstellt automatisch Regeln für branchenspezifische Departments.
|
||||
"""
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.info(f"Starte Erstellung der Wissensbasis (Version {__version__})...")
|
||||
|
||||
@@ -90,7 +79,7 @@ def build_knowledge_base():
|
||||
df = gsh.get_sheet_as_dataframe(SOURCE_SHEET_NAME)
|
||||
|
||||
if df is None or df.empty:
|
||||
logger.critical(f"Konnte keine Daten aus '{SOURCE_SHEET_NAME}' laden oder das Tabellenblatt ist leer. Abbruch.")
|
||||
logger.critical(f"Konnte keine Daten aus '{SOURCE_SHEET_NAME}' laden. Abbruch.")
|
||||
return
|
||||
|
||||
df.columns = [col.strip() for col in df.columns]
|
||||
@@ -112,7 +101,7 @@ def build_knowledge_base():
|
||||
try:
|
||||
with open(EXACT_MATCH_OUTPUT_FILE, 'w', encoding='utf-8') as f:
|
||||
json.dump(exact_match_map, f, indent=4, ensure_ascii=False)
|
||||
logger.info(f"-> '{EXACT_MATCH_OUTPUT_FILE}' mit {len(exact_match_map)} einzigartigen Jobtiteln erfolgreich erstellt.")
|
||||
logger.info(f"-> '{EXACT_MATCH_OUTPUT_FILE}' mit {len(exact_match_map)} Titeln erstellt.")
|
||||
except IOError as e:
|
||||
logger.error(f"Fehler beim Schreiben der Datei '{EXACT_MATCH_OUTPUT_FILE}': {e}")
|
||||
return
|
||||
@@ -141,7 +130,8 @@ def build_knowledge_base():
|
||||
department_branches = branches_by_department.get(department, [])
|
||||
total_titles_in_dept = len(department_branches)
|
||||
|
||||
if total_titles_in_dept > 10: # Mindestanzahl an Datenpunkten, um eine Regel zu erstellen
|
||||
# Angepasste Logik mit transparentem Logging
|
||||
if total_titles_in_dept >= MIN_SAMPLES_FOR_BRANCH_RULE:
|
||||
branch_group_counts = Counter()
|
||||
for branch_name in department_branches:
|
||||
for group_keyword, d365_names in BRANCH_GROUP_RULES.items():
|
||||
@@ -150,16 +140,24 @@ def build_knowledge_base():
|
||||
|
||||
if branch_group_counts:
|
||||
most_common_group, count = branch_group_counts.most_common(1)[0]
|
||||
if (count / total_titles_in_dept) > BRANCH_SPECIFICITY_THRESHOLD:
|
||||
logger.info(f" -> Department '{department}' ist spezifisch für Branche '{most_common_group}' ({count/total_titles_in_dept:.0%}). Regel wird hinzugefügt.")
|
||||
ratio = count / total_titles_in_dept
|
||||
if ratio > BRANCH_SPECIFICITY_THRESHOLD:
|
||||
logger.info(f" -> Department '{department}' ist spezifisch für Branche '{most_common_group}' ({ratio:.0%}). Regel wird hinzugefügt.")
|
||||
rule["required_branch_keywords"] = [most_common_group]
|
||||
else:
|
||||
logger.debug(f" -> Department '{department}' nicht spezifisch genug. Dominante Branche '{most_common_group}' nur bei {ratio:.0%}, benötigt >{BRANCH_SPECIFICITY_THRESHOLD:.0%}.")
|
||||
else:
|
||||
logger.debug(f" -> Department '{department}' konnte keiner Branchen-Gruppe zugeordnet werden.")
|
||||
else:
|
||||
logger.debug(f" -> Department '{department}' hat zu wenige Datenpunkte ({total_titles_in_dept} < {MIN_SAMPLES_FOR_BRANCH_RULE}) für eine Branchen-Regel.")
|
||||
|
||||
|
||||
keyword_rules[department] = rule
|
||||
|
||||
try:
|
||||
with open(KEYWORD_RULES_OUTPUT_FILE, 'w', encoding='utf-8') as f:
|
||||
json.dump(keyword_rules, f, indent=4, ensure_ascii=False)
|
||||
logger.info(f"-> '{KEYWORD_RULES_OUTPUT_FILE}' mit Regeln für {len(keyword_rules)} Departments erfolgreich erstellt.")
|
||||
logger.info(f"-> '{KEYWORD_RULES_OUTPUT_FILE}' mit Regeln für {len(keyword_rules)} Departments erstellt.")
|
||||
except IOError as e:
|
||||
logger.error(f"Fehler beim Schreiben der Datei '{KEYWORD_RULES_OUTPUT_FILE}': {e}")
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user