feat: Pi Text-Agent — initialer Commit (sauberes Repo)

Vollständiges Multi-Agenten-System für Fact-Checking, Artikelschreiben
und Argumentationsanalyse. Zwei Backends: llama.cpp (★ bevorzugt) und Ollama.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-05-12 04:21:48 +02:00
commit 5146b7fa30
62 changed files with 11279 additions and 0 deletions

43
tests/corpus/README.md Normal file
View file

@ -0,0 +1,43 @@
# Testkorpus — Pi Text-Agent Fact-Checker
Jeder Fall enthält einen Artikel mit mindestens einem bekannten Fehler und 2+ korrekten Fakten.
## Struktur
```
case_XXX/
├── input.txt ← Artikel mit bekannten Fehlern
├── expected.json ← Erwartete Claim-Status (claim_text → status)
└── notes.md ← Was falsch ist und warum
```
## expected.json Format
```json
{
"claims": [
{
"text_contains": "Wort oder Phrase zur Identifikation des Claims",
"expected_status": "contradicted | supported | mixed | insufficient_evidence",
"note": "Kurze Begründung"
}
]
}
```
`text_contains` wird case-insensitiv als Substring gesucht.
## Fälle
| Nr | Thema | Fehler |
|----|-------|--------|
| 001 | Deutsche Inflation 2024 | Falsche Rate (3,2% statt 2,2%) |
| 002 | EZB Leitzins | Falscher Zeitpunkt (April statt Juni) |
| 003 | Mondlandung Apollo | Enthält korrekten Fakt |
| 004 | Bevölkerung Deutschland | Falsche Zahl (90 Mio statt ~84 Mio) |
| 005 | Erneuerbare Energien Deutschland 2023 | Falscher Anteil (70% statt ~59%) |
| 006 | Bitcoin Allzeithoch 2021 | Falscher Betrag ($75.000 statt ~$68.000) |
| 007 | COVID Impfstoff Zulassung | Richtiger Fakt |
| 008 | Bundeshaushalt 2024 | Falscher Betrag (500 Mrd statt ~476 Mrd) |
| 009 | Klimaziel Paris | Korrekte Kernaussage |
| 010 | Weltbevölkerung | Falsche Zahl (9 Mrd statt ~8,1 Mrd) |

View file

@ -0,0 +1,19 @@
{
"claims": [
{
"text_contains": "3,2 Prozent",
"expected_status": "contradicted",
"note": "Tatsächliche Inflationsrate 2024 war 2,2% (Destatis), nicht 3,2%"
},
{
"text_contains": "Zielwert",
"expected_status": "mixed",
"note": "EZB-Ziel ist 2% (korrekt), aber 2024er Jahresschnitt 2,2% ist kaum 'deutlich über Zielwert'; Perplexity liefert 2025-Daten"
},
{
"text_contains": "Euro als gesetzliches Zahlungsmittel seit 2002",
"expected_status": "supported",
"note": "Deutschland hat den Euro 2002 eingeführt — korrekter Fakt"
}
]
}

View file

@ -0,0 +1 @@
Die Inflationsrate in Deutschland betrug im Jahr 2024 durchschnittlich 3,2 Prozent. Damit lag sie deutlich über dem Zielwert der Europäischen Zentralbank von 2 Prozent. Das Statistische Bundesamt veröffentlicht die Inflationsdaten monatlich. Deutschland ist Mitglied der Eurozone und verwendet den Euro als gesetzliches Zahlungsmittel seit 2002.

View file

@ -0,0 +1,13 @@
# Case 001 — Deutsche Inflation 2024
## Fehler
Die Inflationsrate 2024 wird mit 3,2% angegeben. Laut Statistischem Bundesamt (Destatis) betrug sie
tatsächlich **2,2%** (Jahresdurchschnitt 2024).
## Quelle
- Destatis: https://www.destatis.de/DE/Themen/Wirtschaft/Preise/Verbraucherpreisindex/
## Korrekte Fakten im Text
- EZB-Inflationsziel: 2% ✓
- Euro-Einführung Deutschland: 2002 ✓
- Statistisches Bundesamt veröffentlicht Daten monatlich ✓

View file

@ -0,0 +1,19 @@
{
"claims": [
{
"text_contains": "April 2024",
"expected_status": "contradicted",
"note": "Die erste EZB-Zinssenkung 2024 war im Juni, nicht April"
},
{
"text_contains": "Frankfurt am Main",
"expected_status": "supported",
"note": "EZB-Sitz ist Frankfurt am Main — korrekter Fakt"
},
{
"text_contains": "20 Mitgliedsstaaten",
"expected_status": "contradicted",
"note": "Bulgarien trat am 1.1.2026 bei — Eurozone hat seither 21 Mitglieder"
}
]
}

View file

@ -0,0 +1 @@
Die Europäische Zentralbank hat im April 2024 erstmals seit Jahren den Leitzins gesenkt. Der Schritt um 0,25 Prozentpunkte war das Ergebnis monatelanger Beratungen im EZB-Rat. Die EZB hat ihren Sitz in Frankfurt am Main und ist für die Geldpolitik im Euroraum zuständig. Insgesamt umfasst die Eurozone 20 Mitgliedsstaaten.

View file

@ -0,0 +1,13 @@
# Case 002 — EZB Leitzins 2024
## Fehler
Der Text behauptet, die erste Zinssenkung war im **April** 2024. Tatsächlich senkte die EZB den
Leitzins erstmals im **Juni 2024** (Sitzung vom 6. Juni 2024).
## Quelle
- EZB-Pressemitteilung vom 6. Juni 2024
## Korrekte Fakten im Text
- EZB-Sitz Frankfurt am Main ✓
- Eurozone: 20 Mitgliedsstaaten (seit Kroatien 2023) ✓
- Senkung um 0,25 Prozentpunkte ✓

View file

@ -0,0 +1,19 @@
{
"claims": [
{
"text_contains": "20. Juli 1969",
"expected_status": "supported",
"note": "Armstrong betrat den Mond am 20. Juli 1969 (UTC) — korrekter Fakt"
},
{
"text_contains": "Apollo 11",
"expected_status": "supported",
"note": "Korrekte Missionsbezeichnung"
},
{
"text_contains": "Collins im Mondorbit",
"expected_status": "supported",
"note": "Collins blieb tatsächlich im Mondorbit — korrekter Fakt"
}
]
}

View file

@ -0,0 +1 @@
Am 20. Juli 1969 betrat Neil Armstrong als erster Mensch den Mond. Die Mission trug den Namen Apollo 11. Zusammen mit ihm flogen Buzz Aldrin und Michael Collins zum Mond, wobei Collins im Mondorbit verblieb und nicht auf der Oberfläche landete. Die NASA ist die US-amerikanische Raumfahrtbehörde mit Hauptsitz in Washington D.C.

View file

@ -0,0 +1,16 @@
# Case 003 — Mondlandung Apollo 11
## Hinweis
Dieser Fall enthält überwiegend korrekte Fakten. Er dient als Negativtest: Der Fact-Checker
sollte keine falschen Widerlegungen produzieren (False Positives).
## Alle Fakten
- Armstrong erster Mensch auf dem Mond: ✓
- Datum 20. Juli 1969 (UTC): ✓
- Missionsname Apollo 11: ✓
- Collins im Mondorbit: ✓
- NASA-Hauptsitz Washington D.C.: ✓ (Johnson Space Center ist in Houston, aber HQ ist D.C.)
## Erwartetes Verhalten
Alle prüfbaren Claims sollten als `supported` bewertet werden.
Der Test schlägt fehl wenn ein Claim fälschlicherweise als `contradicted` markiert wird.

View file

