v1.9.6: pendelbus/shuttlebus naar zwak + zwak-alleen moet titel-anker hebben
Aanleiding: Omroep Brabant-golfbericht (Solheim Cup Cromvoirt, 11-09-2026) kwam door het filter. 'pendelbus' stond op de whitelist (evenementpendel vanaf station Den Bosch), en 'station'+'bus'+'pendelbus' in de samenvatting was samen al drempel 3. - pendelbus/shuttlebus: whitelist + medium -> zwak (1), één familie (synoniemen tellen niet als twee onafhankelijke signalen). - _filter_passes: bij uitsluitend zwakke hits moet minstens één zwak woord in de TITEL staan; zwakke woorden alleen in de samenvatting zijn geen bewijs. - validate_filter.py: invariant 1 uitgebreid + 3 regressiecases (golfbericht, zwak-alleen samenvatting, positieve controle met titel-anker). - _filter_summary()/docstrings gelijkgetrokken met de werkelijke gewichten.
This commit is contained in:
parent
3cdc02aebe
commit
1f168b2f54
3 changed files with 59 additions and 27 deletions
|
|
@ -56,9 +56,12 @@ rss_change_level = EventType.find("xyz.maubot.rss", t_class=EventType.Class.STAT
|
||||||
# Gewicht 2 (medium): één woord in de titel volstaat; in de samenvatting moet er
|
# Gewicht 2 (medium): één woord in de titel volstaat; in de samenvatting moet er
|
||||||
# een tweede OV-woord bijkomen.
|
# een tweede OV-woord bijkomen.
|
||||||
# Gewicht 1 (zwak/dubbelzinnig: los "bus", "breng", "overweg", "overwegen", "sein",
|
# Gewicht 1 (zwak/dubbelzinnig: los "bus", "breng", "overweg", "overwegen", "sein",
|
||||||
# "kaartje", "opwaarderen", "rails"): moet met een ander OV-woord combineren (een
|
# "kaartje", "opwaarderen", "rails", "pendelbus"): moet met een ander OV-woord
|
||||||
# tweede, andere familie — dezelfde zwakke familie in titel én samenvatting telt
|
# combineren (een tweede, andere familie — dezelfde zwakke familie in titel én
|
||||||
# niet als combinatie). Weert zo "VW-bus"/"schoolbus", "weer op de rails", het
|
# samenvatting telt niet als combinatie) EN minstens één zwak woord moet in de
|
||||||
|
# TITEL staan: een combinatie van alleen zwakke woorden in de samenvatting is
|
||||||
|
# geen bewijs (het golfbericht met "station" + "pendelbus" + "bus" in de
|
||||||
|
# samenvatting is geen OV-nieuws). Weert zo "VW-bus"/"schoolbus", "weer op de rails", het
|
||||||
# werkwoord "brengen" ("hoe breng je ... in beeld"), het idioom "goed met elkaar
|
# werkwoord "brengen" ("hoe breng je ... in beeld"), het idioom "goed met elkaar
|
||||||
# overweg kunnen", het werkwoord "overwegen" ("gratieverlening overwegen"), het
|
# overweg kunnen", het werkwoord "overwegen" ("gratieverlening overwegen"), het
|
||||||
# werkwoord "opwaarderen" ("een wijk opwaarderen") en brandweerjargon
|
# werkwoord "opwaarderen" ("een wijk opwaarderen") en brandweerjargon
|
||||||
|
|
@ -101,7 +104,15 @@ rss_change_level = EventType.find("xyz.maubot.rss", t_class=EventType.Class.STAT
|
||||||
# woord nooit de doorslag kan geven. Bekende dubbelzinnige:
|
# woord nooit de doorslag kan geven. Bekende dubbelzinnige:
|
||||||
# trein, bus, station(s), sprinter, reiziger, vervoerder,
|
# trein, bus, station(s), sprinter, reiziger, vervoerder,
|
||||||
# inchecken/uitchecken, sein, overweg, breng, kaartje,
|
# inchecken/uitchecken, sein, overweg, breng, kaartje,
|
||||||
# opwaarderen, rails, dienstregeling, chipkaart, ontsporen.
|
# opwaarderen, rails, dienstregeling, chipkaart, ontsporen,
|
||||||
|
# pendelbus/shuttlebus (evenement-/hotel-/parkeerpendel;
|
||||||
|
# synoniemen -> bewust één familie, anders tellen twee
|
||||||
|
# synoniemen als twee onafhankelijke signalen).
|
||||||
|
# EXTRA REGEL voor zwak-alleen: staat er uitsluitend zwak
|
||||||
|
# bewijs in de SAMENVATTING (geen enkele zwakke hit in de
|
||||||
|
# titel), dan niet doorlaten. Twee/meer zwakke woorden in
|
||||||
|
# de samenvatting zijn anders samen al 3 punten
|
||||||
|
# ("station" + "pendelbus" + "bus" in een golfverslag).
|
||||||
# 3. BLACKLIST -> gematchte woorden zonder OV-waarde (stationsstraat,
|
# 3. BLACKLIST -> gematchte woorden zonder OV-waarde (stationsstraat,
|
||||||
# stationair, stationcar, ...); blokkeren de familie niet.
|
# stationair, stationcar, ...); blokkeren de familie niet.
|
||||||
#
|
#
|
||||||
|
|
@ -128,13 +139,14 @@ MATCH_FILTER_FAMILIES: list[tuple[str, int]] = [
|
||||||
# medium (2)
|
# medium (2)
|
||||||
(r"\btrams?\b", 2),
|
(r"\btrams?\b", 2),
|
||||||
(r"\bmetro(?:'?s)?\b", 2),
|
(r"\bmetro(?:'?s)?\b", 2),
|
||||||
(r"\b(?:openbaar vervoer|lightrail|pendelbus|shuttlebus|halte|bushokje|busbaan)\w*\b", 2),
|
(r"\b(?:openbaar vervoer|lightrail|halte|bushokje|busbaan)\w*\b", 2),
|
||||||
(r"\b(?:ov-chipkaart|ovpay|ov-pay|studentenreisproduct)\w*\b", 2),
|
(r"\b(?:ov-chipkaart|ovpay|ov-pay|studentenreisproduct)\w*\b", 2),
|
||||||
(r"\b(?:ov-staking|conducteursstaking)\w*\b", 2),
|
(r"\b(?:ov-staking|conducteursstaking)\w*\b", 2),
|
||||||
(r"\bconduct(?:eur|eurs)\b", 2), # trein-/buspersoneel: onmiskenbaar OV-jargon
|
(r"\bconduct(?:eur|eurs)\b", 2), # trein-/buspersoneel: onmiskenbaar OV-jargon
|
||||||
(r"\b(?:pont|ponten)\b", 2), # waterbus/veerdienst
|
(r"\b(?:pont|ponten)\b", 2), # waterbus/veerdienst
|
||||||
# zwak (1) — dubbelzinnig, moet combineren
|
# zwak (1) — dubbelzinnig, moet combineren
|
||||||
(r"(?<!-)\bbus(?:sen)?\b", 1), # ná een koppelteken geen OV: 'VW-bus', 'school-bus'
|
(r"(?<!-)\bbus(?:sen)?\b", 1), # ná een koppelteken geen OV: 'VW-bus', 'school-bus'
|
||||||
|
(r"\b(?:pendelbus|shuttlebus)\w*\b", 1), # evenement-/hotel-/parkeerpendel ('pendelbus naar de golfbaan') is geen OV; synoniemen bewust in één familie
|
||||||
(r"\b(?:inchecken|uitchecken)\w*\b", 1), # ook op luchthavens/hotels — geen OV-jargon, moet combineren
|
(r"\b(?:inchecken|uitchecken)\w*\b", 1), # ook op luchthavens/hotels — geen OV-jargon, moet combineren
|
||||||
(r"\bsprinters?\b", 1), # ook atleet ('sprinter verpulvert record') — aparte familie, moet combineren
|
(r"\bsprinters?\b", 1), # ook atleet ('sprinter verpulvert record') — aparte familie, moet combineren
|
||||||
(r"\bvervoerders?\b", 1), # ook logistiek ('vrachtvervoerder') — aparte familie, moet combineren
|
(r"\bvervoerders?\b", 1), # ook logistiek ('vrachtvervoerder') — aparte familie, moet combineren
|
||||||
|
|
@ -201,7 +213,7 @@ MATCH_FILTER_WHITELIST: frozenset[str] = frozenset({
|
||||||
"busstaking", "tramhalte", "tramlijn", "tramnet", "tramverkeer",
|
"busstaking", "tramhalte", "tramlijn", "tramnet", "tramverkeer",
|
||||||
"metrostation", "metrolijn", "metroverkeer",
|
"metrostation", "metrolijn", "metroverkeer",
|
||||||
# Tarief/vervoerder-jargon
|
# Tarief/vervoerder-jargon
|
||||||
"ov-chipkaart", "ov-staking", "lightrail", "pendelbus", "shuttlebus",
|
"ov-chipkaart", "ov-staking", "lightrail",
|
||||||
"conducteur", "conducteurs",
|
"conducteur", "conducteurs",
|
||||||
"openbaar vervoer",
|
"openbaar vervoer",
|
||||||
})
|
})
|
||||||
|
|
@ -378,16 +390,19 @@ class RSSBot(Plugin):
|
||||||
"""Gewogen familiescore: doorlaten bij 2×(titelscore) + 1×(samenvattingscore) >= drempel.
|
"""Gewogen familiescore: doorlaten bij 2×(titelscore) + 1×(samenvattingscore) >= drempel.
|
||||||
|
|
||||||
Sterke families (gewicht 3) halen de drempel al met één woord in titel óf
|
Sterke families (gewicht 3) halen de drempel al met één woord in titel óf
|
||||||
samenvatting. Medium (2) in de titel ook; in de samenvatting moet een tweede
|
samenvatting. Medium (2) in de titel ook; in de samenvatting moet er een
|
||||||
OV-woord bijkomen. Zwakke woorden (losse 'bus', 'breng', 'overweg', 'overwegen',
|
tweede OV-woord bijkomen.
|
||||||
'sein', 'opwaarderen', 'kaartje', 'rails') moeten combineren met een ander
|
Zwakke woorden (losse 'bus', 'breng', 'overweg', 'overwegen', 'sein',
|
||||||
OV-woord; dezelfde zwakke familie in titel én samenvatting is géén combinatie.
|
'opwaarderen', 'kaartje', 'rails', 'pendelbus') moeten combineren met een
|
||||||
Weert oa 'VW-bus' (bus matcht niet ná een koppelteken), 'schoolbus', 'bussen
|
ander OV-woord én minstens één zwak woord moet in de titel staan; dezelfde
|
||||||
rijden om' in een woningbrand-lead, het werkwoord 'brengen', het idioom 'goed
|
zwakke familie in titel én samenvatting is géén combinatie. Weert oa
|
||||||
met elkaar overweg kunnen', 'een wijk opwaarderen', brandweerjargon
|
'VW-bus' (bus matcht niet ná een koppelteken), 'schoolbus', 'bussen rijden
|
||||||
'sein brandmeester' en figuratief 'weer op de rails'.
|
om' in een woningbrand-lead, het werkwoord 'brengen', het idioom 'goed met
|
||||||
Bewust doorgelaten: krant 'De Metro'/café 'De Tram' (medium), film-'treinramp'
|
elkaar overweg kunnen', 'een wijk opwaarderen', brandweerjargon
|
||||||
en atleet-'sprinter' (sterk)."""
|
'sein brandmeester', figuratief 'weer op de rails' en een golfverslag
|
||||||
|
waarin de samenvatting 'station' + 'pendelbus' + 'bus' noemt.
|
||||||
|
Bewust doorgelaten: krant 'De Metro'/café 'De Tram' (medium) en atleet-
|
||||||
|
'sprinter' in combinatie met ander OV-woord."""
|
||||||
# Whitelist: één onmiskenbare OV-term (titel óf samenvatting) laat altijd door.
|
# Whitelist: één onmiskenbare OV-term (titel óf samenvatting) laat altijd door.
|
||||||
if RSSBot._whitelist_hit(title) or RSSBot._whitelist_hit(summary):
|
if RSSBot._whitelist_hit(title) or RSSBot._whitelist_hit(summary):
|
||||||
return True
|
return True
|
||||||
|
|
@ -396,8 +411,12 @@ class RSSBot(Plugin):
|
||||||
score = 2 * sum(w for _, w in t_hits) + sum(w for _, w in s_hits)
|
score = 2 * sum(w for _, w in t_hits) + sum(w for _, w in s_hits)
|
||||||
if score < MATCH_FILTER_THRESHOLD:
|
if score < MATCH_FILTER_THRESHOLD:
|
||||||
return False
|
return False
|
||||||
# Alleen zwakke families? Dan moet een tweede (verschillende) familie meetellen.
|
if max(w for _, w in t_hits + s_hits) == 1:
|
||||||
if max(w for _, w in t_hits + s_hits) == 1 and len({i for i, _ in t_hits + s_hits}) < 2:
|
# Alleen zwakke families: dan moeten ≥2 verschillende families meetellen
|
||||||
|
# én minstens één zwak woord moet in de TITEL staan. Zwakke woorden in
|
||||||
|
# de samenvatting alleen zijn geen bewijs ('station' + 'pendelbus' +
|
||||||
|
# 'bus' in een golfverslag telt anders op tot de drempel).
|
||||||
|
if not t_hits or len({i for i, _ in t_hits + s_hits}) < 2:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
@ -406,17 +425,20 @@ class RSSBot(Plugin):
|
||||||
"""Mensvriendelijke weergave van het vaste gewogen match-filter."""
|
"""Mensvriendelijke weergave van het vaste gewogen match-filter."""
|
||||||
return (
|
return (
|
||||||
"**OV-matchfilter (vast in code, gewogen families):**\n"
|
"**OV-matchfilter (vast in code, gewogen families):**\n"
|
||||||
"- Sterk (3): vervoerders (NS, Arriva, ProRail, Qbuzz, ...), spoorinfra (spoorlijn, spoorwegovergang, seinstoring, perron), "
|
"- Sterk (3): vervoerders (NS, Arriva, ProRail, Qbuzz, ...), spoorinfra (spoorlijn, spoorwegovergang, perron, spoorstoring), "
|
||||||
"station(s), bushalte/buslijn/bushokje/busstation, intercity/sprinter/streekvervoer/veerdienst/buurtbus, 'lijn 12'\n"
|
"trein-/metro-/busstation, samenstellingen als bushalte/buslijn/bushokje/busbaan/busverkeer, treinstoring/treinverkeer/treinstaking, "
|
||||||
"- Medium (2): tram, metro, openbaar vervoer/dienstregeling/inchecken, halte, bushokje, busbaan, vervoerder, reiziger, "
|
"intercity/streekvervoer/veerdienst/buurtbus/belbus, 'lijn 12'\n"
|
||||||
"ov-chipkaart/ovpay/reisproduct, ov-staking, pont\n"
|
"- Medium (2): tram, metro, openbaar vervoer, lightrail, halte, pont, ov-chipkaart/ovpay, ov-staking, conducteur\n"
|
||||||
"- Zwak (1): losse 'bus' (niet ná een koppelteken), 'trein', 'breng', 'overweg', 'overwegen', 'sein', 'kaartje', 'opwaarderen', 'rails' — moet combineren met een ander OV-woord\n\n"
|
"- Zwak (1): losse 'bus' (niet ná een koppelteken), 'pendelbus'/'shuttlebus', 'trein', 'station(s)', 'breng', 'overweg', 'overwegen', "
|
||||||
|
"'sein', 'kaartje', 'opwaarderen', 'rails', 'inchecken'/'uitchecken', 'dienstregeling', 'chipkaart', 'reisproduct', 'vervoersbewijs', "
|
||||||
|
"'ontsporen', 'reiziger', 'vervoerder', 'sprinter' — moet combineren met een ander OV-woord, met minstens één zwak woord in de titel\n\n"
|
||||||
"**Whitelist (altijd door):** één onmiskenbare OV-term in titel óf samenvatting is genoeg "
|
"**Whitelist (altijd door):** één onmiskenbare OV-term in titel óf samenvatting is genoeg "
|
||||||
"(NS, ProRail, Nederlandse Spoorwegen, spoorstoring, perron, bushalte, metrostation, conducteur, "
|
"(NS, ProRail, Nederlandse Spoorwegen, spoorstoring, perron, bushalte, metrostation, conducteur, "
|
||||||
"ov-chipkaart, ovpay, openbaar vervoer, dienstregeling, ...)\n\n"
|
"ov-chipkaart, ovpay, openbaar vervoer, ...)\n\n"
|
||||||
"Uitgesloten (blacklist): woorden die wél matchen maar geen OV-waarde hebben, "
|
"Uitgesloten (blacklist): woorden die wél matchen maar geen OV-waarde hebben, "
|
||||||
"o.a. straatnamen rond stations ('stationsstraat', 'stationsweg', ...) en niet-OV-vormen als 'stationcar' en 'stationair'\n\n"
|
"o.a. straatnamen rond stations ('stationsstraat', 'stationsweg', ...) en niet-OV-vormen als 'stationcar' en 'stationair'\n\n"
|
||||||
"Doorlaten: `2×(titel-score) + 1×(samenvatting-score) ≥ 3`"
|
"Doorlaten: `2×(titel-score) + 1×(samenvatting-score) ≥ 3`; bij uitsluitend zwakke woorden tellen alleen "
|
||||||
|
"≥2 verschillende families én een zwak woord in de titel"
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _send(
|
async def _send(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
id: nl.eddydevink.rss
|
id: nl.eddydevink.rss
|
||||||
version: 1.9.5
|
version: 1.9.6
|
||||||
modules:
|
modules:
|
||||||
- buzzrss
|
- buzzrss
|
||||||
main_class: RSSBot
|
main_class: RSSBot
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ AMBIGUOUS = [
|
||||||
"inchecken", "uitchecken", "sein", "overweg", "overwegen", "breng",
|
"inchecken", "uitchecken", "sein", "overweg", "overwegen", "breng",
|
||||||
"kaartje", "opwaarderen", "rails", "dienstregeling", "chipkaart",
|
"kaartje", "opwaarderen", "rails", "dienstregeling", "chipkaart",
|
||||||
"reisproduct", "vervoersbewijs", "vervoerbewijs",
|
"reisproduct", "vervoersbewijs", "vervoerbewijs",
|
||||||
|
"pendelbus", "shuttlebus",
|
||||||
"ontspor", "ontspoor", "ontspoord", "ontspoorde", "ontsporing",
|
"ontspor", "ontspoor", "ontspoord", "ontspoorde", "ontsporing",
|
||||||
]
|
]
|
||||||
print(f"== invariant 1: {len(AMBIGUOUS)} dubbelzinnige woorden -> alleen zwak (1), nooit whitelist ==")
|
print(f"== invariant 1: {len(AMBIGUOUS)} dubbelzinnige woorden -> alleen zwak (1), nooit whitelist ==")
|
||||||
|
|
@ -123,7 +124,16 @@ GOLDEN = [
|
||||||
("Fietser gewond op de Stationsstraat", "Het slachtoffer is naar het ziekenhuis gebracht.", False),
|
("Fietser gewond op de Stationsstraat", "Het slachtoffer is naar het ziekenhuis gebracht.", False),
|
||||||
("Kunstenaar maakt kaartje voor het museum", "", False),
|
("Kunstenaar maakt kaartje voor het museum", "", False),
|
||||||
("Benzineprijs stijgt opnieuw", "De pomp wordt duurder door de olieprijs.", False),
|
("Benzineprijs stijgt opnieuw", "De pomp wordt duurder door de olieprijs.", False),
|
||||||
|
# geweerd — zwakke woorden alléén in de samenvatting (geen titel-anker).
|
||||||
|
# Echt geval: Omroep Brabant, Solheim Cup-golfverslag (11-09-2026) — 'pendelbus'
|
||||||
|
# stond op de whitelist en 'station'+'pendelbus'+'bus' in de samenvatting was
|
||||||
|
# samen score 3.
|
||||||
|
("Golf-fans uit de hele wereld naar Cromvoirt: 'Beter dan sterrenrestaurant'",
|
||||||
|
"Op het station in Den Bosch stapte de oud-prof in de pendelbus naar Bernardus Golf. "
|
||||||
|
"In de bus bleek ze zeker niet de enige Amerikaanse.", False),
|
||||||
|
("Toernooi trekt duizenden bezoekers", "Vanaf het station rijden pendelbussen en extra bussen.", False),
|
||||||
# door — echte OV-berichten
|
# door — echte OV-berichten
|
||||||
|
("Trein vertraagd, reizigers pakken de bus", "De storing duurde een uur.", True),
|
||||||
("Station Amersfoort krijgt nieuwe perrons", "De NS laat de perrons vernieuwen.", True),
|
("Station Amersfoort krijgt nieuwe perrons", "De NS laat de perrons vernieuwen.", True),
|
||||||
("Trein ontspoorde bij Weesp", "De spoorlijn was uren dicht.", True),
|
("Trein ontspoorde bij Weesp", "De spoorlijn was uren dicht.", True),
|
||||||
("Bushalte aan de Markt wordt verplaatst", "De halte gaat 200 meter opschuiven.", True),
|
("Bushalte aan de Markt wordt verplaatst", "De halte gaat 200 meter opschuiven.", True),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue