Score-Bewertungen ohne Zitate (BUND 21/3660 + fehlende linke/afd-Grundsatzprogramme) #63

Closed
opened 2026-04-10 01:40:19 +02:00 by tobias · 1 comment
Owner

Befund

BUND 21/3660 (Linke-Antrag "Kostenfreies, gesundes und leckeres Mittagessen in allen Schulen und Kitas") zeigt im Report Scores zu Wahl- und Parteiprogrammen, aber null Zitate für mehrere Fraktionen — obwohl die Begründungen so klingen, als hätte das LLM konkrete Programmstellen im Kopf.

Aktueller DB-Inhalt (assessments WHERE drucksache='21/3660'):

Fraktion WP-Score WP-Zitate GP-Score GP-Zitate
Die Linke (Antragsteller) 10/10 0 9/10 0
SPD 9/10 1 8/10 0
CDU 5/10 0 4/10 0
GRÜNE 10/10 0 9/10 0

WP-Begründung Linke: "Der Antrag entspricht exakt dem Kernziel der Linken nach 'sozialer Umverteilung', 'gesellschaftlicher Daseinsvorsorge' u..." — klingt überzeugt, kein Beleg.

Ursachen (zwei verschiedene Bug-Klassen)

1. Fehlende Grundsatzprogramme im PROGRAMME-Index

grep -E '(linke|afd)-grundsatz' app/embeddings.py

linke-grundsatz: not registered
afd-grundsatz: not registered

Aber:

gruene-grundsatz: REGISTERED
spd-grundsatz: REGISTERED
cdu-grundsatz: REGISTERED
fdp-grundsatz: REGISTERED

Auf Bundestags-Ebene werden ausschließlich Grundsatzprogramme (bundesland=NULL) retrievt, weil kein bundesland-spezifisches Wahlprogramm passt. Die Folge:

  • Linke: Null retrievte Chunks → reconstruct_zitate dropped alles, was der LLM aus Trainingswissen zu Linke-Positionen schreibt
  • AfD: würde dasselbe Problem haben (kein Antrag in dieser Drucksache, aber bei AfD-Anträgen oder AfD-Bewertungen würde es zuschlagen)

2. Substring-Match scheitert auch wenn Chunks existieren

GRÜNE hat gruene-grundsatz registriert. Trotzdem 0 Zitate. Hypothese: der LLM hat aus den Chunks paraphrasiert statt wörtlich zu zitieren, und der Substring/5-Wort-Anker-Match in reconstruct_zitate (ADR 0001) schlägt fehl → Zitat wird verworfen. Das ist genau die Drift-Toleranz-Lücke, die ADR 0001 in den "Negativ"-Konsequenzen explizit benennt.

Score bleibt trotzdem hoch, weil das LLM den Score unabhängig von den Citations vergibt. Resultat: Score-Bewertungen ohne Quellen, was die Vertrauenswürdigkeit des Reports unterminiert.

Empfohlene Lösungswege (separat planbar)

A — PROGRAMME-Index erweitern (low-hanging)

Beide fehlenden Grundsatzprogramme als PDF beschaffen + indexieren:

  • DIE LINKE: Erfurter Programm 2011 (das aktuelle Grundsatzprogramm)
  • AfD: Grundsatzprogramm 2016

Beide sind öffentlich auf den jeweiligen Bundespartei-Websites verfügbar. Indexieren: index_programm("linke-grundsatz", referenzen_dir) analog zu den existierenden 4 Grundsatzprogrammen.

Schließt Teil 1 der Bug-Klasse vollständig.

B — UI-Transparenz für leere Citation-Sets

Wenn wahlprogramm.score >= 7 aber len(zitate) == 0: deutlich im Report anzeigen:

⚠️ Score basiert nicht auf belegbaren Programm-Stellen.

Differenzierung zwischen den zwei Ursachen:

Ursache Anzeige
Programm nicht im Index "Kein Programm hinterlegt — Bewertung nicht überprüfbar"
Programm da, LLM-Zitate dropped "Quelle konnte nicht verifiziert werden — Bewertung mit Vorsicht"

Server kann das durch einen Rückgabewert von reconstruct_zitate unterscheiden (vorher-Anzahl vs. nachher-Anzahl der Zitate pro Block + ob Chunks für die Partei existierten).

C — LLM-Prompt: Force-Honesty bei fehlenden Quellen

Im format_quotes_for_prompt Output explizit pro Partei vermerken, ob Chunks da sind oder nicht. Im System-Prompt eine harte Regel:

Wenn für eine Fraktion in <wahlprogramm_zitate> kein Block existiert oder der Block leer ist, setze NULL als Score für wahlprogramm und parteiprogramm dieser Fraktion. Du darfst keinen Score auf Trainingswissen basieren.

Verhindert das Phänomen strukturell für künftige Analysen. Bestehende Assessments müssen re-analysiert werden, um den Effekt zu sehen.

Acceptance Criteria

  • A: linke-grundsatz und afd-grundsatz in PROGRAMME registriert + im Container indexiert
  • B: Im Report-UI markiert ein Score-Block mit 0 Zitaten den Vertrauensgrad farblich/textuell
  • C: format_quotes_for_prompt markiert leere Partei-Blöcke; analyzer.get_system_prompt weist LLM an, dann NULL zu setzen
  • BUND 21/3660 nach Re-Analyse zeigt entweder echte Zitate oder NULL-Scores (kein Score ohne Beleg)

Refs

  • ADR 0001 LLM-Citation-Binding (webapp/docs/adr/0001-llm-citation-binding.md) — der "Negativ"-Abschnitt benennt genau diese Drift-Toleranz-Lücke
  • Issue #60 (LLM-Halluzinationen, geschlossen) — Vorgänger-Bug-Klasse, dort war's "falsche Quelle", hier ist's "keine Quelle"
## Befund `BUND 21/3660` (Linke-Antrag "Kostenfreies, gesundes und leckeres Mittagessen in allen Schulen und Kitas") zeigt im Report Scores zu Wahl- und Parteiprogrammen, aber **null Zitate** für mehrere Fraktionen — obwohl die Begründungen so klingen, als hätte das LLM konkrete Programmstellen im Kopf. Aktueller DB-Inhalt (`assessments WHERE drucksache='21/3660'`): | Fraktion | WP-Score | WP-Zitate | GP-Score | GP-Zitate | |---|---|---|---|---| | **Die Linke** (Antragsteller) | 10/10 | **0** | 9/10 | **0** | | SPD | 9/10 | 1 | 8/10 | 0 | | CDU | 5/10 | 0 | 4/10 | 0 | | GRÜNE | 10/10 | 0 | 9/10 | 0 | WP-Begründung Linke: *"Der Antrag entspricht exakt dem Kernziel der Linken nach 'sozialer Umverteilung', 'gesellschaftlicher Daseinsvorsorge' u..."* — klingt überzeugt, kein Beleg. ## Ursachen (zwei verschiedene Bug-Klassen) ### 1. Fehlende Grundsatzprogramme im PROGRAMME-Index `grep -E '(linke|afd)-grundsatz' app/embeddings.py` → ``` linke-grundsatz: not registered afd-grundsatz: not registered ``` Aber: ``` gruene-grundsatz: REGISTERED spd-grundsatz: REGISTERED cdu-grundsatz: REGISTERED fdp-grundsatz: REGISTERED ``` Auf Bundestags-Ebene werden **ausschließlich** Grundsatzprogramme (`bundesland=NULL`) retrievt, weil kein bundesland-spezifisches Wahlprogramm passt. Die Folge: - **Linke**: Null retrievte Chunks → `reconstruct_zitate` dropped **alles**, was der LLM aus Trainingswissen zu Linke-Positionen schreibt - **AfD**: würde dasselbe Problem haben (kein Antrag in dieser Drucksache, aber bei AfD-Anträgen oder AfD-Bewertungen würde es zuschlagen) ### 2. Substring-Match scheitert auch wenn Chunks existieren GRÜNE hat `gruene-grundsatz` registriert. Trotzdem 0 Zitate. Hypothese: der LLM hat aus den Chunks **paraphrasiert** statt wörtlich zu zitieren, und der Substring/5-Wort-Anker-Match in `reconstruct_zitate` (ADR 0001) schlägt fehl → Zitat wird verworfen. Das ist genau die Drift-Toleranz-Lücke, die ADR 0001 in den "Negativ"-Konsequenzen explizit benennt. Score bleibt trotzdem hoch, weil das LLM den Score unabhängig von den Citations vergibt. Resultat: **Score-Bewertungen ohne Quellen**, was die Vertrauenswürdigkeit des Reports unterminiert. ## Empfohlene Lösungswege (separat planbar) ### A — PROGRAMME-Index erweitern (low-hanging) Beide fehlenden Grundsatzprogramme als PDF beschaffen + indexieren: - **DIE LINKE: Erfurter Programm 2011** (das aktuelle Grundsatzprogramm) - **AfD: Grundsatzprogramm 2016** Beide sind öffentlich auf den jeweiligen Bundespartei-Websites verfügbar. Indexieren: `index_programm("linke-grundsatz", referenzen_dir)` analog zu den existierenden 4 Grundsatzprogrammen. Schließt Teil 1 der Bug-Klasse vollständig. ### B — UI-Transparenz für leere Citation-Sets Wenn `wahlprogramm.score >= 7` aber `len(zitate) == 0`: deutlich im Report anzeigen: > ⚠️ Score basiert nicht auf belegbaren Programm-Stellen. Differenzierung zwischen den zwei Ursachen: | Ursache | Anzeige | |---|---| | Programm nicht im Index | "Kein Programm hinterlegt — Bewertung nicht überprüfbar" | | Programm da, LLM-Zitate dropped | "Quelle konnte nicht verifiziert werden — Bewertung mit Vorsicht" | Server kann das durch einen Rückgabewert von `reconstruct_zitate` unterscheiden (vorher-Anzahl vs. nachher-Anzahl der Zitate pro Block + ob Chunks für die Partei existierten). ### C — LLM-Prompt: Force-Honesty bei fehlenden Quellen Im `format_quotes_for_prompt` Output explizit pro Partei vermerken, ob Chunks da sind oder nicht. Im System-Prompt eine harte Regel: > Wenn für eine Fraktion in `<wahlprogramm_zitate>` kein Block existiert oder der Block leer ist, setze **NULL** als Score für `wahlprogramm` und `parteiprogramm` dieser Fraktion. Du darfst keinen Score auf Trainingswissen basieren. Verhindert das Phänomen strukturell für künftige Analysen. Bestehende Assessments müssen re-analysiert werden, um den Effekt zu sehen. ## Acceptance Criteria - [ ] **A**: `linke-grundsatz` und `afd-grundsatz` in PROGRAMME registriert + im Container indexiert - [ ] **B**: Im Report-UI markiert ein Score-Block mit 0 Zitaten den Vertrauensgrad farblich/textuell - [ ] **C**: `format_quotes_for_prompt` markiert leere Partei-Blöcke; `analyzer.get_system_prompt` weist LLM an, dann NULL zu setzen - [ ] BUND 21/3660 nach Re-Analyse zeigt entweder echte Zitate oder NULL-Scores (kein Score ohne Beleg) ## Refs - ADR 0001 LLM-Citation-Binding (`webapp/docs/adr/0001-llm-citation-binding.md`) — der "Negativ"-Abschnitt benennt genau diese Drift-Toleranz-Lücke - Issue #60 (LLM-Halluzinationen, geschlossen) — Vorgänger-Bug-Klasse, dort war's "falsche Quelle", hier ist's "keine Quelle"
Author
Owner

Resolved. AfD-Grundsatzprogramm 2016 (128 Chunks via Wayback) + DIE LINKE Erfurter Programm 2011 (111 Chunks via originalsozial.de) indexiert. Alle 6 Grundsatzprogramme (CDU, SPD, GRUENE, FDP, AfD, LINKE) jetzt im Index.

Resolved. AfD-Grundsatzprogramm 2016 (128 Chunks via Wayback) + DIE LINKE Erfurter Programm 2011 (111 Chunks via originalsozial.de) indexiert. Alle 6 Grundsatzprogramme (CDU, SPD, GRUENE, FDP, AfD, LINKE) jetzt im Index.
Sign in to join this conversation.
No description provided.