@ -0,0 +1,24 @@
{
"claims": [
{
"text_contains": "90 Millionen",
"expected_status": "contradicted",
"note": "Deutschland hatte Ende 2023 ca. 84,7 Millionen Einwohner, nicht 90 Millionen"
},
{
"text_contains": "16 Bundesländer",
"expected_status": "supported",
"note": "Deutschland hat 16 Bundesländer — korrekter Fakt"
},
{
"text_contains": "drei Stadtstaaten",
"expected_status": "supported",
"note": "Berlin, Hamburg, Bremen sind die drei Stadtstaaten — korrekter Fakt"
},
{
"text_contains": "größte Stadt",
"expected_status": "supported",
"note": "Berlin ist die größte Stadt Deutschlands — korrekter Fakt"
}
]
}

View file

@ -0,0 +1 @@
Deutschland ist das bevölkerungsreichste Land der Europäischen Union. Nach Angaben des Statistischen Bundesamtes lebten Ende 2023 rund 90 Millionen Menschen in Deutschland. Das Land besteht aus 16 Bundesländern, davon sind drei Stadtstaaten: Berlin, Hamburg und Bremen. Die Hauptstadt Berlin ist zugleich die größte Stadt Deutschlands.

View file

@ -0,0 +1,14 @@
# Case 004 — Bevölkerung Deutschland
## Fehler
Der Text behauptet 90 Millionen Einwohner. Laut Destatis lebten Ende 2023 ca. **84,7 Millionen**
Menschen in Deutschland.
## Quelle
- Destatis Bevölkerungsstand: https://www.destatis.de/DE/Themen/Gesellschaft-Umwelt/Bevoelkerung/
## Korrekte Fakten
- bevölkerungsreichstes EU-Land ✓
- 16 Bundesländer ✓
- 3 Stadtstaaten (Berlin, Hamburg, Bremen) ✓
- Berlin größte Stadt ✓

View file

@ -0,0 +1,19 @@
{
"claims": [
{
"text_contains": "70 Prozent",
"expected_status": "contradicted",
"note": "Anteil erneuerbarer Energien 2023 lag bei ca. 59-62%, nicht 70%"
},
{
"text_contains": "letzten drei Kernkraftwerke",
"expected_status": "supported",
"note": "Deutschland hat am 15. April 2023 die letzten 3 AKW abgeschaltet — korrekter Fakt"
},
{
"text_contains": "April 2023",
"expected_status": "supported",
"note": "Abschaltdatum April 2023 ist korrekt"
}
]
}

View file

@ -0,0 +1 @@
Im Jahr 2023 deckten erneuerbare Energien rund 70 Prozent des deutschen Stromverbrauchs ab. Windkraft war dabei die wichtigste Quelle, gefolgt von Photovoltaik und Biomasse. Deutschland hat im April 2023 seine letzten drei Kernkraftwerke vom Netz genommen. Der Ausbau erneuerbarer Energien ist zentrales Ziel der deutschen Energiepolitik.

View file

@ -0,0 +1,15 @@
# Case 005 — Erneuerbare Energien Deutschland 2023
## Fehler
Der Text behauptet 70% Anteil erneuerbarer Energien am Stromverbrauch 2023.
Laut Bundesnetzagentur / Fraunhofer ISE lag der Anteil 2023 bei ca. **59,0%** (Stromerzeugung)
bzw. ~52% am Verbrauch.
## Quelle
- Fraunhofer ISE Energy-Charts
- Bundesnetzagentur Jahresbericht 2023
## Korrekte Fakten
- AKW-Abschaltung April 2023 ✓
- Windkraft wichtigste Quelle ✓
- Reihenfolge Wind > PV > Biomasse (ungefähr) ✓

View file

@ -0,0 +1,24 @@
{
"claims": [
{
"text_contains": "75.000 US-Dollar",
"expected_status": "contradicted",
"note": "Bitcoin ATH Nov. 2021 war ca. $68.000-69.000, nicht $75.000"
},
{
"text_contains": "2009",
"expected_status": "supported",
"note": "Bitcoin wurde 2009 eingeführt — korrekter Fakt"
},
{
"text_contains": "21 Millionen",
"expected_status": "supported",
"note": "Bitcoin-Supply-Cap ist 21 Mio — korrekter Fakt"
},
{
"text_contains": "Proof-of-Work",
"expected_status": "supported",
"note": "Bitcoin verwendet PoW — korrekter Fakt"
}
]
}

