feat(fimi): Pipeline-Hook + match_article_ids
Nach dem Translator-Schritt werden die in einem Refresh neu hinzugekommenen Artikel gegen den Falschbehauptungsbestand abgeglichen (nur neue Artikel, nicht der ganze Bestand). Fehler brechen den Refresh nicht ab. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -1806,6 +1806,27 @@ class AgentOrchestrator:
|
||||
await _pipe_done("translate", count_value=0, count_secondary=0)
|
||||
# Refresh trotz Translator-Fehler weiterlaufen lassen
|
||||
|
||||
# --- FIMI: Abgleich gegen den EUvsDisinfo-Falschbehauptungsbestand ---
|
||||
# Nur die in diesem Refresh neu hinzugekommenen Artikel (per ID), nach
|
||||
# dem Translator, damit auch fremdsprachige Artikel ihren DE-Text fuer
|
||||
# die LLM-Verifikation haben. Fehler duerfen den Refresh nicht brechen.
|
||||
try:
|
||||
_fimi_ids = [a.get("id") for a in new_articles_for_analysis if a.get("id")]
|
||||
if _fimi_ids:
|
||||
from services import fimi_matcher
|
||||
_fimi_res = await fimi_matcher.match_article_ids(db, _fimi_ids)
|
||||
logger.info(
|
||||
"FIMI-Abgleich Incident %d: %d Artikel, %d Kandidaten, "
|
||||
"%d verbreiten Falschbehauptungen, %d Links",
|
||||
incident_id, _fimi_res.get("articles", 0),
|
||||
_fimi_res.get("candidates", 0),
|
||||
_fimi_res.get("articles_with_match", 0),
|
||||
_fimi_res.get("stored", 0),
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning("FIMI-Abgleich fehlgeschlagen fuer Incident %d: %s",
|
||||
incident_id, e, exc_info=True)
|
||||
|
||||
# --- Neueste Entwicklungen (nur Live-Monitoring / adhoc) ---
|
||||
# Basis ist jetzt das frisch generierte Lagebild (autoritativ, thematisch sauber).
|
||||
# Zeitstempel und Quellen kommen aus den jüngsten belegenden Artikeln.
|
||||
|
||||
@@ -348,6 +348,26 @@ async def match_and_store_articles(
|
||||
}
|
||||
|
||||
|
||||
async def match_article_ids(
|
||||
db: aiosqlite.Connection,
|
||||
article_ids: list[int],
|
||||
verify: bool | None = None,
|
||||
) -> dict:
|
||||
"""Matcht eine konkrete Menge Artikel (per ID). Pipeline-Einstieg fuer die
|
||||
in einem Refresh neu hinzugekommenen Artikel."""
|
||||
ids = [int(i) for i in article_ids if i]
|
||||
if not ids:
|
||||
return {"articles": 0, "candidates": 0, "articles_with_match": 0, "stored": 0, "errors": 0}
|
||||
qs = ",".join("?" for _ in ids)
|
||||
cursor = await db.execute(
|
||||
f"SELECT id, headline, headline_de, content_original, content_de, tenant_id "
|
||||
f"FROM articles WHERE id IN ({qs})",
|
||||
tuple(ids),
|
||||
)
|
||||
articles = await cursor.fetchall()
|
||||
return await match_and_store_articles(db, articles, verify=verify)
|
||||
|
||||
|
||||
async def match_incident_articles(
|
||||
db: aiosqlite.Connection,
|
||||
incident_id: int,
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren