feat(recency): Frische-Suchfeed (when:14d) + Aktualitaets-Score

Damit die Pipeline das aktuelle Bild einfaengt, nicht nur das relevanteste
(oft Monate alt). Bei der Test-Lage Qilin war der neueste Artikel 7 Wochen
alt, die Masse 6-7 Monate — weil Google-News-Volltextsuche nach Relevanz
rankt, nicht nach Datum.

- build_news_search_feeds: neuer Parameter recency_days. Wenn gesetzt, wird
  der Google-News-Operator "when:Nd" an die Query gehaengt — der Feed liefert
  nur Artikel der letzten N Tage. Eigene Domain-Gruppe '...-recent'.
- orchestrator._rss_pipeline: baut jetzt ZWEI Suchfeed-Saetze — einen
  Kontext-Feed (alle Zeiten) und einen Frische-Feed (when:14d). Beide laufen
  durch dieselbe Pipeline, Dedup entfernt Ueberschneidungen.
- rss_parser._fetch_feed: relevance_score bekommt einen Aktualitaets-Bonus
  (<=3d +0.35, <=14d +0.20, <=60d +0.05) bzw. -Malus (>180d -0.15, >365d
  -0.30). Damit ueberleben frische Artikel den Domain-Cap statt von alten
  verdraengt zu werden.

Nur adhoc-Pfad betroffen — research-Lagen ueberspringen die RSS-Pipeline
ohnehin und behalten ihre volle historische Tiefe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
2026-05-22 02:32:55 +02:00
Ursprung 309c97f40a
Commit 86b12a156e
3 geänderte Dateien mit 53 neuen und 10 gelöschten Zeilen

Datei anzeigen

@@ -932,11 +932,21 @@ class AgentOrchestrator:
_gnews_langs = list(source_lang_whitelist)
else:
_gnews_langs = list({output_language_iso, research_language_iso})
# Zwei Sets: ein Kontext-Feed (alle Zeiten) + ein Frische-Feed
# (when:14d). Der Frische-Feed garantiert, dass das aktuelle
# Bild eingefangen wird, auch wenn aeltere Artikel relevanter
# ranken. Beide laufen durch dieselbe Pipeline; Dedup entfernt
# Ueberschneidungen.
_gnews_feeds = build_news_search_feeds(keywords, _gnews_langs)
if _gnews_feeds:
logger.info(f"Google-News-Suchfeeds ergaenzt: {len(_gnews_feeds)}")
_gnews_recent = build_news_search_feeds(keywords, _gnews_langs, recency_days=14)
_all_gnews = _gnews_feeds + _gnews_recent
if _all_gnews:
logger.info(
f"Google-News-Suchfeeds ergaenzt: {len(_gnews_feeds)} Kontext "
f"+ {len(_gnews_recent)} Frische (when:14d)"
)
articles = await rss_parser.search_feeds_selective(
title, selected_feeds + _gnews_feeds, keywords=keywords,
title, selected_feeds + _all_gnews, keywords=keywords,
)
else:
articles = await rss_parser.search_feeds(title, international=international, tenant_id=tenant_id, keywords=keywords, user_id=user_id)