Translator-Agent: dedizierter Haiku-Pass fuer fehlende DE-Uebersetzungen
Bisher haben translations als Teil der Analyzer-JSON-Antwort gelebt
("translations": [...]). Bei vielen Artikeln pro Refresh hat das LLM die
Translations regelmaessig weggelassen (Output-Token-Druck), insbesondere
content_de (lange Texte werden zuerst gestrichen). Folge: viele englische
Artikel ohne deutsche Headline/Inhalt im Frontend.
Aenderungen:
- Neuer Agent src/agents/translator.py:
* translate_articles_batch / translate_articles
* Nutzt CLAUDE_MODEL_FAST (Haiku) - billig
* Batch-Size 5 (mit Reserve gegen Output-Truncate)
* Robustes JSON-Parsing: Markdown-Codefence, Truncate-Fallback,
extrahiert auch unvollstaendige Antworten
* Idempotent: Caller filtert auf fehlende headline_de/content_de
- analyzer.py: translations aus 4 Prompt-Templates entfernt (adhoc/research
x analyze/enhance) und Fallback-Return-Dict bereinigt -> Analyzer-Output
wird kompakter und zuverlaessiger
- orchestrator.py:
* Alter Translation-INSERT-Block entfernt (analysis.translations wird
nicht mehr genutzt)
* Nach Analyse + db.commit + cancel-check neuer Translator-Call:
SELECT WHERE language!=de AND (headline_de OR content_de fehlt),
translate_articles, normalize_german_umlauts, COALESCE-UPDATE
* Vor post_refresh_qc -> normalize_umlaut_articles greift auch frische
Uebersetzungen
* Failure-tolerant: Translator-Fehler bricht Refresh nicht ab
Backfill: migrations/migrate_translations_2026-05-03.py im Verwaltungs-Repo.
Dieser Commit ist enthalten in:
@@ -47,7 +47,6 @@ Antworte AUSSCHLIESSLICH als JSON-Objekt mit diesen Feldern:
|
||||
- "summary": Zusammenfassung auf {output_language} mit Quellenverweisen [1], [2] etc. im Text (Markdown-Überschriften ## erlaubt wenn sinnvoll, aber KEINE "## ZUSAMMENFASSUNG"/"## ÜBERBLICK"-Sektion)
|
||||
- "sources": Array von Quellenobjekten, je: {{"nr": 1, "name": "Quellenname", "url": "https://..."}}
|
||||
- "key_facts": Array von bestätigten Kernfakten (Strings, in Ausgabesprache)
|
||||
- "translations": Array von Objekten mit "article_id", "headline_de", "content_de" (nur für fremdsprachige Artikel)
|
||||
|
||||
Antworte NUR mit dem JSON-Objekt. Keine Einleitung, keine Erklärung."""
|
||||
|
||||
@@ -102,7 +101,6 @@ Antworte AUSSCHLIESSLICH als JSON-Objekt mit diesen Feldern:
|
||||
- "summary": Das strukturierte Briefing als Markdown-Text mit Quellenverweisen [1], [2] etc.
|
||||
- "sources": Array von Quellenobjekten, je: {{"nr": 1, "name": "Quellenname", "url": "https://..."}}
|
||||
- "key_facts": Array von gesicherten Kernfakten (Strings, in Ausgabesprache)
|
||||
- "translations": Array von Objekten mit "article_id", "headline_de", "content_de" (nur für fremdsprachige Artikel)
|
||||
|
||||
Antworte NUR mit dem JSON-Objekt. Keine Einleitung, keine Erklärung."""
|
||||
|
||||
@@ -149,7 +147,6 @@ Antworte AUSSCHLIESSLICH als JSON-Objekt mit diesen Feldern:
|
||||
- "summary": Aktualisierte Zusammenfassung mit Quellenverweisen [1], [2] etc.
|
||||
- "sources": Array mit NUR den NEUEN Quellen aus den neuen Meldungen, je: {{"nr": <fortlaufende ganze Zahl, KEINE Buchstaben-Suffixe>, "name": "Quellenname", "url": "https://..."}}. Alte Quellen werden automatisch gemerged.
|
||||
- "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)
|
||||
|
||||
Antworte NUR mit dem JSON-Objekt. Keine Einleitung, keine Erklärung."""
|
||||
|
||||
@@ -201,7 +198,6 @@ Antworte AUSSCHLIESSLICH als JSON-Objekt mit diesen Feldern:
|
||||
- "summary": Das aktualisierte Briefing als Markdown-Text mit Quellenverweisen
|
||||
- "sources": Array mit NUR den NEUEN Quellen aus den neuen Meldungen, je: {{"nr": <fortlaufende ganze Zahl, KEINE Buchstaben-Suffixe>, "name": "Quellenname", "url": "https://..."}}. Alte Quellen werden automatisch gemerged.
|
||||
- "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)
|
||||
|
||||
Antworte NUR mit dem JSON-Objekt. Keine Einleitung, keine Erklärung."""
|
||||
|
||||
@@ -796,5 +792,5 @@ class AnalyzerAgent:
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
|
||||
return {"summary": summary, "sources": sources, "key_facts": [], "translations": []}
|
||||
return {"summary": summary, "sources": sources, "key_facts": []}
|
||||
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren