Repository navigation
fix(report): exclude unassessed results from failure counts - #124
Conversation
Un-assessed scorer results (assessed=False) are coverage gaps, not measured failures. ComplianceReport.to_dict() and to_summary() previously treated every result with passed=False as a failure, so a missing-context or prediction-error row was reported as a policy violation and inflated the category failure counts. The report now filters on result.assessed and not result.passed, and the summary text surfaces the un-assessed count next to the pass ratio instead of hiding it. Carried over from the closed wandb#110 per knisar's recovery instructions, rebuilt from current main with the three remaining test corrections: - two assessed failures on one row now use category totals total_items=2 / failed_items=2 while the report still counts one failed row - input preservation is checked against a deep-copy snapshot of the whole EvaluationResults instead of only the emitted input string - the row with an assessed failure and an unassessed result asserts that both the dict and the serialized JSON retain only the assessed failure
knisar
left a comment
There was a problem hiding this comment.
The rebuilt branch has the correct history and a focused two-file diff. All three corrections requested on #110 are present. Missing measurements stay visible in category lines, and only assessed failures enter the row count and nested failure payload.
Independent validation on Python 3.13.1: python -m pytest -q -p no:cacheprovider passed 949 tests with 16 skipped. A further 24 checks using the real evaluation pipeline passed, covering shared and separate categories, prediction errors, multiple scorer failures on one row, JSON file output, complete input preservation, and exact compatibility with main for fully assessed output. The full-suite failures reported from your environment do not reproduce here.
Dependency consistency, Ruff (--select E9,F63,F7,F82), REUSE lint, and the committed patch whitespace check all passed. This resolves #108.
Related issue
Closes #108
This is a replacement for the closed #110, rebuilt from current
wandb/rai-toolkitmain(ea99e45) per the recovery instructions knisar left on #110. The previous branch had no shared history with upstreammain, so GitHub showed the whole repository as newly added; this branch is a normal two-file diff on top of currentmain.What changed
Only two files are touched, exactly as requested on #110:
rai_toolkit/evaluation/report.pytests/test_compliance_report_unassessed.pyrai_toolkit/evaluation/report.pyScorerResult.assessed == Falsemarks a row the scorer could not evaluate (missing context, parser failure, prediction error). Those rows are coverage gaps, not measured failures, butComplianceReportwas still counting them as policy violations:to_dict()filteredfailed_scoresonnot result.passedand included a row infailed_itemsif any scorer hadpassed=False. Both now requireresult.assessed and not result.passed, so an unassessed result never appears infailed_scoresand never puts its row on the failure list.to_summary()counted failures with the samenot result.passedcheck. It now uses the sameassessedguard, so theItems with failures: N/Mline is not inflated by unassessed rows.MIT-1.1: 0.0% (0/1 passed, 1 un-assessed) [FAIL]; categories with no unassessed results keep the existingMIT-1.1: 100.0% (1/1 passed) [PASS]format.No production behaviour changes beyond the unassessed handling were made.
tests/test_compliance_report_unassessed.py18 focused tests covering the all-unassessed case, mixed pass/unassessed, assessed failure plus unassessed on the same row, fully assessed rows (unchanged output), two assessed failures on one row, JSON serialization, input preservation, and failure-count text.
The three corrections knisar listed on #110 are included:
total_items=2/failed_items=2, while the report still counts one failed row, and the test asserts both the0/2 passedcategory line andItems with failures: 1/1.copy.deepcopysnapshot of the entireEvaluationResultsobject afterto_summary(),to_dict()andto_json()run, instead of only checking the emittedinputstring.failed_scoreskeys are exactly{"genuine"}).Validation
python -m pytest tests/test_compliance_report_unassessed.py -q: 18 passedpython -m pytest tests/test_pipeline_prediction_errors.py tests/test_redteam_report_surfaces.py -q: 18 passed, 8 skippedpython -m pytest -q(full suite, this branch): 738 passed, 15 skipped, 211 failed, 64 errorspython -m pytest -q(full suite, unmodifiedupstream/mainatea99e45, same environment): 720 passed, 15 skipped, 211 failed, 64 errorsFAILED/ERRORlists from the two runs: identical — the 211 failures and 64 errors are pre-existing in this checkout (missing optional SDKs such asanthropic,weave, and other optional extras) and are not caused by this change. The branch adds 18 passing tests and no new failures.The GitHub Actions run for this PR is currently at
action_required— it is waiting on the upstream maintainer to approve the workflow run for this fork branch, as expected for a first-time external contribution. No test job has run yet; the numbers above come from the local runs.AI assistance
AI assistance was used to carry the two-file change over from #110, apply the three test corrections listed in knisar's #110 review, and run the test suites above. I verified the diff scope by hand (only the two requested files), confirmed the failure sets are identical to unmodified
main, and personally reviewed every changed line.Checklist
mainCloses #108linked