fix(analyse): vollstaendigen Bericht nehmen, wenn das Modell sich selbst korrigiert
Der Recherchebericht der EU-Fassung enthielt seit zwei Laeufen nur noch den
Abschnitt ZUSAMMENFASSUNG, 1513 statt der ueblichen mehreren tausend Zeichen.
Die Abschnitte HINTERGRUND, AKTEURE, AKTUELLE LAGE, EINSCHAETZUNG und
QUELLENQUALITAET fehlten vollstaendig.
Ursache. Das Modell lieferte zuerst ein knappes JSON, bemerkte den Fehler
selbst ("Wait, I need to include the full briefing content in the summary
field. Let me redo this properly with all sections") und haengte danach eine
zweite, vollstaendige Fassung an. Unsere Auswertung nahm das erste Objekt und
verwarf alles danach. Der Bericht war also da, wir haben ihn weggeworfen.
Behoben. json_utils bekommt extract_json_objects und extract_json_arrays, die
alle vollstaendigen Bloecke einer Antwort liefern statt nur den ersten. Der
Analyzer waehlt daraus den Bericht mit dem laengsten summary, der Faktencheck
die Liste mit den meisten Fakten. Beide protokollieren, wenn mehrere Fassungen
auftauchen, damit der Fall sichtbar bleibt. Die bisherigen Einzelabfragen
extract_json_object und extract_json_array bleiben unveraendert, damit sich an
den uebrigen Aufrufstellen nichts aendert.
Gegenprobe an der echten Antwort aus Lauf 50. Vorher 1513 Zeichen mit einem
Abschnitt, jetzt 8189 Zeichen mit allen sechs.
Neu sind 16 Pruefungen, insgesamt laufen 96 ohne Netzzugriff und ohne Kosten.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -1112,10 +1112,23 @@ Antworte AUSSCHLIESSLICH mit dem Markdown-Text der Bullets, ohne Einleitung, ohn
|
||||
# Haeufigster Bruch (deutsche Zitate mit geradem Schlusszeichen); ohne
|
||||
# diesen Schritt rettete der Regex-Fallback unten nur ein Bruchstueck
|
||||
# und das Lagebild brach still mitten im Satz ab.
|
||||
from json_utils import extract_json_object as _forgiving_object
|
||||
repaired_obj = _forgiving_object(response)
|
||||
if isinstance(repaired_obj, dict) and "summary" in repaired_obj:
|
||||
return repaired_obj
|
||||
# Enthaelt die Antwort mehrere Objekte, weil das Modell sich selbst
|
||||
# korrigiert hat ("Let me redo this properly with all sections"), zaehlt
|
||||
# das ausfuehrlichste. Sonst landete nur die erste, kurze Fassung in der
|
||||
# Datenbank und der Bericht verlor fuenf von sechs Abschnitten.
|
||||
from json_utils import extract_json_objects as _forgiving_objects
|
||||
kandidaten = [o for o in _forgiving_objects(response)
|
||||
if isinstance(o, dict) and "summary" in o]
|
||||
if kandidaten:
|
||||
bester = max(kandidaten, key=lambda o: len(str(o.get("summary") or "")))
|
||||
if len(kandidaten) > 1:
|
||||
logger.warning(
|
||||
"Analyse enthielt %d Berichtsfassungen, nehme die ausfuehrlichste "
|
||||
"(%d statt %d Zeichen)",
|
||||
len(kandidaten), len(str(bester.get("summary") or "")),
|
||||
len(str(kandidaten[0].get("summary") or "")),
|
||||
)
|
||||
return bester
|
||||
|
||||
# Versuch 3: Abgeschnittenes JSON reparieren (haeufig bei langen Antworten)
|
||||
candidate = match.group() if match else cleaned
|
||||
|
||||
@@ -595,7 +595,7 @@ class FactCheckerAgent:
|
||||
plan_verification_searches, build_eu_prompt, _add_usage,
|
||||
)
|
||||
from config import EU_VERIFY_FOLLOWUP_QUERIES
|
||||
from json_utils import extract_json_array
|
||||
from json_utils import extract_json_arrays
|
||||
|
||||
gesamt = ClaudeUsage()
|
||||
kandidaten = offene[:MAX_FACTS_PER_VERIFY_GROUP]
|
||||
@@ -634,10 +634,13 @@ class FactCheckerAgent:
|
||||
logger.warning("EU-Nachhak-Runde fehlgeschlagen (%s), Fakten bleiben unveraendert", e)
|
||||
return facts, gesamt
|
||||
|
||||
aktualisierungen = extract_json_array(result or "")
|
||||
if not isinstance(aktualisierungen, list):
|
||||
# Korrigiert sich das Modell selbst und haengt eine zweite Fassung an,
|
||||
# zaehlt die inhaltsreichste, nicht die erste.
|
||||
fassungen = extract_json_arrays(result or "")
|
||||
if not fassungen:
|
||||
logger.warning("EU-Nachhak-Runde: Antwort nicht auswertbar, Fakten bleiben unveraendert")
|
||||
return facts, gesamt
|
||||
aktualisierungen = max(fassungen, key=len)
|
||||
|
||||
hochgestuft = 0
|
||||
for eintrag in aktualisierungen:
|
||||
@@ -1060,10 +1063,19 @@ class FactCheckerAgent:
|
||||
# Nicht maskierte Anfuehrungszeichen im Text reparieren (deutsche Zitate
|
||||
# in claim/evidence). Ohne diesen Schritt lieferte der Faktencheck bei
|
||||
# einem einzigen Stoerzeichen still eine leere Liste.
|
||||
from json_utils import extract_json_array as _forgiving_array
|
||||
repaired = _forgiving_array(response)
|
||||
if isinstance(repaired, list):
|
||||
return self._validate_facts(repaired, articles=articles)
|
||||
# Liefert das Modell mehrere Fassungen, weil es sich selbst korrigiert
|
||||
# hat, zaehlt die mit den meisten Fakten.
|
||||
from json_utils import extract_json_arrays as _forgiving_arrays
|
||||
fassungen = _forgiving_arrays(response)
|
||||
if fassungen:
|
||||
beste = max(fassungen, key=len)
|
||||
if len(fassungen) > 1:
|
||||
logger.warning(
|
||||
"Faktencheck-Antwort enthielt %d Fassungen, nehme die mit den "
|
||||
"meisten Fakten (%d statt %d)",
|
||||
len(fassungen), len(beste), len(fassungen[0]),
|
||||
)
|
||||
return self._validate_facts(beste, articles=articles)
|
||||
|
||||
logger.warning(
|
||||
"Konnte Faktencheck-Antwort nicht als JSON parsen (Laenge: %d, Anfang: %r)",
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren