← Back to portfolio

independent · policy evaluation · responsible ML · benchmark design

A moderation benchmark where the correct answer changes when the policy changes.

I built IntegrityBench to test changing moderation policies, then extended it into a fail-closed service evaluated on public Civil Comments data. The generated policy cases remain controls; the real-data track is the model evidence.

IntegrityBench policy-version evaluation workflow
The benchmark keeps the topic fixed while policy versions change the required action.

Why I built it

A static moderation model can appear accurate while applying yesterday's rule. The benchmark gives the same topic different actions under different policy versions. That makes stale-policy behavior visible instead of folding it into a generic accuracy score.

Three systems

The prompt-only control always uses policy v1. The retrieval baseline fetches the current policy. The candidate system retrieves and reranks current rules, checks evidence sufficiency, returns a structured decision, and escalates if a policy match lacks support. Deterministic controls keep the benchmark runnable without an API key; later LLM, RAG, and LoRA runs plug into the same output contract.

Control result

The static-policy control reached 0.620 macro F1 and a 0.286 false-acceptance rate. Current-policy retrieval reached 1.000 macro F1 with no false acceptances or false rejections on the generated v0.1 set. The gap is a construction check, not a production claim: the generator and lexical controls share a controlled vocabulary.

Real-data candidate

A character TF-IDF and class-balanced logistic model was trained on 100,000 public Civil Comments and evaluated once on all 97,320 test rows. Validation-selected safety thresholds reduced false acceptance from 11.43% to 1.84%, with a 48.08% escalation rate.

Human-reviewed distribution shift

I froze the Civil Comments candidate and evaluated it without retraining on 2,802 deduplicated ToxicChat prompts whose labels were explicitly marked as human annotations. False acceptance rose to 59.32%, while false rejection was 2.94%. The result is a useful failure: conversational traffic is different enough that the candidate cannot be presented as a general moderation model.

Why it stayed blocked

The candidate missed two release limits: threat false acceptance was 6.05% and decision calibration error was 5.31%. The service, checksummed registry, review queue, shadow comparison, rollback, container, telemetry, and Terraform plan are implemented, but no live moderation or cloud SLO is claimed.

Limits and next run

The compact-transformer comparison is implemented but still needs a real GPU run. The blinded annotation set still needs two independent reviewers and adjudication. Neither result will be inferred from fixtures.