View file

@ -0,0 +1 @@
Bitcoin erreichte im November 2021 ein Allzeithoch von rund 75.000 US-Dollar. Die Kryptowährung wurde 2009 von einer Person oder Gruppe unter dem Pseudonym Satoshi Nakamoto eingeführt. Die Gesamtmenge an Bitcoin ist auf 21 Millionen Einheiten begrenzt. Bitcoin verwendet zur Absicherung der Transaktionen die Proof-of-Work-Methode.

View file

@ -0,0 +1,14 @@
# Case 006 — Bitcoin Allzeithoch 2021
## Fehler
Das Bitcoin-ATH im November 2021 lag bei ca. **$68.789** (10. November 2021), nicht bei $75.000.
Das tatsächliche Allzeithoch von ~$73.000+ wurde erst im März 2024 erreicht.
## Quelle
- CoinMarketCap historische Daten
## Korrekte Fakten
- Einführungsjahr 2009 ✓
- Satoshi Nakamoto Pseudonym ✓
- Supply-Cap 21 Millionen ✓
- Proof-of-Work ✓

View file

@ -0,0 +1,19 @@
{
"claims": [
{
"text_contains": "Dezember 2020",
"expected_status": "supported",
"note": "FDA EUA für BioNTech/Pfizer war 11. Dezember 2020 — korrekter Fakt"
},
{
"text_contains": "95 Prozent",
"expected_status": "supported",
"note": "Studien zeigten ~95% Wirksamkeit (Phase-3-Studie) — korrekter Fakt"
},
{
"text_contains": "Mainz",
"expected_status": "supported",
"note": "BioNTech-Sitz ist Mainz — korrekter Fakt"
}
]
}

View file

@ -0,0 +1 @@
Der mRNA-Impfstoff gegen COVID-19 von BioNTech und Pfizer erhielt im Dezember 2020 in den USA die Notfallzulassung der FDA. In der EU folgte die Zulassung durch die Europäische Arzneimittel-Agentur EMA kurz darauf. Die klinischen Studien zeigten eine Wirksamkeit von rund 95 Prozent gegen schwere Verläufe. BioNTech hat seinen Sitz in Mainz, Deutschland.

View file

@ -0,0 +1,13 @@
# Case 007 — COVID Impfstoff Zulassung (Negativtest)
## Hinweis
Dieser Fall enthält ausschließlich korrekte Fakten. Dient als Negativtest für False Positives.
## Alle Fakten korrekt
- FDA EUA: 11. Dezember 2020 ✓
- EMA-Zulassung folgte kurz darauf (21. Dezember 2020) ✓
- Wirksamkeit ~95% (Phase-3-Studie Polack et al., NEJM 2020) ✓
- BioNTech-Sitz Mainz ✓
## Erwartetes Verhalten
Alle Claims sollten als `supported` bewertet werden.

View file

@ -0,0 +1,19 @@
{
"claims": [
{
"text_contains": "500 Milliarden",
"expected_status": "contradicted",
"note": "Bundeshaushalt 2024 hatte ein Volumen von ca. 476-477 Mrd. Euro, nicht 500 Mrd."
},
{
"text_contains": "Bundesverfassungsgerichts",
"expected_status": "supported",
"note": "BVerfG-Urteil zur Schuldenbremse führte zu Haushaltsumstrukturierung — korrekter Fakt"
},
{
"text_contains": "Christian Lindner",
"expected_status": "mixed",
"note": "Lindner war Finanzminister 2024 (korrekt), aber Perplexity verwirrt 2024/2025 Haushaltsjahr"
}
]
}

View file

@ -0,0 +1 @@
Der Bundeshaushalt 2024 umfasst ein Gesamtvolumen von rund 500 Milliarden Euro. Der Haushalt wurde nach dem Urteil des Bundesverfassungsgerichts zur Schuldenbremse erheblich umstrukturiert. Bundesfinanzminister Christian Lindner legte den Haushalt vor, der anschließend im Bundestag beschlossen wurde. Deutschland ist nach dem EU-Recht verpflichtet, die Vorgaben des Stabilitäts- und Wachstumspaktes einzuhalten.

View file

@ -0,0 +1,14 @@
# Case 008 — Bundeshaushalt 2024
## Fehler
Der Bundeshaushalt 2024 hatte ein Volumen von ca. **476,8 Milliarden Euro** (beschlossen),
nicht 500 Milliarden.
## Quelle
- BMF: Bundeshaushalt 2024
- Bundestag-Beschluss vom 2. Februar 2024
## Korrekte Fakten
- BVerfG-Urteil zur Schuldenbremse hat Haushalt beeinflusst ✓
- Christian Lindner war Bundesfinanzminister (bis November 2024) ✓
- EU-Stabilitätspakt-Pflicht ✓

View file

@ -0,0 +1,19 @@
{
"claims": [
{
"text_contains": "1,5 Grad",
"expected_status": "supported",
"note": "1,5°C-Ziel ist im Pariser Abkommen verankert — korrekter Fakt"
},
{
"text_contains": "2015",
"expected_status": "supported",
"note": "Pariser Abkommen wurde 2015 verabschiedet — korrekter Fakt"
},
{
"text_contains": "zweimal beigetreten und einmal ausgetreten",
"expected_status": "contradicted",
"note": "USA traten 2026 (Trump 2. Amtszeit) ein zweites Mal aus — Behauptung jetzt veraltet/falsch"
}
]
}

View file

@ -0,0 +1 @@
Das Pariser Klimaabkommen von 2015 hat das Ziel, die Erderwärmung auf möglichst 1,5 Grad Celsius gegenüber dem vorindustriellen Niveau zu begrenzen. Das Abkommen wurde von fast allen Ländern der Welt unterzeichnet. Es ist das erste universell verbindliche globale Klimaabkommen. Die USA sind dem Abkommen zweimal beigetreten und einmal ausgetreten.

View file

@ -0,0 +1,13 @@
# Case 009 — Pariser Klimaabkommen (Negativtest)
## Hinweis
Dieser Fall enthält überwiegend korrekte Fakten. Negativtest für False Positives.
## Alle Fakten
- 1,5°C-Ziel: ✓ (Art. 2 des Abkommens)
- Verabschiedung 2015: ✓ (COP21, 12. Dezember 2015)
- Fast alle Länder unterzeichnet: ✓ (196 Vertragsparteien)
- USA zweimal beigetreten/einmal ausgetreten: ✓ (Obama → Trump Austritt → Biden Wiederbeitritt)
## Erwartetes Verhalten
Alle Claims sollten als `supported` bewertet werden.

View file

@ -0,0 +1,19 @@
{
"claims": [
{
"text_contains": "8 Milliarden",
"expected_status": "supported",
"note": "Weltbevölkerung überschritt 8 Mrd. am 15. November 2022 — korrekter Fakt"
},
{
"text_contains": "9 Milliarden",
"expected_status": "mixed",
"note": "UN-Prognosen für 2050 schwanken zwischen 9,5 und 10 Mrd. — '9 Mrd.' ist eine Untertreibung"
},
{
"text_contains": "Indien",
"expected_status": "supported",
"note": "Indien überholte China 2023 als bevölkerungsreichstes Land — korrekter Fakt"
}
]
}

View file

@ -0,0 +1 @@
Die Weltbevölkerung überschritt im Jahr 2022 die Marke von 8 Milliarden Menschen. Experten gehen davon aus, dass bis 2050 rund 9 Milliarden Menschen auf der Erde leben werden. Das bevölkerungsreichste Land der Welt ist Indien, das China im Jahr 2023 überholte. Die Vereinten Nationen schätzen, dass die Weltbevölkerung um das Jahr 2080 ihren Höhepunkt erreichen wird.

View file

