Prod fuehrt Phase 1 als Quadlet unter
~/.config/containers/systemd/wurzelwerk-ingest.container; Phase 2 legt
sich daneben. Damit faellt die eigene .service-Unit weg - zwei Wege,
dasselbe zu tun, sind einer zuviel.
Drei Dinge, die dabei nicht offensichtlich sind:
Type=oneshot Quadlet setzt sonst Type=notify, und die Unit
gaelte als gestartet, sobald der Container
laeuft, nicht wenn er durch ist.
kein RemainAfterExit Das Handbuch empfiehlt es fuer oneshot, aber bei
Timer-Aktivierung bliebe der Auftrag im Zustand
"started" und der Timer loeste ihn nie wieder
aus.
--env-file EnvironmentFile= im Abschnitt [Container] ist
nicht systemds EnvironmentFile=. Quadlet reicht
die Datei an podman weiter, und podman entfernt
keine Anfuehrungszeichen um Werte.
Network=bebop-net steht jetzt direkt in der Unit; P2_NETZ entfaellt.
Type=oneshot schaltet ausserdem die Startzeitgrenze ab, womit der Grund
fuer TimeoutStartSec=1800 wegfaellt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NupWEBPzsyohVPG47HsTz8
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
Drei Schritte, die zusammen Phase 2 lauffaehig machen.
Revisionen (migrations/p2-004, revisionen.py)
Ingest schreibt jede geaenderte Fassung eines Items nach
raw_item_versionen fort. Daraus faellt ein Befund ab, den die
Spezifikation nicht vorsehen konnte: welches Haus seine Schlagzeile
nachtraeglich umschreibt, und wie. 206 von 3407 Items, acht
Einstufungen von 'formal' bis 'neufassung'. Kein Modell, kein Lexikon,
kein Netzzugriff - nur ein Wortvergleich zweier Fassungen.
Fortschreibungen sind ueber ticker_markiert und kopf_stabil abziehbar,
absichtlich als zwei Merkmale statt einer Kategorie: das eine ist eine
Selbstauskunft des Hauses, das andere eine Beobachtung am Satzbau.
Embeddings (embeddings.py)
multilingual-e5-large, 1024 Dimensionen, MIT. Jede Zeile wird auf feste
128 Token aufgefuellt, nicht nur bis zur laengsten des Stapels - sonst
haengt ein Vektor davon ab, mit welchen Nachbarn er kodiert wurde, und
ein Slot-Lauf liefert andere letzte Stellen als ein Backfill.
Nachgewiesen: 64/64 bitgleich einzeln wie im vollen Stapel, groesste
Abweichung 0.00e+00, und im Betrieb 26 Slot-Vektoren unveraendert
gegen den 3407er-Backfill.
Darum transformers statt sentence-transformers: letzteres kapselt genau
diese Stelle weg.
Container (Containerfile, phase2.py, deploy/)
Debian trixie wie der Postgres-Container, torch aus dem CPU-Index.
Die regelbasierten Module liefern darin fuer alle 3407 Items bitgleich
dieselbe Nutzlast wie auf der Entwicklungsmaschine - Portabilitaet
gemessen, nicht behauptet.
version.py bekommt den Schluessel 'revision'. Weil der Hash ueber den ganzen
Komponentensatz laeuft, aendert das auch die Version des Dublettenmoduls,
obwohl an dessen Verfahren nichts anders ist. Das ist die in version.py
beschriebene Semantik der Spezifikation, kein Versehen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NupWEBPzsyohVPG47HsTz8