New standalone Python/FastAPI service for automatic compliance document scanning, LLM-based classification, IPFS archival, and gap analysis. Includes extractors (PDF, DOCX, XLSX, PPTX), keyword fallback classifier, compliance matrix, and full REST API on port 8098. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
81 lines
2.9 KiB
Python
81 lines
2.9 KiB
Python
"""Heuristic keyword-based classification fallback."""
|
|
|
|
# Keyword patterns per category — order matters (first match wins on tie)
|
|
KEYWORD_MAP: list[tuple[str, list[str]]] = [
|
|
("VVT", [
|
|
"verarbeitungsverzeichnis", "verzeichnis von verarbeitungstaetigkeiten",
|
|
"verarbeitungstaetigkeit", "art. 30", "art 30", "zweck der verarbeitung",
|
|
"kategorie betroffener personen", "datenkategorien",
|
|
]),
|
|
("TOM", [
|
|
"technisch-organisatorische massnahmen", "technische und organisatorische",
|
|
"art. 32", "art 32", "zutrittskontrolle", "zugangskontrolle",
|
|
"zugriffskontrolle", "verschluesselungskonzept", "pseudonymisierung",
|
|
]),
|
|
("DSE", [
|
|
"datenschutzerklaerung", "datenschutzhinweise", "privacy policy",
|
|
"informationspflichten", "art. 13", "art. 14", "art 13", "art 14",
|
|
"betroffenenrechte", "verantwortlicher im sinne",
|
|
]),
|
|
("AVV", [
|
|
"auftragsverarbeitung", "auftragsverarbeitungsvertrag",
|
|
"art. 28", "art 28", "weisungsgebundenheit", "unterauftragnehmer",
|
|
"subunternehmer",
|
|
]),
|
|
("DSFA", [
|
|
"datenschutz-folgenabschaetzung", "folgenabschaetzung",
|
|
"art. 35", "art 35", "risikoanalyse", "hohes risiko",
|
|
"systematische beschreibung",
|
|
]),
|
|
("Loeschkonzept", [
|
|
"loeschkonzept", "loeschfristen", "aufbewahrungsfrist",
|
|
"loeschung personenbezogener", "speicherdauer", "vorhaltefrist",
|
|
]),
|
|
("Einwilligung", [
|
|
"einwilligung", "einwilligungserklaerung", "consent",
|
|
"freiwillige zustimmung", "widerruf der einwilligung",
|
|
]),
|
|
("Vertrag", [
|
|
"vertrag", "vereinbarung", "vertragspartner",
|
|
"leistungsbeschreibung", "vertragsgegenstand",
|
|
]),
|
|
("Richtlinie", [
|
|
"richtlinie", "policy", "datenschutzrichtlinie", "leitlinie",
|
|
"verhaltensregeln", "organisationsanweisung",
|
|
]),
|
|
("Schulungsnachweis", [
|
|
"schulungsnachweis", "schulung", "training", "datenschutzschulung",
|
|
"teilnahmebestaetigung", "fortbildung datenschutz",
|
|
]),
|
|
]
|
|
|
|
MAX_KEYWORD_CONFIDENCE = 0.3
|
|
|
|
|
|
def keyword_classify(text: str, filename: str) -> dict:
|
|
"""Classify document by keyword matching. Confidence capped at 0.3."""
|
|
combined = (filename + " " + text).lower()
|
|
|
|
best_category = "Sonstiges"
|
|
best_score = 0
|
|
|
|
for category, keywords in KEYWORD_MAP:
|
|
score = sum(1 for kw in keywords if kw in combined)
|
|
if score > best_score:
|
|
best_score = score
|
|
best_category = category
|
|
|
|
if best_score == 0:
|
|
return {
|
|
"classification": "Sonstiges",
|
|
"confidence": 0.1,
|
|
"reasoning": "Keine Schluesselwoerter gefunden (Keyword-Fallback)",
|
|
}
|
|
|
|
confidence = min(best_score * 0.1, MAX_KEYWORD_CONFIDENCE)
|
|
return {
|
|
"classification": best_category,
|
|
"confidence": confidence,
|
|
"reasoning": f"Keyword-Fallback: {best_score} Treffer fuer {best_category}",
|
|
}
|