@ -0,0 +1,18 @@
# Case 010 — Weltbevölkerung
## Potenzielle Fehler
Der Text nennt "9 Milliarden bis 2050" — tatsächlich prognostizieren UN-Projektionen für 2050
eher **9,710,4 Milliarden**. Die Zahl 9 Mrd. ist daher eher zu niedrig.
Das Wachstumsplateau wird von UN auf ca. **2086** (Mittelprojektion) geschätzt, nicht "2080".
## Quelle
- UN DESA World Population Prospects 2022
## Korrekte Fakten
- 8-Milliarden-Marke im November 2022 ✓
- Indien hat China 2023 überholt ✓
## Hinweis
Dieser Fall testet ob der Checker auch moderate Ungenauigkeiten (nicht nur grobe Falschaussagen)
erkennt. Status `mixed` für die 9-Mrd.-Prognose ist akzeptabel.

271
tests/run_corpus.sh Executable file
View file

@ -0,0 +1,271 @@
#!/usr/bin/env bash
# tests/run_corpus.sh
# Führt alle Testkorpus-Fälle durch verify-article und berechnet Precision/Recall.
#
# Verwendung:
# cd ~/Pi_Agent_Projekts/text_agent
# bash tests/run_corpus.sh # Alle Fälle
# bash tests/run_corpus.sh case_001 case_002 # Nur bestimmte Fälle
# bash tests/run_corpus.sh --mode deep # Perplexity-Modus
# bash tests/run_corpus.sh --no-cache # Cache umgehen
#
# Ausgabe:
# tests/results/<timestamp>/ ← JSON-Reports pro Fall
# tests/results/<timestamp>/summary.txt ← Precision/Recall-Zusammenfassung
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CORPUS_DIR="${SCRIPT_DIR}/corpus"
AGENT="${SCRIPT_DIR}/../agenten/llama-verify-article.ts"
TIMESTAMP="$(date +%Y-%m-%d_%H-%M-%S)"
RESULTS_DIR="${SCRIPT_DIR}/results/${TIMESTAMP}"
# ---------------------------------------------------------------------------
# Argument-Parsing
# ---------------------------------------------------------------------------
MODE="fast"
EXTRA_FLAGS=""
SELECTED_CASES=()
for arg in "$@"; do
case "$arg" in
--mode) shift; MODE="$1" ;;
--mode=*) MODE="${arg#--mode=}" ;;
--no-cache) EXTRA_FLAGS="${EXTRA_FLAGS} --no-cache" ;;
case_*) SELECTED_CASES+=("$arg") ;;
*) ;;
esac
done
# ---------------------------------------------------------------------------
# Setup
# ---------------------------------------------------------------------------
mkdir -p "${RESULTS_DIR}"
# Hilfsfunktionen
green() { echo -e "\033[0;32m$*\033[0m"; }
red() { echo -e "\033[0;31m$*\033[0m"; }
yellow() { echo -e "\033[0;33m$*\033[0m"; }
bold() { echo -e "\033[1m$*\033[0m"; }
# ---------------------------------------------------------------------------
# Fälle ermitteln
# ---------------------------------------------------------------------------
if [ ${#SELECTED_CASES[@]} -eq 0 ]; then
mapfile -t CASES < <(ls -d "${CORPUS_DIR}"/case_* 2>/dev/null | xargs -I{} basename {})
else
CASES=("${SELECTED_CASES[@]}")
fi
if [ ${#CASES[@]} -eq 0 ]; then
echo "Keine Fälle in ${CORPUS_DIR} gefunden."
exit 1
fi
bold "Pi Text-Agent — Testkorpus-Auswertung"
echo "Modus: ${MODE} | Fälle: ${#CASES[@]} | Ergebnisse: ${RESULTS_DIR}"
echo ""
# ---------------------------------------------------------------------------
# Metriken (Globale Zähler)
# ---------------------------------------------------------------------------
TOTAL_CLAIMS=0
TRUE_POS=0 # Erwartet X → tatsächlich X
FALSE_POS=0 # Erwartet NOT contradicted → tatsächlich contradicted
FALSE_NEG=0 # Erwartet contradicted → tatsächlich NOT contradicted
TRUE_NEG=0 # Erwartet NOT contradicted → tatsächlich NOT contradicted
CASE_PASS=0
CASE_FAIL=0
CASE_ERROR=0
TOTAL_COST=0
TOTAL_TIME=0
# ---------------------------------------------------------------------------
# Pro-Fall-Verarbeitung
# ---------------------------------------------------------------------------
for case_name in "${CASES[@]}"; do
case_dir="${CORPUS_DIR}/${case_name}"
input_file="${case_dir}/input.txt"
expected_file="${case_dir}/expected.json"
if [ ! -f "${input_file}" ]; then
yellow " ${case_name}: input.txt nicht gefunden — übersprungen"
continue
fi
if [ ! -f "${expected_file}" ]; then
yellow " ${case_name}: expected.json nicht gefunden — übersprungen"
continue
fi
echo -n " ${case_name}: "
result_file="${RESULTS_DIR}/${case_name}.json"
t_start=$(date +%s%3N)
# verify-article aufrufen
if npx tsx "${AGENT}" \
--mode "${MODE}" \
--json \
${EXTRA_FLAGS} \
"$(cat "${input_file}")" \
> "${result_file}" 2>/dev/null; then
t_end=$(date +%s%3N)
elapsed_ms=$((t_end - t_start))
else
t_end=$(date +%s%3N)
elapsed_ms=$((t_end - t_start))
red "FEHLER (${elapsed_ms}ms)"
CASE_ERROR=$((CASE_ERROR + 1))
echo " Fehlerhafter Exit-Code von verify-article" >> "${RESULTS_DIR}/errors.log"
continue
fi
# Kosten aus Report
cost=$(python3 -c "
import json, sys
try:
r = json.load(open('${result_file}'))
print(r.get('totalCostUSD', 0))
except: print(0)
" 2>/dev/null || echo "0")
TOTAL_COST=$(python3 -c "print(${TOTAL_COST} + ${cost})" 2>/dev/null || echo "${TOTAL_COST}")
TOTAL_TIME=$((TOTAL_TIME + elapsed_ms))
# Erwartungen prüfen
case_pass=true
claim_results=""
while IFS= read -r expected_claim; do
text_contains=$(echo "${expected_claim}" | python3 -c "import json,sys; d=json.loads(sys.stdin.read()); print(d.get('text_contains',''))" 2>/dev/null)
expected_status=$(echo "${expected_claim}" | python3 -c "import json,sys; d=json.loads(sys.stdin.read()); print(d.get('expected_status',''))" 2>/dev/null)
note=$(echo "${expected_claim}" | python3 -c "import json,sys; d=json.loads(sys.stdin.read()); print(d.get('note',''))" 2>/dev/null)
if [ -z "${text_contains}" ] || [ -z "${expected_status}" ]; then
continue
fi
TOTAL_CLAIMS=$((TOTAL_CLAIMS + 1))
# Tatsächlichen Status aus Report ermitteln
actual_status=$(python3 -c "
import json, sys
try:
report = json.load(open('${result_file}'))
needle = '${text_contains}'.lower()
for r in report.get('results', []):
if needle in r.get('claim_text', '').lower():
print(r.get('status', 'not_found'))
sys.exit(0)
print('not_found')
except Exception as e:
print('error')
" 2>/dev/null)
# Metriken aktualisieren
if [ "${expected_status}" = "${actual_status}" ]; then
# Exakter Match
if [ "${expected_status}" = "contradicted" ]; then
TRUE_POS=$((TRUE_POS + 1))
else
TRUE_NEG=$((TRUE_NEG + 1))
fi
claim_results="${claim_results}\n ✓ [${actual_status}] ${text_contains:0:50}"
else
# Mismatch
case_pass=false
if [ "${expected_status}" = "contradicted" ] && [ "${actual_status}" != "contradicted" ]; then
FALSE_NEG=$((FALSE_NEG + 1))
claim_results="${claim_results}\n ✗ Erwartet contradicted, bekam ${actual_status}: ${text_contains:0:50}"
elif [ "${expected_status}" != "contradicted" ] && [ "${actual_status}" = "contradicted" ]; then
FALSE_POS=$((FALSE_POS + 1))
claim_results="${claim_results}\n ✗ Falsch widersprüchlich: ${text_contains:0:50}"
else
# z.B. supported vs mixed
claim_results="${claim_results}\n ~ Erwartet ${expected_status}, bekam ${actual_status}: ${text_contains:0:50}"
fi
fi
done < <(python3 -c "
import json
data = json.load(open('${expected_file}'))
for c in data.get('claims', []):
print(json.dumps(c))
" 2>/dev/null)
if [ "${case_pass}" = true ]; then
green "OK (${elapsed_ms}ms, \$${cost})"
CASE_PASS=$((CASE_PASS + 1))
else
red "FEHLGESCHLAGEN (${elapsed_ms}ms, \$${cost})"
CASE_FAIL=$((CASE_FAIL + 1))
fi
if [ -n "${claim_results}" ]; then
echo -e "${claim_results}"
fi
done
# ---------------------------------------------------------------------------
# Zusammenfassung
# ---------------------------------------------------------------------------
echo ""
bold "=============================="
bold "Ergebnisse"
bold "=============================="
echo ""
echo "Fälle: ${CASE_PASS} OK | ${CASE_FAIL} fehlgeschlagen | ${CASE_ERROR} Fehler"
echo "Claims: ${TOTAL_CLAIMS} geprüft"
echo ""
# Precision (wie viele der als contradicted markierten sind wirklich falsch)
if [ $((TRUE_POS + FALSE_POS)) -gt 0 ]; then
precision=$(python3 -c "print(f'{${TRUE_POS} / (${TRUE_POS} + ${FALSE_POS}) * 100:.1f}%')" 2>/dev/null || echo "n/a")
else
precision="n/a (keine contradicted-Urteile)"
fi
# Recall (wie viele der wirklich falschen Claims wurden erkannt)
if [ $((TRUE_POS + FALSE_NEG)) -gt 0 ]; then
recall=$(python3 -c "print(f'{${TRUE_POS} / (${TRUE_POS} + ${FALSE_NEG}) * 100:.1f}%')" 2>/dev/null || echo "n/a")
else
recall="n/a (keine erwarteten contradicted-Claims)"
fi
echo "Precision: ${precision} (Anteil korrekt widerlegter unter allen Widerlegungen)"
echo "Recall: ${recall} (Anteil erkannter Fehler unter allen bekannten Fehlern)"
echo ""
echo "True Positives: ${TRUE_POS} (korrekter contradicted-Fund)"
echo "False Positives: ${FALSE_POS} (fälschlich widerlegter korrekter Fakt)"
echo "False Negatives: ${FALSE_NEG} (nicht erkannter Fehler)"
echo "True Negatives: ${TRUE_NEG} (korrekt als nicht-widerlegbar bewertet)"
echo ""
echo "Kosten: \$${TOTAL_COST}"
echo "Zeit: $((TOTAL_TIME / 1000))s total"
echo ""
echo "Reports: ${RESULTS_DIR}/"
# Zusammenfassung speichern
{
echo "Testlauf: ${TIMESTAMP}"
echo "Modus: ${MODE}"
echo "Fälle: ${CASE_PASS} OK | ${CASE_FAIL} fehlgeschlagen | ${CASE_ERROR} Fehler"
echo "Claims: ${TOTAL_CLAIMS} geprüft"
echo "Precision: ${precision}"
echo "Recall: ${recall}"
echo "TP=${TRUE_POS} FP=${FALSE_POS} FN=${FALSE_NEG} TN=${TRUE_NEG}"
echo "Kosten: \$${TOTAL_COST}"
echo "Zeit: $((TOTAL_TIME / 1000))s"
} > "${RESULTS_DIR}/summary.txt"
# Exit-Code: 0 wenn alle Fälle bestanden
if [ "${CASE_FAIL}" -gt 0 ] || [ "${CASE_ERROR}" -gt 0 ]; then
exit 1
fi
exit 0