Dateien nach "/" hochladen

This commit is contained in:
2026-02-23 10:48:57 +00:00
parent 99418fda7a
commit 4b72282029
3 changed files with 152 additions and 0 deletions

1
.env.example Normal file
View File

@@ -0,0 +1 @@
OPENAI_API_KEY=sk-....

149
generate_pii_texts.py Normal file
View File

@@ -0,0 +1,149 @@
"""
Generiert synthetische deutsche Texte mit PII-Daten via OpenAI.
Speichert das Ergebnis als JSON.
Usage:
pip install openai python-dotenv
set OPENAI_API_KEY=sk-...
python generate_pii_texts.py
"""
import json
import os
import random
from pathlib import Path
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
SYSTEM_PROMPT = """\
Du bist ein Testdaten-Generator. Du erzeugst realistische deutsche Texte \
die personenbezogene Daten (PII) enthalten. Alle Daten sind FIKTIV.
Wichtig:
- Sei KREATIV bei den PII-Typen. Nicht nur Name+Email, sondern auch:
Geburtsdaten, Steuernummern, Kennzeichen, Kundennummern, IP-Adressen,
Benutzernamen, Bankverbindungen, Sozialversicherungsnummern, Adressen,
Telefonnummern, Kreditkarten, Personalausweisnummern, Reisepassnummern,
Führerscheinnummern, Krankenkassennummern, URLs mit PII-Parametern,
Geburtsorte, Nationalitäten, Religionszugehörigkeit usw.
- Baue EDGE CASES ein:
* PII in Tabellenform, Aufzählungen, Signaturen
* Abgekürzte Namen (M. Müller), Spitznamen, Doppelnamen
* Telefonnummern in verschiedenen Formaten (+49, 0049, 089/, mit/ohne Leerzeichen)
* Adressen in verschiedenen Formaten (mit/ohne Bundesland, Postfach, c/o)
* Teilweise geschwärzte Daten (DE** **** **** 1234 56)
* PII eingebettet in Code-Snippets, Log-Dateien, SQL-Queries
* PII in E-Mail-Headern, Chat-Verläufen
* Mehrere Personen im selben Text
* PII die sich über Zeilenumbrüche erstreckt
* Tippfehler in PII-nahen Kontexten
* IBANs/Kartennummern mit und ohne Leerzeichen
- Variiere die Textarten: Emails, Chatverläufe, Briefe, Logs, Formulare,
Berichte, Notizen, Protokolle, Tickets, Datenbankeinträge
"""
SCENARIOS = [
"Kundenanfrage per Email mit Signatur",
"IT-Support-Ticket mit Log-Auszügen",
"Internes Chat-Protokoll zwischen Kollegen",
"Behördliches Schreiben / Bescheid",
"Arztbrief mit Patientendaten",
"Polizeibericht / Unfallprotokoll",
"Bewerbung mit Lebenslauf-Auszügen",
"Bankmitteilung / Kontoeröffnung",
"Versicherungsmeldung / Schadensfall",
"Datenbankexport / CSV-artige Daten mit Kopfzeile",
"Handschriftliche Notiz (transkribiert) mit PII",
"Server-Logfile mit User-Daten und IPs",
"SQL-Query oder Code-Snippet mit hardkodierten PII",
"Meeting-Protokoll mit Teilnehmerliste",
"Mietvertrag / Wohnungsübergabe-Protokoll",
]
def generate(count=5, scenario=None, model="gpt-4o"):
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
scenario = scenario or random.choice(SCENARIOS)
user_prompt = f"""\
Generiere {count} verschiedene deutsche Texte (je 50-250 Wörter).
Szenario: {scenario}
Jeder Text soll VERSCHIEDENE PII-Typen enthalten nicht immer die gleichen.
Baue bewusst Edge Cases und ungewöhnliche Formate ein.
Antwort als JSON:
{{
"samples": [
{{
"text": "...",
"pii_spans": [
{{"type": "PERSON", "value": "Max Müller", "start": 10, "end": 20}},
{{"type": "PHONE", "value": "+49 170 1234567", "start": 55, "end": 70}}
],
"scenario": "Kundenanfrage"
}}
]
}}
Regeln für pii_spans:
- type: freier String, z.B. PERSON, EMAIL, PHONE, IBAN, ADDRESS, DATE_OF_BIRTH,
LICENSE_PLATE, IP_ADDRESS, CREDIT_CARD, TAX_ID, SSN, ID_CARD, PASSPORT, URL, USERNAME, ...
- start/end: Zeichenpositionen im text (0-basiert). MÜSSEN exakt dem value entsprechen.
- JEDE PII im Text muss als span annotiert sein.
"""
print(f" → Generiere {count}x '{scenario}' ...")
resp = client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_prompt},
],
temperature=1.0,
response_format={"type": "json_object"},
)
raw = json.loads(resp.choices[0].message.content or "{}")
samples = raw.get("samples", [])
# Fix offsets: LLMs liegen oft daneben bei start/end
for s in samples:
for span in s.get("pii_spans", []):
val = span.get("value", "")
idx = s["text"].find(val)
if idx != -1:
span["start"] = idx
span["end"] = idx + len(val)
return samples
def main():
total = 50
batch_size = 5
all_samples = []
print(f"Generiere {total} synthetische PII-Texte...\n")
for i in range(0, total, batch_size):
scenario = random.choice(SCENARIOS)
n = min(batch_size, total - i)
try:
batch = generate(count=n, scenario=scenario)
all_samples.extend(batch)
print(f"{len(all_samples)}/{total} fertig")
except Exception as e:
print(f" ✗ Fehler: {e}")
out = Path("output/synthetic_pii_data.json")
out.parent.mkdir(exist_ok=True)
out.write_text(json.dumps(all_samples, indent=2, ensure_ascii=False), encoding="utf-8")
print(f"\n{len(all_samples)} Texte gespeichert → {out}")
if __name__ == "__main__":
main()

2
requirements.txt Normal file
View File

@@ -0,0 +1,2 @@
openai
python-dotenv