perf(eval): Audit-Pass rechnet nur auditierte Claims neu (#151)#215
Merged
Conversation
…151) Teilfix zu #151 (Nebenbefund PR #181): eval_note rief _claim_scores_from_judge im Audit-Pfad zweimal mit identischen Primaer-Inputs auf (einmal ohne audit_rows, dann nochmal MIT audit_rows aber wieder ueber ALLE judge_rows). Fuer nicht-auditierte Claims war der zweite Durchlauf bit-identische Doppelarbeit (reine CPU, kein LLM-Call), da audit_by_idx.get(claim_idx) fuer sie in beiden Durchlaeufen ohnehin immer None liefert. Der zweite Durchlauf beschraenkt sich jetzt auf die judge_rows der tatsaechlich auditierten Claims; das Ergebnis wird per claim_idx in claim_scores zurueckgemergt. Nicht-auditierte Eintraege bleiben unveraendert aus dem ersten Durchlauf. Zwei Tests (generative/tests/test_audit_double_call.py): - Aufruf-Zaehler-Spy auf _claim_scores_from_judge: RED zeigte, dass der Audit-Durchlauf exakt dieselbe Claim-Menge wie der Primaer- Durchlauf abdeckte; nach dem Fix ist es eine echte Teilmenge. - Aequivalenz-Regression gegen einen eingefrorenen Snapshot des unveraenderten Codes (gleiches Fixture, Claims mit und ohne audit_rows-Eintrag): voller eval_note-Output bit-identisch bis auf timestamp. Kanonische Suite (generative lib/decision_engine/tests shared/tests): 5695 passed, 3 skipped, 4 deselected. ruff format/check sauber. Cross-Model-Review (Mistral magistral-medium-latest): kein Fund. Teilfix zu #151 -- Issue bleibt offen (Stage-8-Parallelisierung, concept_text_window, quality_history-Format, Cache-Root- Konsolidierung, source_coverage/covered_pages sind separate Punkte).
…ppeln (#151 Nachbesserung)
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.
Problem
Teilfix zu #151 (Nebenbefund PR #181):
eval_note(generative/eval_quality_v4.py) rief_claim_scores_from_judgeim Audit-Pfad zweimal mit identischen Primaer-Inputs auf:Der zweite Aufruf lief ueber ALLE
judge_rows, nicht nur ueber die auditierten Claims. Fuer nicht-auditierte Claims istaudit_by_idx.get(claim_idx)in beiden Durchlaeufen immerNone— das Ergebnis war also bit-identische Doppelarbeit (reine CPU, kein LLM-Call, aber unnoetige Judge-Row-Verarbeitung + Evidence-Verifikation fuer jeden Claim ein zweites Mal).Fix
Der zweite Durchlauf beschraenkt sich jetzt auf die
judge_rowsder tatsaechlich auditierten Claims (audited_judge_rows) und mergt das Ergebnis perclaim_idxzurueck inclaim_scores. Nicht-auditierte Eintraege bleiben unveraendert aus dem ersten Durchlauf.RED-Beweis
Aufruf-Zaehler-Spy auf
_claim_scores_from_judge(generative/tests/test_audit_double_call.py::TestAuditPassRecomputesOnlyAuditedClaims): gegen den unveraenderten Code zeigte der Test, dass der Audit-Durchlauf exakt dieselbe Claim-Index-Menge{0,1,2,3,4,5}wie der Primaer-Durchlauf abdeckte (assert audit_idxs < set(primary_call["judge_idxs"])schlug fehl: "Both sets are equal"). Nach dem Fix ist es eine echte Teilmenge.Aequivalenz-Nachweis
TestEvalNoteResultUnchangedvergleicht den volleneval_note-Output (claim_scores, Aggregat-Kennzahlen, llm_usage) gegen einen eingefrorenen Snapshot des UNVERAENDERTEN Codes auforigin/master, erzeugt mit demselben synthetischen Fixture (6 Claims, davon 2 auditiert — einer per Low-Cosine-System-Trigger, einer per stratifiziertem Sample; einer der beiden zeigt eine echte Label-Aenderung durch Audit-Override). Ergebnis: bit-identisch bis auftimestamp(per Design bei jedem Laufdatetime.now()). Vor dem Fix ist dieser Test gruen (Snapshot korrekt eingefroren); nach dem Fix bleibt er gruen (kein Verhaltensunterschied).Suite-Ergebnis
pytest generative lib/decision_engine/tests shared/tests -q: 5695 passed, 3 skipped, 4 deselected, 0 Failures. Testzahl gesamt (inkl. deselected):origin/master5700, dieser Branch 5702 (+2 durch diesen PR).ruff format --check .undruff check .: sauber.Cross-Model-Review
Mistral (
magistral-medium-latest) hat den Diff geprueft: Merge-Logik korrekt bestaetigt, Edge Cases (leereaudit_indices, Reihenfolge, doppelteclaim_idx) abgedeckt, Diff minimal und im Scope. Kein Fund.Scope
Nur
generative/eval_quality_v4.py+ Test. Angefasst wird ausschliesslich der doppelte_claim_scores_from_judge-Aufruf im Audit-Pfad — Stage-8-Parallelisierung,concept_text_window,quality_history-Format/Retention, Cache-Root-Konsolidierung (config.py vs. db.py) und dersource_coverage/covered_pages-Befund aus #151 sind bewusst NICHT Teil dieses PRs (brauchen Maintainer-Entscheidungen).Teilfix zu #151 — Issue bleibt offen.
Nachbesserung (Fable-Kontrollreview)
test_audit_double_call.py):EXPECTED_RESULTpinnte zuvor"version": "v0.3.140"und das kompletteMODEL_CONFIG-Dict als Literale. Der Maintainer-Modus_auto_version_bumpschreibtAGENT_VERSIONbei jeder Pipeline-Code-Aenderung hoch — der Snapshot-Test haette dann grundlos gebrochen. Fix:_run_eval_noterufteq.eval_note(..., pipeline_version="v0.0.0")mit fixem Wert auf (Konvention wietest_per_agent_tracking.py::test_aggregate_includes_model_config),EXPECTED_RESULT["version"]folgt;model_configreferenziert jetzt direkteq.MODEL_CONFIGstatt eine Kopie zu pflegen. Die Bit-Identitaets-Aussage des Tests bleibt erhalten (_aggregate()schreibt exakt dieses Objekt unveraendert ins Ergebnis).origin/master= 5700, dieser Branch = 5702). Oben korrigiert._normalize_judge_rowsingenerative/eval_quality_v4.py(~Z. 481-501) gefunden — bei ungueltigem Label wirdparse_errorgesetzt,evidencebleibt aber stehen._claim_scores_from_judgeberechnet darausevidence_verified=True/FalsestattNone, was einen latentenClaimInput.__post_init__-Crash ausloesen kann. Ausserhalb des Scopes dieses PRs; als Hinweis fuer eine moegliche Folge-Issue dokumentiert.