fix(recherche): Suchbegriffe treffen wieder, Verzeichnis ohne Dubletten
Vier Befunde aus dem Vergleich vom 02.08.2026, sortiert nach Wirkung.
1. Mehrwort-Suchbegriffe fielen im RSS-Abgleich durch. Dieselbe Lage lieferte
je nach Titel 79 oder 17 Treffer. Die Keyword-Erzeugung liefert bei
politisch formulierten Titeln Phrasen ("migrationskrise spanien",
"aufnahmeverfahren eu"), das Matching verglich sie als starre Zeichenfolge.
Die Schlagzeile "Migrationskrise in Spanien" enthaelt "migrationskrise
spanien" nicht, wegen des Wortes dazwischen. Aus 53 Artikeln wurden so 16.
Eine Phrase trifft jetzt, wenn alle ihre Bestandteile im Text vorkommen,
unabhaengig von Reihenfolge und Abstand. Die Genauigkeit bleibt erhalten,
nur die starre Reihenfolge faellt weg.
Dazu der Auftrag an die Keyword-Erzeugung: Einzelwoerter statt Phrasen, und
die harten Eigennamen der Lage sind Pflicht. Bei den betroffenen Laeufen
fehlte "ceuta" komplett, dafuer stand "europol migration" in der Liste, was
den Europol-Feed anzog und sieben themenfremde Pressemitteilungen
einbrachte, die der Topic-Filter danach wieder aussortieren musste.
2. Dubletten im Quellenverzeichnis. Lage 56 fuehrte 30 Eintraege fuer 28
Adressen, zweimal dieselbe tagesschau-Meldung unter je zwei Nummern.
Ausgerechnet die strittigste Behauptung, der offene Brief der 22 Staaten,
stuetzte sich damit auf "3 Quellen", von denen zwei derselbe Artikel waren.
Gleiche Adresse heisst jetzt ein Eintrag, Verweise auf die entfernte Nummer
werden auf den behaltenen umgebogen. Verglichen wird ohne Schema, www und
Endschraegstrich.
3. Die Zeitleiste wird deterministisch sortiert. Im selben Bericht sprang der
letzte Eintrag von 12:44 zurueck auf 17:47. Der Auftrag verlangt die
Sortierung zwar vom Modell, im prominentesten Kapitel darf sie aber nicht
von dessen Sorgfalt abhaengen. Gegenprobe an Lage 56: 23:23, 22:09, 17:47,
16:58 statt des Sprungs ans Ende.
4. Weiterleitungen zaehlen als ein Beleg. Sie verbergen ihr Zielmedium, also
laesst sich nicht behaupten, dass dahinter verschiedene Redaktionen stehen.
Die bisherige Einzelzaehlung stellte den Anthropic-Weg rechnerisch besser:
in Lage 57 standen 10 ausgewiesene Belege fuer 7 Haeuser, weil vier der elf
Adressen news.google.com-Weiterleitungen waren.
Gegenprobe an beiden gespeicherten Laeufen: Lage 56 zeigt 28 statt 30
Verzeichniseintraege, beide Berichte zaehlen lueckenlos, die Zeitleiste ist
sortiert.
Neu sind 26 Pruefungen, insgesamt laufen 206 ohne Netzzugriff und ohne Kosten.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
105
tests/test_rss_treffer.py
Normale Datei
105
tests/test_rss_treffer.py
Normale Datei
@@ -0,0 +1,105 @@
|
||||
"""Testet das Keyword-Matching der RSS-Auswertung.
|
||||
|
||||
Hintergrund: Dieselbe Lage lieferte am 01.08.2026 je nach Titel 79 oder 17
|
||||
RSS-Treffer. Ursache war die Kombination aus zwei Dingen. Die
|
||||
Keyword-Erzeugung lieferte fuer den politisch formulierten Titel Phrasen
|
||||
("migrationskrise spanien", "aufnahmeverfahren eu") statt Einzelbegriffe, und
|
||||
das Matching verglich diese Phrasen als starre Zeichenfolge. Die Schlagzeile
|
||||
"Migrationskrise in Spanien" enthaelt "migrationskrise spanien" nicht, wegen
|
||||
des Wortes dazwischen. Aus 53 Artikeln wurden so 16.
|
||||
|
||||
Laeuft ohne Netzzugriff und ohne Kosten.
|
||||
|
||||
Aufruf aus dem Projektstamm:
|
||||
venv/bin/python tests/test_rss_treffer.py
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "src"))
|
||||
|
||||
from feeds.rss_parser import wort_trifft, _is_specific_word # noqa: E402
|
||||
from agents.researcher import FEED_SELECTION_PROMPT_TEMPLATE # noqa: E402
|
||||
|
||||
ok = 0
|
||||
fail = 0
|
||||
|
||||
|
||||
def pruefe(name, bedingung, extra=""):
|
||||
global ok, fail
|
||||
if bedingung:
|
||||
ok += 1
|
||||
print(" OK " + name)
|
||||
else:
|
||||
fail += 1
|
||||
print(" FEHL " + name + " " + str(extra))
|
||||
|
||||
|
||||
SCHLAGZEILE = (
|
||||
"migrationskrise in spanien: eu-innenminister beraten am dienstag über ceuta"
|
||||
).lower()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# A. Einzelbegriffe verhalten sich wie bisher
|
||||
# ---------------------------------------------------------------------------
|
||||
print("\nA. Einzelbegriffe")
|
||||
pruefe("A1 enthaltenes Wort trifft", wort_trifft("ceuta", SCHLAGZEILE))
|
||||
pruefe("A2 nicht enthaltenes Wort trifft nicht", not wort_trifft("marokko", SCHLAGZEILE))
|
||||
pruefe("A3 Wortteil trifft weiterhin (Komposita)", wort_trifft("migration", SCHLAGZEILE))
|
||||
pruefe("A4 leeres Wort trifft nie", not wort_trifft("", SCHLAGZEILE))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# B. Phrasen treffen wortweise
|
||||
# ---------------------------------------------------------------------------
|
||||
print("\nB. Mehrwort-Begriffe")
|
||||
pruefe("B1 Phrase mit Wort dazwischen trifft jetzt",
|
||||
wort_trifft("migrationskrise spanien", SCHLAGZEILE))
|
||||
pruefe("B2 Phrase in umgekehrter Reihenfolge trifft",
|
||||
wort_trifft("spanien migrationskrise", SCHLAGZEILE))
|
||||
pruefe("B3 zusammenhaengende Phrase trifft weiterhin",
|
||||
wort_trifft("eu-innenminister beraten", SCHLAGZEILE))
|
||||
pruefe("B4 fehlt ein Bestandteil, trifft die Phrase nicht",
|
||||
not wort_trifft("migrationskrise portugal", SCHLAGZEILE))
|
||||
pruefe("B5 abstrakte Phrase ohne Bezug trifft nicht",
|
||||
not wort_trifft("aufnahmeverfahren eu", SCHLAGZEILE))
|
||||
|
||||
# Der gemeldete Fall: zehn Begriffe, davon neun Phrasen.
|
||||
KEYWORDS_LAGE_55 = [
|
||||
"migrationskrise spanien", "eu-innenminister", "südgrenze spanien",
|
||||
"mittelmeer migration", "grenzschutz europa", "flüchtlinge mittelmeer",
|
||||
"überfahrten mittelmeer", "schengen-außengrenzen", "europol migration",
|
||||
"aufnahmeverfahren eu",
|
||||
]
|
||||
treffer = sum(1 for w in KEYWORDS_LAGE_55 if wort_trifft(w, SCHLAGZEILE))
|
||||
alt_treffer = sum(1 for w in KEYWORDS_LAGE_55 if w in SCHLAGZEILE)
|
||||
pruefe("B6 der gemeldete Keyword-Satz trifft die Schlagzeile jetzt",
|
||||
treffer >= 2, (treffer, alt_treffer))
|
||||
pruefe("B7 vorher traf nur der eine Einzelbegriff", alt_treffer == 1, alt_treffer)
|
||||
|
||||
# Die Schwelle bleibt unveraendert streng: ohne spezifisches Wort im Text
|
||||
# braucht es mehrere Treffer.
|
||||
FREMDE = "fussball bundesliga spieltag zusammenfassung".lower()
|
||||
pruefe("B8 fremde Schlagzeile bleibt ohne Treffer",
|
||||
sum(1 for w in KEYWORDS_LAGE_55 if wort_trifft(w, FREMDE)) == 0)
|
||||
pruefe("B9 Spezifik-Erkennung unveraendert",
|
||||
_is_specific_word("migrationskrise spanien") and not _is_specific_word("eu"))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# C. Der Auftrag verlangt Einzelbegriffe und Eigennamen
|
||||
# ---------------------------------------------------------------------------
|
||||
print("\nC. Auftrag an die Keyword-Erzeugung")
|
||||
for stichwort, name in (
|
||||
("EINZELWÖRTER", "C1 Einzelwoerter statt Phrasen gefordert"),
|
||||
("Eigennamen der Lage MÜSSEN", "C2 Eigennamen sind Pflicht"),
|
||||
("Schauplatz", "C3 Schauplatz wird ausdruecklich genannt"),
|
||||
("KEINE abstrakten Politikbegriffe", "C4 abstrakte Begriffe ausgeschlossen"),
|
||||
):
|
||||
pruefe(name, stichwort in FEED_SELECTION_PROMPT_TEMPLATE)
|
||||
pruefe("C5 Beispiel nennt den konkreten Fehlerfall",
|
||||
"ceuta" in FEED_SELECTION_PROMPT_TEMPLATE.lower())
|
||||
|
||||
print("\nErgebnis: " + str(ok) + " bestanden, " + str(fail) + " fehlgeschlagen")
|
||||
sys.exit(1 if fail else 0)
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren