feat(multitenancy): Sprach-Whitelist + Translator-Override + Forum-Quellenklasse
Vorbereitung fuer jp_demo-Organisation: drei separate Sprach-Settings statt einer einzigen output_language. org_settings.py: - get_source_language_whitelist: Liste erlaubter Quellsprachen als JSON-Array (z.B. ["ja"] beschraenkt RSS/Telegram auf japanische Quellen). - get_research_language: Sprache fuer WebSearch-Prompts (Default: output_language). - get_translator_enabled: Pro-Org-Override des globalen TRANSLATOR_ENABLED-Flags. - LANGUAGE_DISPLAY_NAMES um ja/zh/ko/ru/ar/fa/he/fr/es erweitert. source_rules.py: - get_feeds_with_metadata filtert nach source_language_whitelist, wenn gesetzt. - Feeds ohne primary_language fallen bei aktiver Whitelist raus (gewollt). - SELECT um media_type erweitert, damit es im Feed-Dict ankommt. orchestrator.py: - Laedt research_language, source_language_whitelist, translator_enabled aus den Org-Settings. - Wenn Whitelist gesetzt: international_sources-Flag wird ignoriert. - research_language_iso wird an researcher.search() weitergegeben. - translate_articles bekommt enabled-Parameter aus Org-Setting. - Geoparsing ueberspringt media_type='forum' Artikel. - SELECT * FROM articles wird zu JOIN sources, damit media_type beim Reload am Article-Dict haengt. researcher.py: - search() akzeptiert research_language_iso. Asymmetrische Sprach-Auswahl (Recherche != Output) erzeugt eigene Prompt-Anweisung "primaer in Quell- sprache, englische Region-Outlets erlaubt". translator.py: - translate_articles akzeptiert enabled-Parameter. Ueberschreibt die globale TRANSLATOR_ENABLED-Konstante pro Aufruf. factchecker.py: - _format_articles_text filtert Artikel mit media_type='forum' aus. Anonyme Foren-Posts gelten nicht als Faktenbeleg. rss_parser.py: - _fetch_feed traegt media_type aus feed_config ins Article-Dict ein, damit downstream Pipeline-Schritte Foren-Quellen erkennen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -431,9 +431,27 @@ class FactCheckerAgent:
|
||||
"""Prüft Fakten über Claude CLI gegen unabhängige Quellen."""
|
||||
|
||||
def _format_articles_text(self, articles: list[dict], max_articles: int = 20) -> str:
|
||||
"""Formatiert Artikel als Text für den Prompt."""
|
||||
"""Formatiert Artikel als Text für den Prompt.
|
||||
|
||||
Foren-Quellen (media_type='forum', z.B. 5ch/Hatena/Note) werden hier
|
||||
ausgeschlossen — sie sind Stimmungsmaterial, kein Faktenbeleg. Ein
|
||||
anonymer Forenpost darf nicht als "Quelle bestaetigt Behauptung X"
|
||||
gelten.
|
||||
"""
|
||||
# Falls media_type am Dict vorhanden ist, Foren-Quellen ausfiltern.
|
||||
# Bei Article-Dicts aus dem RSS-/Pre-Topic-Pfad ist das Feld gesetzt;
|
||||
# bei Reload aus der DB muss der Orchestrator das per JOIN annotieren.
|
||||
non_forum = [a for a in articles if (a.get("media_type") or "").lower() != "forum"]
|
||||
skipped = len(articles) - len(non_forum)
|
||||
if skipped > 0:
|
||||
logger.info(
|
||||
"Faktencheck: %d Foren-Quellen (media_type='forum') ausgeschlossen, "
|
||||
"%d Artikel als Faktenbeleg-Kandidaten",
|
||||
skipped, len(non_forum),
|
||||
)
|
||||
|
||||
articles_text = ""
|
||||
for i, article in enumerate(articles[:max_articles]):
|
||||
for i, article in enumerate(non_forum[:max_articles]):
|
||||
articles_text += f"\n--- Meldung {i+1} ---\n"
|
||||
articles_text += f"Quelle: {article.get('source', 'Unbekannt')}\n"
|
||||
source_url = article.get('source_url', '')
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren