Warum RAG-Pipelines bei naiver Anonymisierung versagen

Retrieval-Augmented Generation (RAG) stützt sich auf die semantische Ähnlichkeit zwischen einer Nutzerfrage und indexierten Dokumentabschnitten. Fragt jemand „Was hat Maria Rossi letzten Monat bestellt?“, sucht das Abrufsystem nach inhaltlich passenden Abschnitten. Ein großes Sprachmodell (LLM) formuliert aus dem gefundenen Kontext eine Antwort.

Das Problem entsteht beim Einlesen der Dokumente. Wenn Sie Dokumente vor der Erstellung ihrer Vektordarstellungen anonymisieren und dabei denselben Wert unterschiedlich ersetzen, geht die semantische Verbindung verloren:

  • Dokument A: „Maria Rossi“ → [PERSON_1]
  • Dokument B: „Maria Rossi“ → [PERSON_3]
  • Dokument C: „M. Rossi“ → [PERSON_7]

Die drei Dokumente sollten gemeinsam gefunden werden. Im Index erscheinen sie nun aber so, als bezögen sie sich auf drei verschiedene Personen. Dadurch bricht die Trefferquote beim Abruf ein. Das Sprachmodell erstellt aus nur einem Bruchteil des relevanten Kontexts unvollständige Antworten.

Das Problem: Inkonsistente Anonymisierung zerstört die Suche

Übliche Anonymisierungswerkzeuge sind für einzelne Dokumente und Sitzungen ausgelegt. Sie vergeben Platzhalter wie [PERSON_1] und [PERSON_2] der Reihe nach und speichern die Zuordnung nicht dauerhaft. Verarbeiten Sie dasselbe Dokument zweimal, können unterschiedliche Token entstehen.

Für RAG-Pipelines hat das drei Folgen:

  • Die Suche über mehrere Dokumente hinweg scheitert: Derselbe Wert hat in verschiedenen Dokumenten unterschiedliche Token. Die Ähnlichkeitssuche übersieht deshalb zusammengehörige Abschnitte.
  • Das schrittweise Erweitern des Index wird problematisch: Neue Dokumente beginnen mit einer neuen Tokenfolge. Dadurch können Token mit vorhandenen kollidieren. Ein neues [PERSON_1] kann eine andere Person bezeichnen.
  • Die Anonymisierung der Suchfrage passt nicht zum Index: Wenn Sie eine Nutzerfrage vor der Suche anonymisieren, müssen deren Token genau mit den Token im Index übereinstimmen.

Die Lösung: konsistente Pseudonymisierung

Bei konsistenter Pseudonymisierung gilt eine feste Zuordnung: Derselbe eingegebene Wert erhält immer dasselbe Token. Eine dauerhaft gespeicherte Tabelle, etwa in einer Datenbank oder einem Schlüssel-Wert-Speicher, hält die Zuordnung für alle Dokumente und Sitzungen bereit.

Dafür gibt es zwei Wege:

Ansatz 1: Token aus Hashwerten

Berechnen Sie aus dem Wert einer Person einen Hashwert mit geheimem Schlüssel. Gleiche Eingaben ergeben denselben Hashwert. Zwei Vorkommen von „Maria Rossi“ erhalten somit identische Token. Ein geheimer Schlüssel (HMAC) verhindert die Rückrechnung.

import hmac, hashlib

HMAC_KEY = b"your-secret-key-32-bytes-minimum"

def consistent_token(entity_type: str, entity_value: str) -> str:
    """Erzeugt ein stabiles, gleichbleibendes Token für einen Wert."""
    digest = hmac.new(
        HMAC_KEY,
        f"{entity_type}:{entity_value.strip().lower()}".encode(),
        hashlib.sha256
    ).hexdigest()[:8]
    return f"[{entity_type}_{digest}]"

# Beispiele:
# consistent_token("PERSON", "Maria Rossi") -> "[PERSON_3a7f9c2b]"  (immer)
# consistent_token("PERSON", "maria rossi") -> "[PERSON_3a7f9c2b]"  (gleich)
# consistent_token("PERSON", "John Smith")  -> "[PERSON_b1e4a8d6]"  (anders)

Ansatz 2: Nachschlagetabelle mit fortlaufenden Nummern

Speichern Sie die Zuordnung von Werten zu Token dauerhaft. Beim ersten Auftreten erhält ein Wert das nächste verfügbare Token seiner Art. Bei späteren Vorkommen verwenden Sie die gespeicherte Zuordnung.

import json, pathlib

class PersistentMapping:
    def __init__(self, path: str):
        self.path = pathlib.Path(path)
        self.data = json.loads(self.path.read_text()) if self.path.exists() else {}
        self.counters = {}

    def get_token(self, entity_type: str, entity_value: str) -> str:
        key = f"{entity_type}:{entity_value.strip().lower()}"
        if key not in self.data:
            count = self.counters.get(entity_type, 0) + 1
            self.counters[entity_type] = count
            self.data[key] = f"[{entity_type}_{count}]"
            self.path.write_text(json.dumps(self.data))
        return self.data[key]

    def reverse(self, token: str) -> str | None:
        reverse_map = {v: k.split(":", 1)[1] for k, v in self.data.items()}
        return reverse_map.get(token)

mapping = PersistentMapping("entity_mapping.json")
print(mapping.get_token("PERSON", "Maria Rossi"))  # [PERSON_1]
print(mapping.get_token("PERSON", "Maria Rossi"))  # [PERSON_1] (gleich)
print(mapping.get_token("PERSON", "John Smith"))   # [PERSON_2]

Umkehrbare Tokenisierung mit anonym.legal

anonym.legal bietet umkehrbare Tokenisierung, beispielsweise über das Werkzeug anonym_legal_anonymize_text seines MCP-Servers. Jeder Aufruf liefert eine session_id. Die Zuordnung der Token wird verschlüsselt gespeichert: standardmäßig für 24 Stunden oder mit der Einstellung persistent für bis zu 30 Tage. Wenn die Zuordnung über viele Dokumente eines gesamten Bestands hinweg gleich bleiben soll, führen Sie eine eigene Tabelle wie oben gezeigt. Angaben zur REST-Schnittstelle finden Sie in der API-Dokumentation bei anonym.legal.

// anonym.legal MCP-Server (Paket: anonym-legal-mcp-server)
// Werkzeug: anonym_legal_anonymize_text
{
  "text": "Maria Rossi ordered from Berlin on Jan 15.",
  "mode": "tokenize",           // umkehrbares Ersetzen (Standard)
  "persistence": "persistent",  // Zuordnung 30 Tage gespeichert; "session" = 24 Stunden (Standard)
  "sessionName": "rag-corpus-v1"
}

// Die Antwort enthält anonymized_text und eine session_id.
// Bewahren Sie die session_id auf, um die ursprünglichen Werte wiederherzustellen.

Welche Arten personenbezogener Daten für RAG wichtig sind

Die Datenarten beeinflussen die Suche unterschiedlich stark. Pseudonymisieren Sie vor allem Werte konsistent, nach denen gesucht wird oder auf die mehrere Dokumente verweisen:

Datenart Einfluss auf die Suche Empfehlung
Personennamen Sehr hoch – häufigster Suchbegriff Immer konsistent pseudonymisieren
Organisationen Hoch – häufig in geschäftlich genutzten RAG-Systemen Konsistent pseudonymisieren
Orte und Adressen Mittel – abhängig vom Anwendungsfall Stadt und Land konsistent pseudonymisieren; Straßenadressen entfernen
Kennungen (Konto, Krankenakte) Hoch – Suchfragen mit exakter Übereinstimmung Immer konsistent behandeln; die Suche nach Kennungen erfordert exakte Übereinstimmung
Datumsangaben Gering bis mittel – relative Zeitangaben sind wichtig Konkrete Daten entfernen; relative Zeitangaben erhalten
E-Mail-Adressen und Telefonnummern Gering – danach wird selten gesucht Vollständig entfernen; für die Suche nicht erforderlich

Der Entschlüsselungsschritt: ursprüngliche Werte nach der Suche wiederherstellen

Wenn die RAG-Pipeline eine Antwort mit pseudonymisierten Token zurückgibt, müssen Sie vor der Anzeige die ursprünglichen Werte wiederherstellen. Das ist der Schritt zum Rückgängigmachen der Pseudonymisierung:

// Werkzeug: anonym_legal_detokenize_text
{
  "text": "<PERSON_1> placed order #<ID_1> on <DATE_1>.",
  "session_id": "<session_id aus der Antwort von anonymize_text>"
}

// Gibt den Text mit den ursprünglichen Werten zurück,
// solange die Sitzung nicht abgelaufen ist.

Diesen Schritt sollten nur berechtigte Personen ausführen können. Setzen Sie eine rollenbasierte Zugriffskontrolle um: Analysten können den pseudonymisierten Index abfragen. Nur berechtigte Datenverantwortliche dürfen Antworten mit wiederhergestellten Werten sehen.

Compliance: Erwägungsgrund 26 der DSGVO und Artikel 10 der EU-KI-Verordnung

Erwägungsgrund 26 der DSGVO unterscheidet anonyme Informationen, die keiner identifizierten oder identifizierbaren Person zugeordnet werden können, von personenbezogenen Daten. Anonyme Informationen fallen nicht unter die DSGVO. Eine konsistente Pseudonymisierung mit getrennt gespeicherter und zugriffsgeschützter Zuordnungstabelle erfüllt diesen Maßstab nicht: Die Daten bleiben personenbezogen, weil mit der Zuordnung eine erneute Identifizierung möglich ist. Für pseudonymisierte Daten gelten aber geringere Pflichten, und die Pseudonymisierung ist nach Artikel 32 als Sicherheitsmaßnahme anerkannt.

Artikel 10 der EU-KI-Verordnung verlangt für Trainings-, Validierungs- und Testdaten von Hochrisiko-KI-Systemen geeignete Daten-Governance- und Datenverwaltungsverfahren. Dazu gehören Maßnahmen, um Verzerrungen zu erkennen und zu korrigieren sowie Relevanz und Repräsentativität sicherzustellen. Ein konsistent pseudonymisierter RAG-Dokumentbestand mit getrennt gespeicherter und zugriffsgeschützter Zuordnungstabelle kann eine technische Maßnahme sein, die solche Verfahren und den Datenschutz durch Technikgestaltung nach Artikel 25 DSGVO unterstützt. Für sich genommen stellt sie die Einhaltung keiner der beiden Vorschriften sicher.

Leistung: Wartezeit und Stapelverarbeitung

Der Aufruf eines gehosteten Dienstes fügt beim Einlesen der Dokumente eine Anfrage über das Netzwerk hinzu:

  • Wartezeit der API: Sie hängt von Textlänge, Sprache und Netzwerk ab. Messen Sie sie in Ihrer eigenen Pipeline.
  • Stapelverarbeitung: Die Stapel-API von anonym.legal nimmt je nach Tarif 5, 20, 50 oder 100 Texte pro Anfrage an. Einzelheiten stehen in der API-Dokumentation bei anonym.legal.
  • Lokale Zwischenspeicherung: Speichern Sie die Sitzungszuordnung nach dem ersten Aufruf lokal zwischen. Bei weiteren Dokumenten rufen Sie die API nur für neue Werte auf.
  • Aufwand für Vektordarstellungen: Anonymisierter Text hat etwas andere semantische Eigenschaften als der Originaltext. Verwenden Sie durchgehend dasselbe Modell für Vektordarstellungen. Mischen Sie keine Vektordarstellungen anonymisierter und nicht anonymisierter Texte.

Grenzen und ehrliche Einschränkungen

Konsistente Pseudonymisierung hat in einer RAG-Pipeline Grenzen. Weil derselbe Wert immer dasselbe Token erhält, kann jemand durch den Vergleich vieler Token aus verschiedenen Dokumenten Personen möglicherweise wieder identifizieren. Pseudonymisierte Daten bleiben nach der DSGVO personenbezogene Daten. Das Verfahren passt auch nicht zu jedem Anwendungsfall: Wenn beim Abruf der echte Wert benötigt wird, etwa um einen namentlich bekannten Kunden zu kontaktieren, ist ein gesonderter, zugriffsgeschützter Schritt zur Wiederherstellung erforderlich. Die Pseudonymisierung schützt den Index, aber nicht jede Stelle, die seine Daten anschließend nutzt.

🔨

MCP-Server: Datenschutz in Claude Desktop und Cursor

6 MCP-Verarbeitungsarten zur Anonymisierung von KI-Abläufen in Claude Desktop, Cursor und VS Code.

Weiterlesen →
🔒

Personenbezogene Daten in LLM-Eingaben

Was geschieht, wenn personenbezogene Daten in ein großes Sprachmodell gelangen, und welche technischen Maßnahmen dies verhindern.

Weiterlesen →
📈

Anonymisierung und Pseudonymisierung im Vergleich

Der rechtliche und technische Unterschied und wann welches Verfahren nach der DSGVO geeignet ist.

Weiterlesen →

RAG-Pipelines mit Datenschutz aufbauen

Anonymisierung für RAG, das Einlesen von Dokumenten und KI-Abläufe. Umkehrbare Tokenisierung und Stapelverarbeitung, ausgerichtet an Ihren Pflichten nach der DSGVO.

Gilt das für Ihre Organisation?

Dieser Leitfaden ist allgemein; Ihre Pflichten sind es nicht. Nennen Sie uns Ihre Branche und sagen Sie uns, wohin Ihre Daten gelangen dürfen. Wir sagen Ihnen, was für Sie gilt.