Akteursmodul mit Wikidata-Spiegel
Modul 4 der Spezifikation, dazu das Lexikon, auf das es sich stuetzt. Drei Schritte, streng getrennt: die NER liefert Kandidatenspannen, das Lexikon entscheidet den Typ, die Amtstabelle loest Aemter gegen das Datum des Items auf. Die Trennung ist gemessen begruendet und nicht uebernommen: de_core_news_lg haelt "Merz" fuer einen Ort, "Landtagswahl" fuer einen Ort und "Ukraine-Krieg" fuer eine Person. Der NER-Typ steht als ner_typ in der Nutzlast, entscheidet aber nichts. Modellwahl gemessen: sm und lg finden fast gleich viele Entitaeten (14249 gegen 14261), aber nicht dieselben - nur 10,7 Prozent der Items bekommen von beiden dasselbe Ergebnis, der Jaccard ueber alle Spannen liegt bei 0,590. lg findet 170-mal zusaetzlich "AfD" sowie Merz, Putin, Trump, Kushner, Witkoff. Zeitlich kostet das nichts (7,3 gegen 8,0 Sekunden fuer den Gesamtbestand), an Plattenplatz 568 MB. Der Spiegel ist eine Abschrift, keine Auslegung: lexikon/*.json enthaelt die Wikidata-Antworten unveraendert, mit MANIFEST.json als Beleg. Jede Ableitung geschieht in lexikon_laden.py. Nur lexikon.py --spiegeln fasst das Netz an, und es laeuft von Hand - die WDQS ist ein spendenfinanzierter Dienst, kein Endpunkt fuer eine Pipeline im Viertelstundentakt. p2-005 legt akteure und amtsinhaber an, dazu zwei Betriebssichten. Keine Ausschlussbeschraenkung gegen ueberlappende Amtszeiten: Doppelspitzen sind im deutschen Parteiensystem der Normalfall, und Bremen fuehrt "Buergermeister" als kollegiales Amt. Die Sicht amtsinhaber_ueberschneidungen macht Ueberlappungen sichtbar, statt sie zu verbieten. Amtszeiten sind halboffen - der Tag der Uebergabe gehoert dem Nachfolger, sonst waere jeder Amtswechsel eine Ueberschneidung. Messung ueber den Gesamtbestand: 3407 Items in 21,1 Sekunden, 14652 Nennungen, 2889 aufgeloest. Ein Slot-Lauf erzeugt bitgleich dieselbe Nutzlast wie der Gesamtlauf, 0 Abweichungen. spaCy ist stapelunabhaengig (Stapelgroesse 64, 7, 1 und rueckwaerts: identische Spannen), der Kunstgriff mit der festen Tokenlaenge aus dem Embeddingmodul ist hier nicht noetig. Zwei Fallen sind in NOTES.md festgehalten: eine geratene QID haengt einen Eintrag an ein fremdes Objekt (Q157617 ist die Commerzbank, nicht der Bundesrat), und FILTER (lang(?name) = "de") verliert lautlos alles ohne deutsches Label - Apple, Microsoft und Meta. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NupWEBPzsyohVPG47HsTz8
This commit is contained in:
co-authored by
Claude Opus 5
parent
cf89e012b2
commit
7e4c31912c
@@ -24,6 +24,11 @@ Spezifikation: [`phase_02_spec.md`](phase_02_spec.md).
|
||||
| `revisionen.py` | Modul: nachträglich geänderte Schlagzeilen |
|
||||
| `test_revisionen.py` | Testfälle dazu, ohne Datenbank |
|
||||
| `embeddings.py` | Modul 5: Satzvektoren |
|
||||
| `akteure.py` | Modul 4: Akteursauflösung gegen das Lexikon |
|
||||
| `test_akteure.py` | Testfälle dazu, ohne Datenbank und ohne spaCy |
|
||||
| `lexikon.py` | Wikidata spiegeln (`--spiegeln`), von Hand, nicht im Takt |
|
||||
| `lexikon_laden.py` | Spiegel in `akteure` und `amtsinhaber` laden |
|
||||
| `lexikon/` | Der Spiegel selbst, versioniert, plus `hand.json` |
|
||||
| `phase2.py` | Läufer: alle Module in fester Reihenfolge |
|
||||
| `Containerfile` | Laufzeitumgebung, identisch auf Dev und Prod |
|
||||
| `deploy/` | systemd-Units und Umgebungsbeispiel für Prod |
|
||||
@@ -430,3 +435,79 @@ Bestands (812 Items) ~160 s — bei einem 15-Minuten-Raster unkritisch.
|
||||
`item_embeddings` belegt 19 MB Heap für 3407 Vektoren, der HNSW-Index weitere
|
||||
26 MB. Der Index kostet also mehr als die Daten; die Faustregel »mit HNSW eher
|
||||
das Doppelte« aus dem Abschnitt zum Platzbedarf ist damit bestätigt.
|
||||
|
||||
|
||||
## Modul 4: Akteure
|
||||
|
||||
Löst Personen, Organisationen, Parteien, Staaten und Ämter auf stabile IDs
|
||||
auf. Kein Netzzugriff zur Laufzeit, kein Modell, das etwas benennt — die NER
|
||||
liefert nur, *wo* etwas steht, das Lexikon entscheidet, *was* es ist.
|
||||
|
||||
```
|
||||
lexikon.py --spiegeln # Wikidata abfragen, von Hand, selten
|
||||
lexikon_laden.py # Spiegel in die Tabellen
|
||||
akteure.py --backfill # Gesamtbestand kodieren
|
||||
akteure.py --slot '<ts>' # ein Slot
|
||||
```
|
||||
|
||||
### Der Spiegel ist eine Abschrift, keine Auslegung
|
||||
|
||||
`lexikon/*.json` enthält, was Wikidata geantwortet hat — unverändert, mit
|
||||
`MANIFEST.json` als Beleg (Stand, Zeilenzahl, Hash der Abfrage). Jede
|
||||
Ableitung daraus — IDs, Rollen, Aliase, Amtszeiten — geschieht in
|
||||
`lexikon_laden.py`. Wer eine Zuordnung ändern will, ändert den Lader und
|
||||
lädt neu; Wikidata wird dafür nicht ein zweites Mal befragt.
|
||||
|
||||
Das ist kein Selbstzweck. Die Wikidata Query Service ist ein
|
||||
spendenfinanzierter öffentlicher Dienst, und eine Pipeline, die alle
|
||||
15 Minuten dagegenläuft, wäre Schmarotzertum.
|
||||
|
||||
### Warum das Lexikon den Typ bestimmt, nicht das Modell
|
||||
|
||||
`de_core_news_lg` hält `Merz` für einen Ort, `Landtagswahl` für einen Ort und
|
||||
`Ukraine-Krieg` für eine Person. Die NER-Typen sind deshalb nur
|
||||
Herkunftsvermerk; sie stehen in der Nutzlast als `ner_typ`, entscheiden aber
|
||||
nichts. Für die Geokodierung bleiben sie als Vorfilter nützlich.
|
||||
|
||||
### Was eine Auflösung wert ist
|
||||
|
||||
| Methode | Konfidenz | Bedeutung |
|
||||
|---|---|---|
|
||||
| `alias` | 0,95 | volle Namensform oder Alias aus dem Lexikon |
|
||||
| `alias_ohne_anrede` | 0,90 | nach Abzug von »US-Präsident«, »Bundesminister« |
|
||||
| `amt` | 0,90 | Amt, gegen `pubdate` auf eine Person aufgelöst |
|
||||
| `nachname` | 0,80 | Nachname, im Lexikon eindeutig |
|
||||
| `fuzzy` | 0,60 | Editierdistanz, längenabhängig begrenzt |
|
||||
|
||||
Bei Mehrdeutigkeit entscheidet der Kontext (wird die Partei eines Kandidaten
|
||||
im selben Item genannt?), und wenn auch der nicht reicht, bleibt die Nennung
|
||||
**unaufgelöst**. Ein Münzwurf wäre hier der schlimmere Fehler, weil er in
|
||||
der Zeitreihe nicht auffällt.
|
||||
|
||||
### Ämter sind zeitabhängig, und das ist der Punkt
|
||||
|
||||
`amtsinhaber` hält fest, wer wann welches Amt hatte. »Der Kanzler« löst am
|
||||
1. März 2023 auf Scholz auf und am 7. September 2026 auf Merz. Die Intervalle
|
||||
sind halboffen: der Tag der Übergabe gehört dem Nachfolger. Ohne diese
|
||||
Konvention wäre jeder Amtswechsel eine Überschneidung, weil Wikidata den
|
||||
Übergabetag bei beiden einträgt.
|
||||
|
||||
### Keine Ausschlussbeschränkung gegen Überschneidungen
|
||||
|
||||
Sie wäre falsch. Doppelspitzen sind im deutschen Parteiensystem der
|
||||
Normalfall, und Bremen führt »Bürgermeister« als kollegiales Amt mit mehreren
|
||||
gleichzeitigen Inhabern. Gleichzeitig *ist* eine Überschneidung beim
|
||||
Kanzleramt ein Datenfehler. Die Unterscheidung hängt am Amt, nicht an der
|
||||
Zeile, und lässt sich in einer Beschränkung nicht ausdrücken — also macht die
|
||||
Sicht `amtsinhaber_ueberschneidungen` sie sichtbar, statt sie zu verbieten.
|
||||
|
||||
### Handpflege
|
||||
|
||||
`lexikon/hand.json` ergänzt, was durch jede Spiegelabfrage fällt: die NATO
|
||||
(bei Wikidata ein Militärbündnis, keine internationale Organisation), der
|
||||
Bundestag (ein Parlament), Apple und Microsoft (haben kein deutsches Label).
|
||||
Jeder Eintrag trägt eine Begründung. QIDs gehören **geprüft** hinein — eine
|
||||
geratene QID hängt den Eintrag an ein fremdes Objekt.
|
||||
|
||||
Die Sicht `akteure_unaufgeloest` zählt aus, was die NER fand und das Lexikon
|
||||
nicht kannte. Das ist der laufende Handarbeitsposten der Phase.
|
||||
|
||||
Reference in New Issue
Block a user