TEI-NER Pipeline

Programmablaufplan · Entity-Linking & Normdaten-Enrichment

Phase 0 Corpus-Profiler System-Prompt generieren
1
TEI-Dokumente analysieren
Stichprobe von N Dokumenten (--llm-sample). Sprachen, Zeitraum, Regionen, Korrespondenz-Netzwerk erkennen.
2
Register-Metadaten auswerten
Entity-Typen, Note-Kategorien, Lebensdaten-Spanne, Alt-Namen-Sprachen.
3
generated_prompt.txt + corpus_profile.json erzeugen
Dynamischer Projekt-Kontext für LLM-Verifikation. Geographische Disambiguierungs-Anweisung. Sprach-Mapping für Multi-Language Wikidata-Suche.
Sprachen: de, en, la, el → Wikidata API language codes Zeitraum: 1567-1605 → Anachronismus-Schwelle Region: Antikes Mittelmeer → Geo-Bias
Phase 1.5 Filter & Scoring Kandidaten bewerten
Hard-Filter: Meta-Einträge entfernen NEU
"given name", "family name", "genus of", "disambiguation", "wikimedia" → sofort entfernt. Blockieren sonst Top-N Plätze für echte Kandidaten.
Anachronismus-Filter
Lebensdaten vs. Korpus-Zeitraum (-0.50). Jahreszahlen in Beschreibung (-0.50). ANACHRONISM_KEYWORDS: video game, exhibition, ship, comic, etc. (-0.40).
Typ-Whitelist NEU
Statt Blacklist: Was DARF in diesem Register stehen?
Person: ~270 Keywords (Herrscher, Ämter, Handwerk, Mythologie, Völker...)
Place: ~300 Keywords (Siedlungen, Gewässer, Burgen, Territorien...)
Org: ~40 Keywords (Institutionen, Orden, Zünfte...)
Kein Whitelist-Match → -0.35 Penalty
Kollektiv-Penalty / Pseudo-Corp
Note "Volksstamm" + Person-Treffer → -0.35. SubjectHeading mit Kollektiv-Bezug → +0.30.
Pseudo-Corp (Erben/Offizin) → CorporateBody +0.25, Person -0.30.
Phase 1.7 Disambiguierung Multi-Signal-Scoring
A
Namens-Überlappung
Name-Parts vs. Label+Beschreibung (nicht nur Label!). 0% Overlap → -0.30. <60% → -0.15. Schützt vor Adels-Namenswechsel: "Anna von Honstein" findet "Honstein" in Beschreibung von "Mansfeld, Anna von".
B
Primärname-Check
Suchname am Label-Anfang → +0.15. Nur Sekundärreferenz ("Sohn des Ares") → -0.20.
C
Lebensdaten-Match
Register-Geburtsjahr = Kandidat → +0.15. Todesjahr → +0.10.
D
Note-Keywords (gewichtet)
Abstammungs-Keywords +0.20 (stark). Phrasen +0.12. Jahreszahlen +0.08. Normale Keywords +0.03. Stamm-Matching: "priamos" → Stamm "priam" matcht "daughter of Priam".
E
Domänen-Boost ERWEITERT
Note-Domäne + Beschreibungs-Domäne übereinstimmend → +0.30. "biblisch" in Note + "Bible/patriarch" in Beschreibung → Boost. Phantom-Penalty: Note hat Domäne, Kandidat hat nichts → -0.25.
◆ Auto-Link Schwelle
Score ≥ 0.90 → Auto-Link (kein LLM)
Score < 0.90 → Weiter zu Phase 2
Phase 2 LLM-Verifikation Gemma 4 (lokal) / Gemini 2.5 Flash (API)
◆ Provider-Erkennung
Lokal (Gemma 4 via LM Studio)
Kompakter System-Prompt (197T)
Projekt-Kontext im User-Prompt
KV-Cache: 100% Hit-Rate
API (Gemini 2.5 Flash / Claude)
Voller System-Prompt (1250T)
Projekt-Kontext im System-Prompt
Batch-API: 50% Rabatt (Anthropic)
1
Verify-Prompt bauen
Pro Entity: Name, Typ (mit Subtyp-Annotation!), Alt-Namen, Lebensdaten, Note, Quelltext-Kontext, Epochen-Hinweis, Geo-Kontext aus Corpus-Profil. Max 5 Kandidaten pro Entity (Top-5 nach Score). Kandidaten mit [wikidata]/[gnd]-Quell-Labels.
Typ: person (PERSONENGRUPPE/VOLK — kein Individuum!) Typ: person (KOERPERSCHAFT — Erben/Offizin, kein Individuum!) Type Enforcement: Entity-Typ vom Editor ist nicht verhandelbar!
2
LLM-Call (max_tokens: 4000)
Timeout: 600s (lokal). JSON-Parsing mit Thinking-Tag-Removal, Wrapper-Unwrapping, Truncation-Repair.
3
Verdict auswerten
MATCH (≥0.90) → ID schreiben. PARTIAL (≥0.75 Confidence) → ID schreiben. PARTIAL-Fallback NEU: GND-Confidence ≥0.70 → Auto-Link. NONE → weiter zu Phase 2.7.
◆ Zwei-Modell-Strategie (optional)
PARTIAL/NONE → Retry mit stärkerem Modell (--retry-model)
Kein Retry-Modell → Ergebnis final
Phase 2.7 Spelling-Recovery VERIFIED_NONE mit Kandidaten NEU
1
VERIFIED_NONE-Entities filtern
Nur Entities, bei denen das LLM alle Kandidaten abgelehnt hat (VERIFIED_NONE), aber Kandidaten vorhanden waren. Entities ohne Kandidaten gehen direkt zu Phase 3.
2
Schreibweisen-Analyse
LLM prüft ob der Entity-Name eine historische Schreibweise sein könnte. Falls ja: erneute Normdaten-Suche mit modernem Namen + Verifikation.
LLM
3
Erneute Verifikation
Neue Kandidaten werden mit dem originalen Kontext verifiziert. Rettet Einträge, bei denen der historische Name den richtigen Kandidaten verdeckt hat.
Phase 4 Kreuzreferenz GND ↔ Wikidata ergänzen
GND → Wikidata
3-Stufen-Strategie: (1) Vorhandene Kandidaten prüfen. (2) Alt-Namen in WD suchen. (3) Direkte Suche mit Match-Label + Domänen-Check + Temporale Konsistenz. Schwelle: 0.55 (mit Desc) / 0.80 (ohne Desc).
Wikidata → GND
Primärname-Check: Suchname muss im GND-Hauptnamen vorkommen. Domänen-Check. LOBID-Korrektur: Niedrigste Q-Nummer bevorzugen.
Phase 5 Output & Report XML + JSON + HTML + CSV
TEI-XML schreiben
<idno type="GND" resp="#tei-ner-pipeline" cert="high">. Editoriale IDs werden NIE überschrieben. Provenienz: @resp + @cert für jedes Pipeline-Element.
📊
enrichment_report.json
Vollständige Statistiken, pro-Entity-Ergebnisse, Kandidaten, Verdicts, Reasons. Grundlage für HTML-Report und Training-Export.
🎨
HTML-Report
Interaktiver Report: Suchfeld, Filter-Buttons, sortierbare Spalten, GND/WD-Links, Konflikte hervorgehoben, Confidence-Badges.
📄
Pipeline-Summary
Speicher-Watchdog, Cache-Statistiken (Hit-Rate), Wikidata 429-Retries, Sprach-Kaskade, Kosten.
Speicher: 3200/16384 MB, GC: 0x, Throttle: 0x Cache: 3200 Eintraege, 3150/3200 Hits (98.4%) wikidata: 1780 Hits, 20 Misses (98.9%) gnd: 1370 Hits, 30 Misses (97.8%)
Phase 6 Training-Export (optional) Fine-Tuning Datensatz
1
Trainingsdaten sammeln
Aus enrichment_report.json: VERIFIED_MATCH + EDITORIAL_CONFIRMED + VERIFIED_NONE. Min-Confidence Filter. Mehrere Projekte kombinierbar.
2
Kandidaten-Splitting NEU
Jeder Kandidat wird eigenes Trainingspaar: 1x MATCH (richtiger) + Nx NONE (abgelehnte mit Begründung). Erhöht Datenmenge um ~40%.
3
Stratifizierung
Ziel-Verteilung: 55% MATCH, 35% NONE, 10% PARTIAL. Verhindert dass Modell "im Zweifel MATCH" lernt.
4
Export: ChatML + Alpaca + Conversation
Für Gemma 4, Phi-4, LLaMA, Unsloth, Axolotl. Mit Train/Val Split (90/10). Zusätzlich: Gezieltes Training für Schwachstellen (Alt-Namen-Disambiguierung, Region-unabhängige Orte, Kollektive, Institutionen). NEU
python3 -m src.training_exporter \ --input projekt1/ projekt2/ projekt3/ \ --split-candidates --stratify \ --output training/

Legende

NEU — In dieser Session hinzugefügt ERWEITERT — Bestehend, verbessert CACHE — Persistenter SQLite-Cache LLM — Erfordert LLM-Inference