fix(eu): Belastungsprobe folgt auch auf eine erfolgreiche Nachbelegung

Der erste Lauf mit den Gegenproben (Lage 64) zeigte, dass der Faktencheck
selbst jetzt ehrlich arbeitet. Der erste Durchgang liess 3 von 10 Behauptungen
offen, also 30 Prozent und damit genau das Niveau des Anthropic-Wegs. Vorher
waren es acht Laeufe hintereinander null.

Danach hob die Nachhak-Runde alle drei wieder auf bestaetigt, und der Lauf
endete erneut ohne eine einzige Unsicherheit.

Ursache war ein Denkfehler im Aufbau. Die zweite Runde war ein Entweder-oder.
Entweder wurde nachbelegt oder es lief die Belastungsprobe. Sobald nachbelegt
wurde, stand am Ende wieder alles auf bestaetigt und niemand prueft das nach.

Jetzt laufen beide Schritte nacheinander. Erst wird nachbelegt, danach greift
die Belastungsprobe, wenn kaum noch etwas offen ist. Sie prueft damit genau die
frisch vergebenen Bestaetigungen. Damit sie wirklich neu sucht, meldet die
Nachhak-Runde ihre Anfragen zurueck und die Belastungsprobe meidet auch diese.

Der Weg ueber die Anthropic-CLI bleibt unveraendert. 254 Pruefungen laufen ohne
Netzzugriff und ohne Kosten.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
claude-dev
2026-08-02 11:27:17 +00:00
Ursprung d948e3a7f4
Commit b00076d320
3 geänderte Dateien mit 82 neuen und 31 gelöschten Zeilen

Datei anzeigen

@@ -769,30 +769,38 @@ class FactCheckerAgent:
# Die zweite Runde ist eine Verbesserung, keine Voraussetzung. Faellt sie
# aus, bleibt das Ergebnis des ersten Durchgangs erhalten, statt dass der
# ganze Faktencheck verloren geht.
gestellte_anfragen = list(suche.queries)
try:
# Erster Schritt: offene Punkte nachbelegen, sofern welche da sind.
offene = [f for f in facts if f.get("status") in OFFENE_STATUS]
if len(offene) >= EU_VERIFY_FOLLOWUP_MIN_OPEN:
logger.info(
"EU-Faktencheck: %d von %d Behauptungen offen, starte Nachhak-Runde",
len(offene), len(facts))
facts, zweite_usage = await self._eu_nachhaken(
facts, nachhak_usage, nachhak_anfragen = await self._eu_nachhaken(
facts=facts, offene=offene, title=title,
output_language=output_language, incident_type=incident_type,
avoid_queries=suche.queries, followup_queries=anzahl_nachhak,
avoid_queries=gestellte_anfragen, followup_queries=anzahl_nachhak,
)
else:
bestaetigt = [f for f in facts if f.get("status") in BESTAETIGTE_STATUS]
if not bestaetigt:
return facts, gesamt
_add_usage(gesamt, nachhak_usage)
gestellte_anfragen += nachhak_anfragen
# Zweiter Schritt: bleibt danach kaum etwas offen, wird das
# geprueft. Ohne diesen Schritt hob die Nachhak-Runde am 02.08.2026
# alle drei offenen Punkte wieder hoch und der Lauf endete erneut
# ohne eine einzige Unsicherheit.
offene = [f for f in facts if f.get("status") in OFFENE_STATUS]
bestaetigt = [f for f in facts if f.get("status") in BESTAETIGTE_STATUS]
if bestaetigt and len(offene) < EU_VERIFY_FOLLOWUP_MIN_OPEN:
logger.info(
"EU-Faktencheck: %d von %d Behauptungen bestaetigt, starte Belastungsprobe",
len(bestaetigt), len(facts))
facts, zweite_usage = await self._eu_belastungsprobe(
"EU-Faktencheck: nur %d von %d Behauptungen offen, starte Belastungsprobe",
len(offene), len(facts))
facts, probe_usage = await self._eu_belastungsprobe(
facts=facts, bestaetigt=bestaetigt, title=title,
output_language=output_language, incident_type=incident_type,
avoid_queries=suche.queries, queries=anzahl_nachhak,
avoid_queries=gestellte_anfragen, queries=anzahl_nachhak,
)
_add_usage(gesamt, zweite_usage)
_add_usage(gesamt, probe_usage)
except asyncio.CancelledError:
raise
except Exception as e:
@@ -912,9 +920,14 @@ class FactCheckerAgent:
incident_type: str,
avoid_queries: list[str],
followup_queries: int | None = None,
) -> tuple[list[dict], ClaudeUsage]:
) -> tuple[list[dict], ClaudeUsage, list[str]]:
"""Sucht gezielt Belege fuer die offenen Behauptungen und bewertet nur
diese erneut. Gibt die zusammengefuehrte Faktenliste zurueck."""
diese erneut.
Gibt die zusammengefuehrte Faktenliste, den Verbrauch und die gestellten
Anfragen zurueck. Letztere braucht die Belastungsprobe, damit sie nicht
dieselben Anfragen noch einmal stellt.
"""
from agents.claude_client import call_claude
from agents.eu_researcher import (
plan_verification_searches, build_eu_prompt, _add_usage,
@@ -926,7 +939,7 @@ class FactCheckerAgent:
kandidaten = offene[:MAX_FACTS_PER_VERIFY_GROUP]
claims = [f.get("claim", "") for f in kandidaten if f.get("claim")]
if not claims:
return facts, gesamt
return facts, gesamt, []
suche = await plan_verification_searches(
title=title, search_items=claims, output_language=output_language,
@@ -937,7 +950,7 @@ class FactCheckerAgent:
_add_usage(gesamt, suche.usage)
if not block:
logger.info("EU-Nachhak-Runde: keine zusaetzlichen Belege gefunden, Fakten bleiben unveraendert")
return facts, gesamt
return facts, gesamt, suche.queries
status_werte = ("established|unverified|disputed|false|developing"
if incident_type == "research"
@@ -954,17 +967,17 @@ class FactCheckerAgent:
_add_usage(gesamt, usage)
except TimeoutError:
logger.warning("EU-Nachhak-Runde: Timeout, Fakten bleiben unveraendert")
return facts, gesamt
return facts, gesamt, suche.queries
except Exception as e:
logger.warning("EU-Nachhak-Runde fehlgeschlagen (%s), Fakten bleiben unveraendert", e)
return facts, gesamt
return facts, gesamt, suche.queries
# 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
return facts, gesamt, suche.queries
aktualisierungen = max(fassungen, key=len)
hochgestuft = 0
@@ -1032,7 +1045,7 @@ class FactCheckerAgent:
"EU-Nachhak-Runde abgeschlossen: %d von %d offenen Behauptungen belegt",
hochgestuft, len(kandidaten),
)
return facts, gesamt
return facts, gesamt, suche.queries
async def check(self, title: str, articles: list[dict], incident_type: str = "adhoc", output_language: str = "Deutsch") -> tuple[list[dict], ClaudeUsage | None]:
"""Führt vollständigen Faktencheck durch (erster Refresh)."""