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>
Bisher generierte Haiku Keywords nur in DE/EN/Romaji. Japanische RSS-Feeds
(z.B. MOD-GNews mit "防衛省・自衛隊の宇宙政策") matchten daher nie, weil
"jieitai" ≠ "自衛隊". Arabische/persische Telegram-Channels matchten nur
durch Zufall (lateinische Eigennamen in Hashtags/URLs).
Drei zusammenhängende Änderungen:
1. get_feeds_with_metadata liefert primary_language pro Feed mit.
2. FEED_SELECTION_PROMPT_TEMPLATE und KEYWORD_EXTRACTION_PROMPT verlangen
sprach-gruppierte Keywords ({de:[...], en:[...], ja:[...], ru:[...], ...}).
"en" enthält lateinische Eigennamen (universell). Andere Sprachen werden
nur gegen Feeds derselben Sprache gematcht.
3. RSS- und Telegram-Parser kombinieren pro Feed/Channel die "en"-Universalbegriffe
mit den Keywords der Quellsprache. Die Spezifik-Schwelle (1-Treffer-Match)
greift jetzt auch ab 3 Zeichen bei Non-ASCII (CJK, Arabisch, Kyrillisch).
Backward-kompatibel: flache Keyword-Listen werden weiter akzeptiert.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Neue Spalte sources.primary_language (ISO-2-Code) mit Backfill aus dem
Freitext-Feld language (Erste Sprache vor /-Trennung). Edge-Cases wie
Iran Military Magazine (English) [Farsi/Arabisch] landen als fa und
koennen ueber das Verwaltungsportal manuell justiert werden.
- get_source_rules(tenant_id) bestimmt die Org-Sprache und bucketed Feeds
nach primary (=Org-Sprache) / international (=alle anderen) / behoerden
(Kategorie behoerde). Bei tenant_id=None oder Helper-Fehler default de.
- rss_parser.search_feeds unveraendert in Logik (international=False
laesst weiterhin alle ausser dem international-Bucket durch), Kommentare
generischer formuliert.
Phase 3 von 8 (eng_demo / Org-Sprache).
Bisher hatten Quellen vom Typ web_source keine praktische Wirkung auf
die Recherche - sie lagen nur als Marker in der DB. Jetzt werden sie
aktiv in den Recherche-Prompt eingebunden.
Ablauf:
1. Vor dem Hauptaufruf an Opus prüft ein günstiger Haiku-Call alle
aktiven Web-Quellen des Tenants (plus globale) und wählt die
thematisch passenden aus. Leere Selektion ist ausdrücklich erlaubt.
2. Die ausgewählten Domains werden dem Recherche-Prompt als
"EINGETRAGENE WEB-QUELLEN" Block beigegeben mit der Empfehlung,
gezielt mit "site:domain query" zu suchen, falls thematisch passend.
3. site: ist Empfehlung, kein Zwang - Claude bleibt flexibel und
ergänzt seine sonstige Recherche.
- source_rules.get_feeds_with_metadata: SELECT um notes-Feld erweitert,
damit der Selektor besseren Kontext zur Quelle hat.
- ResearcherAgent.select_relevant_web_sources: neuer Helper analog zu
select_relevant_feeds, mit Skip-Optimierung wenn ≤3 Quellen.
- WEB_SOURCE_SELECTION_PROMPT: explizite Regel "lieber leer als
pauschal alle", verhindert Token-Verschwendung.
- ResearcherAgent.search: neuer Parameter preferred_sources, beide
Templates (RESEARCH + DEEP_RESEARCH) bekommen optionalen
preferred_sources_block.
- Orchestrator._web_search_pipeline: Vorselektion vor researcher.search,
Token-Usage in usage_acc, Logging der gewählten Domains.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Neue Tabelle user_excluded_domains für benutzerspezifische Ausschlüsse
- Domain-Ausschlüsse wirken nur für den jeweiligen User, nicht org-weit
- user_id wird durch die gesamte Pipeline geschleust (Orchestrator → Researcher → RSS-Parser)
- Grundquellen (is_global) können nicht mehr bearbeitet/gelöscht werden im Frontend
- Grundquelle-Badge bei globalen Quellen statt Edit/Delete-Buttons
- Filter Von mir ausgeschlossen im Quellen-Modal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- config.py: MAX_FEEDS_PER_DOMAIN=3, MAX_ARTICLES_PER_DOMAIN_RSS=10
- rss_parser.py: _apply_domain_cap() begrenzt Artikel pro Domain nach RSS-Fetch
- orchestrator.py: Domain-Balance vor Feed-Selektion (max 3 Feeds/Domain),
Domain-Cap in Background-Discovery
- source_rules.py: article_count in get_feeds_with_metadata(), Content-Hash
in _validate_feed() für Duplikat-Erkennung bei Discovery
- researcher.py: QUELLENVIELFALT-Regel im Haiku Feed-Selektions-Prompt
- DB: 52 WordPress-Redirect-Duplikate deaktiviert (netzpolitik.org, bashinho.de)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>