Inkrementelle Analyse + Token-Optimierung + Relevanz-Scoring
TOKEN-OPTIMIERUNG: - Inkrementelle Analyse: Folge-Refreshes senden nur noch das bisherige Lagebild + neue Artikel an Claude (statt alle Artikel erneut). Spart ~60-70% Tokens bei Lagen mit vielen Artikeln. - Inkrementeller Faktencheck: Bestehende Fakten als Zusammenfassung, nur neue Artikel werden vollstaendig geprueft. - Modell-Steuerung: Feed-Selektion nutzt jetzt Haiku (CLAUDE_MODEL_FAST) statt Opus. Spart ~50-70% bei Feed-Auswahl. - Set-basierte DB-Deduplizierung: Bestehende URLs/Headlines einmal in Sets geladen statt N*M einzelne DB-Queries pro Artikel. INHALTLICHE VERBESSERUNGEN: - Relevanz-Scoring: Artikel nach Keyword-Dichte (40%), Quellen-Reputation (30%), Inhaltstiefe (20%), RSS-Score (10%). - Flexibles RSS-Matching: min. Haelfte der Keywords statt alle. RSS-Artikel bekommen einen relevance_score. - Fuzzy Claim-Matching: SequenceMatcher (0.7) statt exakter String-Vergleich. Verhindert Duplikat-Akkumulation. - Translation-Fix: Nur gueltige DB-IDs (isinstance int). - Researcher: WebFetch fuer Top-Artikel, erweiterte Zusammenfassungen. DATEIEN: - config.py: CLAUDE_MODEL_FAST - claude_client.py: model-Parameter - researcher.py: Haiku Feed-Selektion, erweiterte Prompts - analyzer.py: Inkrementelle Analyse + analyze_incremental() - factchecker.py: Inkrementeller Check + Fuzzy-Matching - orchestrator.py: Set-Dedup, Relevanz-Scoring, inkrementeller Flow - rss_parser.py: Flexibles Keyword-Matching + relevance_score
Dieser Commit ist enthalten in:
@@ -121,8 +121,11 @@ class RSSParser:
|
||||
summary = entry.get("summary", "")
|
||||
text = f"{title} {summary}".lower()
|
||||
|
||||
# Prüfe ob mindestens ein Suchwort vorkommt
|
||||
if all(word in text for word in search_words):
|
||||
# Flexibles Keyword-Matching: mindestens die Hälfte der Suchworte muss vorkommen
|
||||
min_matches = max(1, len(search_words) // 2)
|
||||
match_count = sum(1 for word in search_words if word in text)
|
||||
|
||||
if match_count >= min_matches:
|
||||
published = None
|
||||
if hasattr(entry, "published_parsed") and entry.published_parsed:
|
||||
try:
|
||||
@@ -130,6 +133,9 @@ class RSSParser:
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
|
||||
# Relevanz-Score: Anteil der gematchten Suchworte (0.0-1.0)
|
||||
relevance_score = match_count / len(search_words) if search_words else 0.0
|
||||
|
||||
articles.append({
|
||||
"headline": title,
|
||||
"headline_de": title if self._is_german(title) else None,
|
||||
@@ -139,6 +145,7 @@ class RSSParser:
|
||||
"content_de": summary[:1000] if summary and self._is_german(summary) else None,
|
||||
"language": "de" if self._is_german(title) else "en",
|
||||
"published_at": published,
|
||||
"relevance_score": relevance_score,
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren