refactor: Quellen-Merge vom KI-Prompt in Python-Code verlagern

Claude liefert bei der Analyse nur noch neue Quellen statt alle bisherigen
zu wiederholen. Der Merge mit bestehenden Quellen passiert deterministisch
im Code. Spart Tokens und verhindert das versehentliche Vergessen von Quellen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
Claude Dev
2026-03-12 19:08:13 +01:00
Ursprung 2c73b1c8f0
Commit 08aad935c9

Datei anzeigen

@@ -135,12 +135,11 @@ REGELN:
- KEINE Gedankenstriche (—, –) verwenden — stattdessen Kommas, Doppelpunkte oder neue Saetze - KEINE Gedankenstriche (—, –) verwenden — stattdessen Kommas, Doppelpunkte oder neue Saetze
- Bei widersprüchlichen Angaben beide Seiten erwähnen - Bei widersprüchlichen Angaben beide Seiten erwähnen
- Quellen immer mit [Nr] referenzieren - Quellen immer mit [Nr] referenzieren
- Das sources-Array muss ALLE Quellen enthalten (bisherige + neue)
- Ältere Quellen zeitlich einordnen - Ältere Quellen zeitlich einordnen
Antworte AUSSCHLIESSLICH als JSON-Objekt mit diesen Feldern: Antworte AUSSCHLIESSLICH als JSON-Objekt mit diesen Feldern:
- "summary": Aktualisierte Zusammenfassung mit Quellenverweisen [1], [2] etc. - "summary": Aktualisierte Zusammenfassung mit Quellenverweisen [1], [2] etc.
- "sources": VOLLSTÄNDIGES Array aller Quellen (alte + neue), je: {{"nr": 1, "name": "Quellenname", "url": "https://..."}} - "sources": Array mit NUR den NEUEN Quellen aus den neuen Meldungen, je: {{"nr": <fortlaufend>, "name": "Quellenname", "url": "https://..."}}. Alte Quellen werden automatisch gemerged.
- "key_facts": Array aller aktuellen Kernfakten (in Ausgabesprache) - "key_facts": Array aller aktuellen Kernfakten (in Ausgabesprache)
- "translations": Array von Objekten mit "article_id", "headline_de", "content_de" (nur für neue fremdsprachige Artikel) - "translations": Array von Objekten mit "article_id", "headline_de", "content_de" (nur für neue fremdsprachige Artikel)
@@ -180,12 +179,11 @@ REGELN:
- Neue Erkenntnisse einarbeiten - Neue Erkenntnisse einarbeiten
- Veraltete Informationen aktualisieren - Veraltete Informationen aktualisieren
- Quellen immer mit [Nr] referenzieren - Quellen immer mit [Nr] referenzieren
- Das sources-Array muss ALLE Quellen enthalten (bisherige + neue)
- Markdown-Überschriften (##) für die Abschnitte verwenden - Markdown-Überschriften (##) für die Abschnitte verwenden
Antworte AUSSCHLIESSLICH als JSON-Objekt mit diesen Feldern: Antworte AUSSCHLIESSLICH als JSON-Objekt mit diesen Feldern:
- "summary": Das aktualisierte Briefing als Markdown-Text mit Quellenverweisen - "summary": Das aktualisierte Briefing als Markdown-Text mit Quellenverweisen
- "sources": VOLLSTÄNDIGES Array aller Quellen (alte + neue), je: {{"nr": 1, "name": "Quellenname", "url": "https://..."}} - "sources": Array mit NUR den NEUEN Quellen aus den neuen Meldungen, je: {{"nr": <fortlaufend>, "name": "Quellenname", "url": "https://..."}}. Alte Quellen werden automatisch gemerged.
- "key_facts": Array aller gesicherten Kernfakten (in Ausgabesprache) - "key_facts": Array aller gesicherten Kernfakten (in Ausgabesprache)
- "translations": Array von Objekten mit "article_id", "headline_de", "content_de" (nur für neue fremdsprachige Artikel) - "translations": Array von Objekten mit "article_id", "headline_de", "content_de" (nur für neue fremdsprachige Artikel)
@@ -263,13 +261,21 @@ class AnalyzerAgent:
new_articles_text = self._format_articles_text(new_articles, max_articles=20) new_articles_text = self._format_articles_text(new_articles, max_articles=20)
previous_sources_text = "Keine bisherigen Quellen" previous_sources_text = "Keine bisherigen Quellen"
self._all_previous_sources = []
if previous_sources_json: if previous_sources_json:
try: try:
sources = json.loads(previous_sources_json) self._all_previous_sources = json.loads(previous_sources_json)
lines = [] total = len(self._all_previous_sources)
for s in sources: recent = self._all_previous_sources[-100:] if total > 100 else self._all_previous_sources
lines.append(f"[{s.get('nr', '?')}] {s.get('name', '?')}{s.get('url', '?')}") src_lines = []
previous_sources_text = "\n".join(lines) if total > 100:
highest_nr = self._all_previous_sources[-1].get("nr", "?")
src_lines.append(f"(... {total - 100} aeltere Quellen ausgelassen, hoechste Nr: {highest_nr})")
for s in recent:
nr = s.get("nr", "?")
name = s.get("name", "?")
src_lines.append(f"[{nr}] {name}")
previous_sources_text = chr(10).join(src_lines)
except (json.JSONDecodeError, TypeError): except (json.JSONDecodeError, TypeError):
previous_sources_text = "Fehler beim Laden der bisherigen Quellen" previous_sources_text = "Fehler beim Laden der bisherigen Quellen"
@@ -290,7 +296,19 @@ class AnalyzerAgent:
try: try:
result, usage = await call_claude(prompt) result, usage = await call_claude(prompt)
analysis = self._parse_response(result) analysis = self._parse_response(result)
if analysis: if analysis and self._all_previous_sources:
# Merge: alte Quellen beibehalten, neue hinzufuegen
returned_sources = analysis.get("sources", [])
returned_nrs = {s.get("nr") for s in returned_sources}
merged = [s for s in self._all_previous_sources if s.get("nr") not in returned_nrs]
merged.extend(returned_sources)
merged.sort(key=lambda s: s.get("nr", 0) if isinstance(s.get("nr"), int) else 9999)
analysis["sources"] = merged
logger.info(
f"Inkrementelle Analyse abgeschlossen: {len(new_articles)} neue Artikel, "
f"{len(analysis.get('sources', []))} Quellen gesamt (merged)"
)
elif analysis:
logger.info( logger.info(
f"Inkrementelle Analyse abgeschlossen: {len(new_articles)} neue Artikel, " f"Inkrementelle Analyse abgeschlossen: {len(new_articles)} neue Artikel, "
f"{len(analysis.get('sources', []))} Quellen gesamt" f"{len(analysis.get('sources', []))} Quellen gesamt"