Retrieval-Goldset + Evidence-in-Pool-Recall-Harness als #232-Abnahme (PR-A) - #254
Merged
Conversation
-Abnahme (PR-A) Additives Abnahme-Artefakt fuer den kommenden #232-Retrieval-Fix (PR-B). Aendert keinen Retrieval-/Chunking-Code, sondern macht den Granularitaets-Mismatch (Chunk- vs. Satz-Retrieval) messbar und reproduzierbar. - generative/calibration/retrieval-goldset/anchors.jsonl: 11 hand-adjudizierte, pdftotext-verifizierte Anker aus 3 Diagnose-Laeufen (Hrastinski 2008, Bates 2017, Suehl-Strohmenger 2008). 10x false_positive_retrieval_miss + 1x true_hallucination (idx8 Table-3-Attributionsfehler als Negativ-Kontrolle, darf vom Fix nicht wegkalibriert werden). 2 Cross-Lingual-Faelle mit niedriger Presence-Cosine (0,64/0,67). - generative/tests/test_retrieval_goldset.py: deterministischer Harness ohne LLM. Misst Evidence-in-Pool-Recall ueber die FP-Anker (aktuell 2/10 = 20% auf master, der Bug-Beleg). Scharfe Assertion recall>=0.90 als xfail(strict=True), bis PR-B den Recall hebt. Negativ-Kontrolle bereits gruen. @pytest.mark.slow (MiniLM-Load), damit die regulaere Suite (-m "not slow") sie deselektiert. - generative/calibration/retrieval-goldset/build_from_reports.py: Parser fuer die Anker-Forensik-Tabellen der LAUF-INFO.md-Diagnoseberichte (Schritt 1). - README.md: Herkunft, Format, Adjudikations-Legende, reale Retrieval-Zahlen, verworfene Kandidaten, Erweiterungs-Anleitung. - .gitignore: scoped Ausnahme fuer anchors.jsonl (vom *.jsonl-Run-Output-Filter). Refs #232
…engig, keine fixe Referenzzahl Nachbesserung nach unabhaengigem Review (harte Faktentreue-Regel): ein zweiter Messlauf ergab 4/10 statt der zuvor als Fakt genannten 2/10. Ursache: Modell-/ Library-Versionsdrift (embeddings.position_ids | UNEXPECTED im BertModel-Load). - "Reale Zahlen"-Sektion -> "Beobachtete Zahlen": die "bit-fuer-bit dieselbe Pipeline-Logik"-Behauptung entfernt; die feste 2/10-Ziffer durch einen Caveat ersetzt (Recall beobachtet 2/10-4/10 ueber verschiedene sentence-transformers- Zustaende, in JEDEM Fall robust unter der 0,90-Schwelle). Die Cosine-Tabelle bleibt als illustrative Momentaufnahme EINES Environments, ausdruecklich als driftend markiert. - Abnahme fuer PR-B praezisiert: prueft die Recall-Verbesserung IN DERSELBEN Umgebung (before/after), NICHT das Erreichen einer absoluten Referenzzahl. - Cross-Lingual-Presence-Cosine (idx4/idx13) von "deterministisch nachgerechnet" auf "gemessen, umgebungsabhaengig (~0,64-0,67)" entschaerft. - build_from_reports.py: Regex-Edge-Case dokumentiert (pipe-foermiger Teilstring im Claim/Befund kann still fehlparsen; Absicherung = verpflichtende manuelle pdftotext-Gegenprobe vor Aufnahme in anchors.jsonl). anchors.jsonl unveraendert (Anker sind PDF-verifiziert und korrekt). Refs #232
TillQuandel
added a commit
that referenced
this pull request
Jul 14, 2026
…g gegen Retrieval-Miss (#232) (#265) * fix(eval): Satz-Level-Retrieval-Rescue + Titel-Chunk-Deprioritisierung gegen Retrieval-Miss (#232) Root Cause (#232): Granularitaets-Mismatch. Das Eval-Retrieval (_retrieve_claim_contexts) rankt Claims gegen CHUNK-Embeddings (100-180 Tok); der stuetzende SATZ hat hohe Claim-Cosine, sein Home-Chunk landet aber weit hinten, weil das Beleg-Signal ueber den Chunk gemittelt wird -> faellt aus adaptive_k -> der Judge sieht den Beleg nie -> falsch-positives not_in_context -> aufgeblaehte Halluzinationsrate. F1 -- Satz-Level-Retrieval-Rescue VOR dem Judge (_rescue_chunk_indices, _sentence_chunk_map): pro Claim werden die Home-Chunks des/der best-belegenden Satzes/Chunks ADDITIV in den Kontext-Pool injiziert. KEIN Relabel -- der Judge entscheidet weiter selbst. Zwei Pfade (Union): (1) semantisch nach max. Satz-Cosine je Chunk (faengt Cross-Lingual DE<->EN, wo der Chunk-Mittelwert verwaessert), (2) lexikalisch nach Content-Token-Overlap (faengt starke Paraphrasen gleicher Sprache, wo die Satz-Cosine niedrig ist -- Cross-Lingual- Netz gegen die Presence-Scorer-False-Negatives). F2 -- Titel-/Front-Matter-Chunk-Deprioritisierung: der erste Chunk wird, wenn front-matter-typisch (Title-Case-Dichte / sehr kurz), im adaptive_k-Ranking mild gedaempft (nicht entfernt -- Abstracts enthalten echte Belege; F1 holt den Chunk bei Bedarf zurueck). Zitat-Marker-robuste Evidence-Normalisierung (_normalize_for_evidence): PyMuPDF interleaviert hochgestellte Zitat-/Fussnoten-Marker als inline Ziffern-Tokens, die den woertlichen Beleg-Substring-Abgleich brechen. Kurze freistehende Ziffern-Tokens (1-3 Stellen) werden symmetrisch entfernt -- match-neutral fuer echte Zahlen, Jahre bleiben erhalten. Goldset #254 (test_retrieval_goldset.py): Evidence-in-Pool-Recall 2/10=0.200 (VORHER) -> 10/10=1.000 (NACHHER) in der Referenz-Umgebung. xfail(strict=True) entfernt, Assertion recall>=0.90 jetzt hart. Negativ- Kontrolle idx8 (true_hallucination) bleibt gruen. EVAL_VERSION 4.1 -> 4.2 (Methodik-Aenderung invalidiert den Eval-Cache- Namespace). quality_history.jsonl unveraendert (read-only); der eval_version- Skew ist gewollt sichtbar, fairer Vor/Nach-Vergleich braucht Re-Eval-Sweep (dokumentiert in calibration/retrieval-goldset/README.md). Snapshot in test_audit_double_call.py auf 4.2 nachgezogen. Suite: 5833 passed, 3 skipped (pytest -m "not slow"). ruff check + format sauber. * fix(eval): Rescue-Budget cappen + Masking-Risiko ehrlich dokumentieren/testen (#232) Nachbesserung nach Kontrolle (NEEDS-FIX): F1 loest die Ueber-Zaehl-Seite, trug aber ein unbeschriftetes Masking-Risiko auf der Unter-Zaehl-Seite. 1. Ehrliche Doku: Die Floor-/Safety-Behauptung war empirisch falsch. Der RESCUE_SENTENCE_MIN_COSINE-Floor (0.45) ist ein OFF-TOPIC-Filter, KEIN Halluzinations-Filter -- eine themen-nahe, aber unbelegte Halluzination (max Satz-Cosine ~0.64) liegt in derselben Cosine-Range wie echte Cross-Lingual- Belege (0.64-0.67) und passiert ihn. Kommentare in eval_quality_v4.py + README korrigiert: F1 injiziert (anders als das flag-only Fix B) tatsaechlich on-topic Kontext in den Judge-Pool und traegt damit ein Masking-Risiko. 2. Budget-Cap: RESCUE_MAX_CHUNKS=6, an die Dokumentgroesse gekoppelt (RESCUE_MAX_DOC_FRACTION=0.30) -> min(6, round(0.30*n_chunks)). Begrenzt die injizierte Kontextmenge (Masking-Flaeche). Semantischer + lexikalischer Pfad werden vor dem Cap fair verschraenkt (Round-Robin), damit das Cap keinen Pfad aushungert. Goldset-Recall mit gebuendeltem Budget neu gemessen: bleibt 10/10. 3. Masking-Richtung testbar: zwei neue Goldset-Anker (Hrastinski) -- eine topical_hallucination_probe (fabrizierte, themen-nahe Aussage) und eine off_topic_control. Neue Tests belegen ohne Judge: (a) fuer die Probe wird on-topic Kontext injiziert, der fabrizierte Beleg landet aber NICHT im Pool, und das Budget-Cap greift; (b) Off-Topic bekommt 0 Rescue-Chunks. Beide sind aus der FP-Recall-Population ausgeschlossen (Metadaten-Test). 4. Nicht ueberclaimen: klar dokumentiert (Code + README + Test-Docstring), dass die volle Masking-Validierung (bleibt hallucination_rate ehrlich?) einen Re-Eval-Sweep mit echtem Judge braucht -- Recall-vs-Masking ist ein realer, offen benannter Trade-off. Minor: _normalize_for_evidence-Ziffern-Kommentar praezisiert (match-neutral nur bei Zahlgleichheit; bei Zahl-Differenz geht Diskriminanz verloren, akzeptabel da Produktions-Verifikation fuzzy). Suite: 5834 passed, 3 skipped (pytest -m "not slow"); Goldset 6/6 (-m slow), Recall 10/10. ruff check + format sauber. --------- Co-authored-by: TillQuandel <tillq@live.de>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Zweck
Additive Abnahme-Grundlage fuer den kommenden #232-Retrieval-Fix (PR-B). Diese PR aendert keinen Retrieval-/Chunking-Code — sie konserviert die handadjudizierten Kalibrierungs-Datenpunkte aus der Diagnose und macht den Bug (Granularitaets-Mismatch Chunk- vs. Satz-Retrieval) als deterministische Kennzahl messbar.
Was drin ist
generative/calibration/retrieval-goldset/anchors.jsonl— 11 hand-adjudizierte Anker aus 3 Diagnose-Laeufen, jederevidence_quoteperpdftotext -layoutgegen die Original-PDF und gegen den echtenChunk.text-Output der Pipeline verifiziert:20260712-215118): 6 Anker20260712-213647): 2 Anker20260712-205627): 3 Ankergenerative/tests/test_retrieval_goldset.py— deterministischer Harness, kein LLM. Nutzt die Produktions-Bausteine (_chunks_from_sentences,_retrieve_claim_contexts,_build_context_pool,_normalize_for_evidence).generative/calibration/retrieval-goldset/build_from_reports.py— Regex-Parser fuer die Anker-Forensik-Tabellen der Diagnose-Berichte (Schritt 1 der Pipeline).README.md— Herkunft, Format, Adjudikations-Legende, reale Retrieval-Zahlen, verworfene Kandidaten, Erweiterungs-Anleitung..gitignore— scoped Ausnahme fueranchors.jsonl(der globale*.jsonl-Filter zielt auf Run-Output, nicht auf dieses versionierte Abnahme-Artefakt).Anker-Aufschluesselung
false_positive_retrieval_misstrue_hallucination(Negativ-Kontrolle idx8)expected_label: contradicted,adjudication: true_hallucination). Der spaetere Fix darf sie NICHT wegkalibrieren; der Test prueft explizit, dass ihre kontrahierende Evidenz korrekt im Pool landet (bereits heute gruen).Der Bug in Zahlen (master)
Evidence-in-Pool-Recall ueber alle 10
false_positive_retrieval_miss-Anker: 2/10 = 20,0 % (batched wie Produktion, ein gemeinsamer Kontext-Pool je Note). Deterministisch reproduziert; die Chunk-Top-Cosine deckt sich exakt mit den Diagnose-Berichten. Die 2 Treffer sind Batch-Pooling-/_expand_context-Zufallsrettungen (bei isolierter Einzel-Claim-Retrieval waere der Recall 0/10), kein Fix.Die scharfe Assertion
recall >= 0.90ist als@pytest.mark.xfail(strict=True)markiert: heute erwartet-rot (xfail, zaehlt nicht als Failure), nach PR-B (F1+F2) wird der Recall gehoben → XPASS →strict=TrueFAILt den Lauf und zwingt zum Entfernen des xfail-Markers → Abnahme scharf geschaltet.Status
pytest generative lib/decision_engine/tests shared/tests -q: 5789 passed, 3 skipped, 6 deselected (0 unerwartete Failures; die 2 slow-Goldset-Tests unter den Deselected).ruff check+ruff format --check: sauber.quality_history.jsonl,runs/,.cache/eval/baseline— reine Lese-Zugriffe.Refs #232 (schliesst NICHT — #232 schliesst erst PR-B, der den xfail scharf schaltet).
🤖 Generated with Claude Code
https://claude.ai/code/session_019AnPkyEqHyKUSJKVqp3SZS