Das Abbild traegt jetzt spaCy und de_core_news_lg 3.8.0 mit fester Version sowie den Wikidata-Spiegel. Es waechst dadurch von 1,28 auf 2,12 GB. Das Modell liegt im Abbild statt im Cache-Volume: 568 MB, die sich nie aendern, und der erste Lauf auf Prod soll nicht an einem Download haengen. Gemessen: ein Slot-Lauf im Container erzeugt bitgleich dieselbe Nutzlast wie die Workstation - 3407 Codings, 0 Abweichungen, gleiche coder_version. Der User-Agent fuer die WDQS traegt jetzt die Impressumsadresse des Projekts, wie es die Nutzungsrichtlinie erbittet. NOTES.md haelt fest, woher die Zeichenkette "None" kommt: bei leerer <description> faellt der Poller auf content:encoded zurueck, und die ZEIT liefert dort einen Anker, dessen Text "None" lautet. Phase 1 schreibt getreu mit, der Fehler ist stromaufwaerts. Am Live-Feed reproduziert, 8 von 15 Items. Der Prod-Cluster-Dump ist per .gitignore ausgeschlossen - er enthaelt die Rollen samt Passworthashes, auch die von gitea und hedgedoc. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NupWEBPzsyohVPG47HsTz8
453 lines
18 KiB
Markdown
453 lines
18 KiB
Markdown
# Befunde aus dem Dublettenmodul
|
||
|
||
Gemessen am Bestand vom 4.–7.9.2026: 3407 Items, 12 Quellen, 106 Slots.
|
||
|
||
## Das Verfahren der Spezifikation findet keine Übernahmen
|
||
|
||
67 Gruppen, 147 Mitglieder, **null davon über Häuser hinweg**. Alle gefundenen
|
||
Gruppen sind Wiederholungen innerhalb eines Feeds.
|
||
|
||
Das ist kein Schwellenproblem, das sich durch Nachjustieren lösen ließe. Ein
|
||
vollständiger Vergleich aller 599.004 hausübergreifenden Paare des stärksten
|
||
Tages (6.9., 1162 vergleichbare Items) ergibt:
|
||
|
||
| Jaccard über Titel+Teaser | Paare über Häuser |
|
||
|---|---|
|
||
| ≥ 0.85 (Schwelle der Spec) | **0** |
|
||
| ≥ 0.7 | 1 |
|
||
| ≥ 0.5 | 3 |
|
||
| ≥ 0.3 | 8 |
|
||
|
||
Der höchste erreichte Wert im gesamten Tag liegt bei 0.65. Die Schwelle wird
|
||
nie berührt.
|
||
|
||
Die Hamming-Grenze ist dabei unschuldig: von 224 Paaren mit Jaccard ≥ 0.85
|
||
verwirft sie 6. Der Vorfilter über SimHash-Bänder kostet also fast nichts —
|
||
er ist gut, er hat nur nichts zu tun.
|
||
|
||
## Warum: der Titel wird übernommen, der Teaser nicht
|
||
|
||
Die Übernahmen sind da, sie sehen nur anders aus als angenommen. Beispiele
|
||
vom 6.9., alle mit **zeichengleichem Titel** nach Normalisierung:
|
||
|
||
```
|
||
zeit / handelsblatt Wahl in Sachsen-Anhalt: Klüssendorf: Frage nach SPD-Vorsitz …
|
||
zeit / handelsblatt Ukraine-Krieg: Selenskyj mit wenig Hoffnung auf baldigen Frieden
|
||
heise / tagesschau Deutsche Isar-Aerospace-Rakete erfolgreich ins All gestartet
|
||
handelsblatt / tagesschau +++ Iran-Krieg +++: Tote und Verletzte bei neuen Angriffen
|
||
```
|
||
|
||
Die Häuser übernehmen die Agenturüberschrift wörtlich und schreiben den
|
||
Teaser selbst. Werden beide in einen Sack geworfen, verdünnt der Teaser genau
|
||
das Signal, das trägt: dieselben Paare landen bei Jaccard 0.29 bis 0.38.
|
||
|
||
Gemessen, wenn **nur der Titel** verglichen wird (6.9., 1144 Items mit
|
||
mindestens fünf Titelwörtern):
|
||
|
||
| Kriterium | Paare | davon über Häuser |
|
||
|---|---|---|
|
||
| Titel zeichengleich | 61 | **22** |
|
||
| Titel-Jaccard ≥ 0.75 | 16 | **9** |
|
||
|
||
31 hausübergreifende Übernahmen an einem Tag statt null. Die Differenz
|
||
zwischen „zeichengleich" und „≥ 0.75" ist fast immer ein vorangestelltes
|
||
Ressortkürzel des Hauses: `Raumfahrt: Deutsche Isar-Aerospace-Rakete …` gegen
|
||
`Deutsche Isar-Aerospace-Rakete …`, oder `Notfälle:` gegen `Flugverkehr:` vor
|
||
derselben dpa-Zeile.
|
||
|
||
## Vorschlag
|
||
|
||
Vergleichsbasis auf den **Titel** umstellen, den Teaser nur noch als
|
||
Bestätigung heranziehen, wo er auf beiden Seiten vorliegt. Zusätzlich das
|
||
führende Ressortpräfix (`Wort:` am Anfang) in der Normalisierung abtrennen —
|
||
danach fällt ein Teil der 0.75er-Fälle in die Zeichengleichheit.
|
||
|
||
Das ist eine Änderung an Abschnitt 3 der Spezifikation, nicht an ihrer Absicht:
|
||
„near-exact, kein thematisches Clustering" bleibt. Die Abnahmekriterien wären
|
||
neu zu setzen, weil sich mit der Basis auch die Grundgesamtheit ändert.
|
||
|
||
## Umgesetzt, mit diesem Ergebnis
|
||
|
||
Der Vorschlag ist gebaut und ist jetzt die Vorgabe (`--basis titel`, dazu das
|
||
abgetrennte Ressortkürzel). Auf demselben Bestand:
|
||
|
||
| | Titel + Teaser | Titel |
|
||
|---|---|---|
|
||
| Gruppen gesamt | 67 | 135 |
|
||
| Mitglieder | 147 | 290 |
|
||
| **Gruppen über mehrere Häuser** | **0** | **63** |
|
||
| Items in solchen Gruppen | 0 | 143 |
|
||
|
||
Gruppengrößen: 240 Paare, 33 Dreier, 12 Vierer, 5 Fünfer. Die größte ist
|
||
dieselbe Zeile über den Start der Isar-Aerospace-Rakete bei handelsblatt,
|
||
heise, tagesschau und zeit.
|
||
|
||
Auf dem gemessenen Tag (6.9.) erreicht das Verfahren 42 von 45
|
||
hausübergreifenden Paaren mit Jaccard ≥ 0.70. Die Schwellen kosten dabei
|
||
nichts: an der Jaccard-Schwelle gehen 0 Paare verloren, an der
|
||
Hamming-Grenze 0. Die drei fehlenden scheitern am SimHash-Bandvorfilter —
|
||
bei sechs bis acht Trigrammen je Titel ist SimHash ein grobes Werkzeug. Ein
|
||
Trigramm-Index als zweiter Kandidatenweg würde sie einfangen.
|
||
|
||
Die Schwelle selbst ist unkritisch: zwischen Jaccard 0.70 und 0.85 liegt auf
|
||
diesem Bestand kein einziges Paar. Nach dem Abtrennen des Ressortkürzels sind
|
||
die Übernahmen entweder zeichengleich oder deutlich verschieden.
|
||
|
||
## Nebenbefund: Volltext hilft hier nicht
|
||
|
||
Auf den ersten Blick läge nahe, den Volltext zu nehmen, wo er da ist. Genau
|
||
das verbietet sich: die Abdeckung ist ungleich (faz 311/489, heise 174/196,
|
||
aber derstandard, welt, dlf, taz, sz jeweils 0), und ein Paar aus einem Haus
|
||
mit und einem ohne Volltext ist der häufigste Fall überhaupt. Eine je Item
|
||
verschiedene Vergleichsbasis macht genau die Paare unauffindbar, um die es
|
||
geht.
|
||
|
||
## Nebenbefund: `agentur_vermutet` greift kaum
|
||
|
||
Zwei Belege im gesamten Bestand, beide `reuters`. Die Agenturkennung steht in
|
||
RSS-Titeln und -Teasern praktisch nie; sie taucht erst im Volltext oder in der
|
||
Bildunterschrift auf. Das Feld bleibt, liefert aber auf RSS-Basis fast immer
|
||
`null`.
|
||
|
||
## Was beim Aufräumen weggefallen ist
|
||
|
||
Nach den Experimenten einmal gemessen, welche Regel auf den 3407 Items
|
||
überhaupt jemals greift:
|
||
|
||
| Regel | Treffer |
|
||
|---|---|
|
||
| Ressortkürzel abtrennen | 1870 |
|
||
| Anführungszeichen/Striche vereinheitlichen | 654 |
|
||
| `+++ … +++` entfernen | 8 |
|
||
| NFKC | 4 |
|
||
| `Eilmeldung:` entfernen | **0** |
|
||
| Ortsmarke `Berlin (dpa) -` entfernen | **0** |
|
||
| HTML-Tags entfernen | **0** (auch im Teaser) |
|
||
| Entities auflösen im Titel | **0** |
|
||
|
||
Entfernt wurden `_EILMELDUNG` und `_ORTSMARKE`. Beide stehen so in Abschnitt 3
|
||
der Spezifikation, greifen aber auf RSS-Titeln nie — die Ortsmarke steht im
|
||
Volltext einer Agenturmeldung, nicht in der Überschrift. Kommt Volltext als
|
||
Quelle hinzu, gehören sie zurück.
|
||
|
||
Das Entfernen von HTML-Tags bleibt trotz null Treffern: Phase 1 zieht die
|
||
`links` aus dem Teaser-HTML, HTML ist im Feed also grundsätzlich zu erwarten.
|
||
Der doppelte Entity-Durchlauf (vor *und* nach dem Tag-Entfernen) ist auf einen
|
||
reduziert.
|
||
|
||
Ebenfalls raus: der ungenutzte `anzahl`-Parameter von `baender()`, zwei
|
||
ungenutzte Argumente von `stichprobe()`, der `version`-Parameter von
|
||
`eintragen()`, ein `__main__`-Block in `version.py`, der eine Version ohne
|
||
Moduleinstellungen ausgab und damit nie die echte.
|
||
|
||
Zusammengelegt: `lade()` hatte am Ende selbst gruppiert, und `main()` rechnete
|
||
dieselbe Gruppierung anschließend ein zweites Mal. Beides steckt jetzt in
|
||
`lade_und_gruppiere()` — beim Slot-Lauf gehört es ohnehin zusammen, weil sich
|
||
erst an den Gruppen zeigt, wieviel geladen werden muss.
|
||
|
||
Zwei Kommentarblöcke zur Vergleichsbasis widersprachen sich nach der
|
||
Umstellung; der ältere behauptete noch „verglichen wird immer Titel + Teaser".
|
||
|
||
Die Schwellen selbst sind alle belegt. Von 778 Kandidatenpaaren verwirft das
|
||
Datumsfenster 223, die Regel „gleiches Haus, anderer Tag" 48 und die
|
||
Hamming-Grenze 330; 177 werden bestätigt. Nur die Jaccard-Bestätigung verwirft
|
||
nichts mehr — sie bleibt als Präzisionszusage, weil SimHash kollidieren kann.
|
||
Der Kettenschnitt trifft genau eine von 135 Komponenten und bleibt aus
|
||
demselben Grund.
|
||
|
||
# Befunde aus dem Revisionsmodul
|
||
|
||
Bestand vom 4.–7.9.2026, 3407 Items, 3974 Fassungen.
|
||
|
||
## Wieviel überhaupt geändert wird
|
||
|
||
| | Items |
|
||
|---|---|
|
||
| nie geändert | 3084 |
|
||
| mindestens eine neue Fassung | 323 |
|
||
| davon mit geändertem **Titel** | 206 (357 Übergänge) |
|
||
| davon nur Teaser geändert | 111 |
|
||
| URL geändert | 78 Übergänge |
|
||
|
||
Rund 6 Prozent aller Schlagzeilen werden nach der Veröffentlichung noch
|
||
angefasst. Das ist häufiger, als man erwartet, und es verteilt sich über alle
|
||
zwölf Häuser.
|
||
|
||
## Art der Änderung (erste gegen letzte Fassung)
|
||
|
||
| Einstufung | gesamt | ohne Fortschreibung |
|
||
|---|---|---|
|
||
| umformulierung | 83 | 77 |
|
||
| neufassung | 56 | 22 |
|
||
| kopfwechsel | 26 | 26 |
|
||
| erweiterung | 14 | 13 |
|
||
| kuerzung | 11 | 11 |
|
||
| formal | 9 | 9 |
|
||
| tippfehler | 6 | 6 |
|
||
| zurueckgenommen | 1 | 0 |
|
||
|
||
»Ohne Fortschreibung« zieht die 10 selbstbenannten Ticker und die 33 Items mit
|
||
stabiler Rubrik und ausgetauschtem Stand ab. Die Spalte zeigt, wozu das nötig
|
||
ist: bei `neufassung` bleiben von 56 nur 22 übrig — zwei Drittel der scheinbar
|
||
komplett neu geschriebenen Schlagzeilen sind Liveticker, die von einem Stand
|
||
zum nächsten weiterzählen.
|
||
|
||
## Umgeschriebene Schlagzeilen je Haus (ohne Fortschreibung)
|
||
|
||
spiegel 39, zeit 26, derstandard 18, faz 17, ntv 13, tagesschau 10, welt 10,
|
||
heise 9, taz 9, handelsblatt 8, dlf 3, sz 2.
|
||
|
||
Vorsicht bei der Deutung: die Zahlen hängen an der Feedgröße (zeit 550 Items,
|
||
sz 73) und an der Frage, ob ein Haus überhaupt denselben Item-Key beibehält,
|
||
wenn es die Überschrift ändert. Wer die URL mitwechselt, erscheint bei Ingest
|
||
als neues Item und taucht hier gar nicht auf. Als Rangliste taugt das nicht,
|
||
als Nachweis, dass es geschieht, sehr wohl.
|
||
|
||
## Warum der Pluskasten hier stehen bleiben muss
|
||
|
||
`normalisierung.normalisiere()` entfernt für das Dublettenmodul »++ … ++«, weil
|
||
verschiedene Häuser denselben Agenturtext verschieden einrahmen. Die tagesschau
|
||
führt ihren Liveticker aber vollständig darin:
|
||
|
||
++ Liveticker zur Sachsen-Anhalt-Wahl: Wahllokale haben geöffnet ++
|
||
|
||
Nach der Dublettennormalisierung bleibt davon der leere String. 31 der 357
|
||
Übergänge wären damit unvergleichbar gewesen. Deshalb `pluskasten=False`.
|
||
|
||
## Was das Verfahren nicht kann
|
||
|
||
* **Unmarkierte Fortschreibungen.** Die Welt schrieb »54,4 Prozent am
|
||
Nachmittag …« zu »Schon 65,3 Prozent …« um — ein Wahlabend-Dauerartikel ohne
|
||
jedes Tickerwort und ohne feste Rubrik. Er zählt als `neufassung`. `fassungen`
|
||
und `zahlen_geaendert` stehen in der Nutzlast, damit sich das nachträglich
|
||
eingrenzen lässt; automatisch erkannt wird es nicht.
|
||
* **Getrennt- und Zusammenschreibung.** »Drohnenattacken:« → »Drohnen-Attacken:«
|
||
gilt als `kopfwechsel`, nicht als `formal`, weil die Normalisierung
|
||
Satzzeichen entfernt und daraus zwei Wörter werden. Ein Fall im Bestand.
|
||
* **Das Gewicht einer Änderung.** `kopfwechsel` sagt, *wo* geändert wurde, nicht
|
||
wie schwer es wiegt. Für die Unterscheidung sind `hinzu` und `entfernt` da.
|
||
|
||
## Nebenwirkung auf die coder_version
|
||
|
||
`version.KOMPONENTEN` bekam den Schlüssel `revision`. Weil der Hash über den
|
||
ganzen Komponentensatz läuft, ändert sich damit auch die Version des
|
||
Dublettenmoduls (`10cea100` → `51e03f9b`), obwohl an dessen Verfahren nichts
|
||
anders ist. Das ist die in `version.py` beschriebene Semantik der
|
||
Spezifikation, kein Versehen. Der Backfill kostet 0,3 Sekunden; die alte
|
||
Version wurde verworfen.
|
||
|
||
# Befunde aus dem Embeddingmodul
|
||
|
||
## Die Stapelzusammensetzung ist das eigentliche Problem
|
||
|
||
Nicht die CPU, nicht die Bibliothek, nicht der Container: dass ein Encoder
|
||
stapelweise rechnet und die Matrizenform mit dem Stapel wechselt. Wer nur bis
|
||
zur längsten Zeile des Stapels auffüllt, bekommt für dieselbe Zeile
|
||
verschiedene letzte Stellen, je nachdem, wer mit ihr im Stapel lag.
|
||
|
||
Mit fester Länge (128 Token für jede Zeile) verschwindet der Effekt
|
||
vollständig — nicht »klein«, sondern exakt null:
|
||
|
||
| Vergleich | bitgleich | größte Abweichung |
|
||
|---|---|---|
|
||
| voller Stapel gegen einzeln | 64/64 | 0.00e+00 |
|
||
| voller Stapel gegen rückwärts | 64/64 | 0.00e+00 |
|
||
|
||
Der Preis: jede Zeile kostet 128 Token Rechenzeit, auch wenn sie 62 braucht.
|
||
Bei Median 62 ist das gut Faktor zwei. Für die Zusage aus Invariante 2 ist er
|
||
es wert — und bei 7 s je Slot fällt er nicht auf.
|
||
|
||
## Tokenlängen im Bestand
|
||
|
||
Median 62, p95 90, p99 107, Maximum 233. Über 128 liegen 3 von 3407 Items:
|
||
zweimal »tagesschau 20:00 Uhr« (Sendungsablauf mit vollständiger Themenliste)
|
||
und einmal eine DLF-Hochrechnung. 256 statt 128 würde die Rechenzeit
|
||
verdoppeln, um 0,09 Prozent der Items vollständig zu erfassen — nicht
|
||
lohnend.
|
||
|
||
## Was die Vektoren finden, was SimHash nicht findet
|
||
|
||
Hausübergreifende Paare über 0.94 Kosinus, die das Dublettenmodul nicht
|
||
zusammengeführt hat — dieselbe Geschichte, anderer Wortlaut:
|
||
|
||
0.994 faz / handelsblatt Wasserdefizit in Deutschland
|
||
0.992 spiegel / handelsblatt Drohne trifft Geheimdienstzentrale in Kiew
|
||
0.992 zeit / faz Michael Mendl gestorben ("Schauspieler" / "Charakterdarsteller")
|
||
0.991 tagesschau / welt Trump-Gesandte reisen nach Moskau und Kiew
|
||
0.985 heise / handelsblatt Isar-Aerospace-Rakete erfolgreich gestartet
|
||
|
||
Das ist der Beleg dafür, dass Modul 1 und Modul 5 verschiedene Fragen
|
||
beantworten und keins das andere ersetzt.
|
||
|
||
## Container
|
||
|
||
Die regelbasierten Module liefern im Container (Debian trixie, Python 3.13)
|
||
für alle 3407 Items bitgleich dieselbe Nutzlast wie auf der
|
||
Entwicklungsmaschine (Fedora, Python 3.14). Damit ist die Portabilität nicht
|
||
behauptet, sondern gemessen.
|
||
|
||
`sentence-transformers` fiel zugunsten von `transformers` weg: es kapselt das
|
||
Auffüllen der Stapel weg — also genau die Stelle, an der hier die
|
||
Reproduzierbarkeit entschieden wird — und zieht scipy und scikit-learn nach.
|
||
|
||
Ein Stolperstein beim Volume: der Container läuft als UID 10001, ein frisch
|
||
angelegtes Podman-Volume gehört root im User-Namespace. Ohne `:U` am
|
||
Volume-Argument scheitert der erste Schreibzugriff auf den Modell-Cache.
|
||
Dieselbe Klasse Problem wie bei pgAdmin, nur mit anderem Symptom.
|
||
|
||
# Befunde aus der Vorarbeit zu Akteuren
|
||
|
||
## Ein Datenfehler aus Phase 1: `"None"` als Teaser
|
||
|
||
382 der 550 zeit-Items tragen als Teaser die Zeichenkette `None` — nicht
|
||
`NULL`, sondern Pythons `None` in Text verwandelt. Das sind 69 Prozent des
|
||
Hauses.
|
||
|
||
Der Fehler entsteht im Ingest und ist in Phase 2 bereits wirksam geworden:
|
||
|
||
- die Embeddings dieser 382 Items kodieren ein bedeutungsloses Wort mit,
|
||
- die Dublettenprüfung vergleicht es mit,
|
||
- die NER hält es 112-mal für einen Ort oder eine Organisation.
|
||
|
||
Zu reparieren ist er richtigerweise in Phase 1. Phase 2 kann ihn abfangen,
|
||
das entwertet aber jede bestehende `coder_version` und erzwingt einen
|
||
vollständigen Neuaufbau.
|
||
|
||
Bemerkenswert ist, wie lange er unentdeckt blieb: keine der drei bisherigen
|
||
Auswertungen schaute je auf einen einzelnen Teaser, und in der Aggregation
|
||
ist `None` ein Wort wie jedes andere.
|
||
|
||
## `de_core_news_sm` gegen `de_core_news_lg`, 3407 Items
|
||
|
||
| | sm | lg |
|
||
|--------------------------|--------|--------|
|
||
| Entitäten | 14 249 | 14 261 |
|
||
| Durchsatz | 465/s | 428/s |
|
||
| Items ohne jede Entität | 81 | — |
|
||
|
||
Die Gesamtzahlen sind fast gleich. Das ist eine Falle: die beiden Modelle
|
||
finden **nicht dieselben** Entitäten.
|
||
|
||
| Vergleich | Wert |
|
||
|------------------------------------|-------|
|
||
| Items mit identischem Ergebnis | 10,7 %|
|
||
| Items mit identischen Spannen | 18,2 %|
|
||
| Jaccard über alle Spannen | 0,590 |
|
||
|
||
Auch wenn man die Typen ignoriert und nur die Spannen vergleicht, stimmen
|
||
die Modelle bei zwei von fünf Nennungen nicht überein.
|
||
|
||
Entscheidend ist, *welche* Nennungen das sind. `lg` findet 170-mal
|
||
zusätzlich `AfD` und je 80-mal `Kushner` und `Witkoff`, dazu `Merz`, `Putin`,
|
||
`Trump`, `Siegmund` — also genau die Akteure, um die es in diesem Korpus
|
||
geht. `sm` stuft `AfD` 226-mal als MISC und 23-mal als LOC ein, `lg` 392-mal
|
||
als ORG.
|
||
|
||
Daraus folgen zwei Dinge:
|
||
|
||
1. **`lg`**, denn der Zeitunterschied ist mit 7,3 zu 8,0 Sekunden für den
|
||
Gesamtbestand kein Argument. Der Preis sind 568 MB im Image.
|
||
2. **Den NER-Typen ist nicht zu trauen.** Beide Modelle halten `Merz` für
|
||
einen Ort, `Landtagswahl` für einen Ort und `Ukraine-Krieg` für eine
|
||
Person. Die NER liefert deshalb nur *Kandidatenspannen*; welchen Typ eine
|
||
Nennung hat, entscheidet das Lexikon, nicht das Modell.
|
||
|
||
## Was das Akteursmodul auflöst — und was nicht
|
||
|
||
Gesamtbestand, 3407 Items, 21,1 Sekunden:
|
||
|
||
| | |
|
||
|---|---|
|
||
| Nennungen | 14 652 |
|
||
| aufgelöst | 2 889 (19,7 %) |
|
||
| Lexikon | 5540 Akteure, 416 Amtszeiten |
|
||
|
||
Ein Slot-Lauf erzeugt bitgleich dieselbe Nutzlast wie der Gesamtlauf
|
||
(3407 Codings, 0 Abweichungen).
|
||
|
||
Die 19,7 Prozent klingen niedrig und sind es nicht. Die häufigsten
|
||
unaufgelösten Formen zeigen, warum:
|
||
|
||
| Nennungen | Form | wessen Zuständigkeit |
|
||
|---|---|---|
|
||
| 567 | Sachsen-Anhalt | Geokodierung |
|
||
| 382 | `None` | Ingest-Fehler, siehe oben |
|
||
| 170 | Landtagswahl in Sachsen-Anhalt | Ereignis, kein Akteur |
|
||
| 143 | Berlin | Geokodierung |
|
||
| 119 | Kiew | Geokodierung |
|
||
| 95 | Witkoff | echte Lexikonlücke |
|
||
| 87 | Kushner | echte Lexikonlücke |
|
||
| 56 | Siegmund | echte Lexikonlücke |
|
||
|
||
Drei verschiedene Dinge, die als eine Zahl erscheinen: Orte gehören dem
|
||
nächsten Modul, `None` ist ein Datenfehler, und nur der Rest ist wirklich
|
||
eine Lücke im Lexikon.
|
||
|
||
### Die Lücke hat ein Muster
|
||
|
||
`Witkoff`, `Kushner`, `Siegmund` — US-Sondergesandte und
|
||
Landtagsabgeordnete. Der Spiegel deckt Bundestag, Staats- und
|
||
Regierungschefs, Parteien, Staaten, Leitindex-Unternehmen und internationale
|
||
Organisationen ab. **Landtagsabgeordnete fehlen**, und ausgerechnet dieser
|
||
Korpus wird von einer Landtagswahl beherrscht.
|
||
|
||
Die Spezifikation nennt Landtagsabgeordnete nicht; die Auslassung ist also
|
||
regelkonform, aber für diesen Bestand teuer. Eine zusätzliche
|
||
Spiegelabfrage würde sie schließen.
|
||
|
||
### Zwei Fallen beim Spiegeln
|
||
|
||
**Geratene QIDs.** `Q157617` ist nicht der Bundesrat, sondern die
|
||
Commerzbank. Weil der Lader Einträge über die QID zusammenführt, trug er
|
||
prompt »Bundesrat« als Alias der Commerzbank ein. Handgesetzte QIDs gehören
|
||
geprüft, und `hand.json` sagt das jetzt in seinem Kopf.
|
||
|
||
**`FILTER (lang(?name) = "de")`.** Apple, Microsoft und Meta haben kein
|
||
deutsches Label in Wikidata und fallen deshalb aus jeder Spiegelabfrage —
|
||
lautlos. Ein Rückfall auf `en` wäre beim nächsten Spiegellauf die bessere
|
||
Wahl.
|
||
|
||
### spaCy ist stapelunabhängig
|
||
|
||
Bei Stapelgröße 64, 7 und 1 sowie rückwärts durchlaufen liefert
|
||
`de_core_news_lg` für 400 Items identische Spannen. Der Kunstgriff mit der
|
||
festen Tokenlänge, den die Embeddings brauchen, ist hier nicht nötig.
|
||
|
||
|
||
## Woher `None` wirklich kommt
|
||
|
||
Reproduziert am Live-Feed, nicht erschlossen: bei Items mit leerer
|
||
`<description>` fällt der Poller korrekt auf `content:encoded` zurück, und
|
||
dort liefert die ZEIT
|
||
|
||
```
|
||
<a href="https://www.zeit.de/news/..."><img ...>None</a>
|
||
```
|
||
|
||
Der Ankertext *ist* die Zeichenkette `None` — ein Renderfehler im CMS der
|
||
ZEIT. `klartext()` entfernt die Tags, und übrig bleibt `None`. Phase 1
|
||
schreibt also getreu mit; der Fehler ist stromaufwärts.
|
||
|
||
Am 8. September 2026 betraf das 8 von 15 Items im Feed. Im Prod-Bestand:
|
||
|
||
| Tag | `None` / zeit-Items |
|
||
|---|---|
|
||
| 2026-09-04 | 12 / 20 |
|
||
| 2026-09-05 | 83 / 136 |
|
||
| 2026-09-06 | 187 / 262 |
|
||
| 2026-09-07 | 305 / 400 |
|
||
| 2026-09-08 | 67 / 79 |
|
||
|
||
Gleichbleibend rund 70 bis 85 Prozent — der Fehler läuft weiter.
|
||
|
||
## Container mit spaCy
|
||
|
||
Das Abbild wächst durch `de_core_news_lg` von 1,28 auf 2,12 GB. Das Modell
|
||
liegt im Abbild, nicht im Cache-Volume: 568 MB, die sich nie ändern, und der
|
||
erste Lauf auf Prod soll nicht an einem Download hängen.
|
||
|
||
Gemessen, nicht behauptet: ein Slot-Lauf im Container (Debian trixie,
|
||
Python 3.13) erzeugt für die Akteure bitgleich dieselbe Nutzlast wie die
|
||
Workstation (Fedora, Python 3.14) — 3407 Codings, 0 Abweichungen, gleiche
|
||
`coder_version`.
|