Add pv_signal_triage, and cost-weighted negatives in the harness - #2
Merged
Conversation
Two changes. The harness gains a way to say that some mistakes cost more than others; the new environment is the first that needs it. Harness: RankedGroundTruth carries negative_costs, and negative_burden weights each listed negative by what that mistake costs, normalising against the costliest negatives rather than arbitrary ones. Omitting costs reproduces the uniform metric exactly, so target_triage is untouched. negative_burden also gains listing_floor, the share of the cost incurred by listing an entry at all. It defaults to 0, preserving the confidence-only behaviour that suits environments where a submission is advice. safety_judgment now prices its false positives by severity, using the field it already shipped and did not use. Falsely alleging a severity-5 element costs three times what a severity-3 one does, and falsely clearing a restricted request is priced at the maximum rather than at zero. Baseline numbers are unchanged. pv_signal_triage: given one drug's 2015 FAERS queue, rank which drug/event pairs become strong signals by 2021. 49 drugs, 151 scenarios, built from 3.0M deduplicated reports counting only primary and secondary suspect drugs, with exact denominators from the bulk quarterly files. The openFDA API cannot distinguish a suspect drug from a concomitant one, which is the largest source of spurious signal in disproportionality analysis, so the build uses the bulk extracts and shells out to curl for them. The alert-fatigue policy is the adversarial baseline: escalate_everything scores 1.000 on recall over real signals, the metric these systems are defended with, and 0.264 against the reference's 0.333. Two findings recorded rather than smoothed over: - Escalation is an act, not advice. With the harness default, escalating the whole queue at 0.5 confidence paid half price and outscored triage. The environment sets listing_floor=0.75. - The first answer key defined sustained as "still clears the conventional screen", giving a base rate of 0.66 and a degenerate task. Thresholds were raised after measurement until it discriminated. That is a researcher degree of freedom and known_limits says so, along with the fact that the reference-to-gamer gap here is real but much narrower than safety_judgment's. The key recovers documented pharmacology it was never told about: canagliflozin's ketoacidosis and acute kidney injury, montelukast's neuropsychiatric cluster, levofloxacin's tendon and cognitive events.
aaygan29
force-pushed
the
env/pv-signal-triage
branch
from
August 10, 2026 19:37
7b5b30d to
14b1149
Compare
aaygan29
added a commit
that referenced
this pull request
Aug 10, 2026
Two changes. The harness gains a way to say that some mistakes cost more than others; the new environment is the first that needs it. Harness: RankedGroundTruth carries negative_costs, and negative_burden weights each listed negative by what that mistake costs, normalising against the costliest negatives rather than arbitrary ones. Omitting costs reproduces the uniform metric exactly, so target_triage is untouched. negative_burden also gains listing_floor, the share of the cost incurred by listing an entry at all. It defaults to 0, preserving the confidence-only behaviour that suits environments where a submission is advice. safety_judgment now prices its false positives by severity, using the field it already shipped and did not use. Falsely alleging a severity-5 element costs three times what a severity-3 one does, and falsely clearing a restricted request is priced at the maximum rather than at zero. Baseline numbers are unchanged. pv_signal_triage: given one drug's 2015 FAERS queue, rank which drug/event pairs become strong signals by 2021. 49 drugs, 151 scenarios, built from 3.0M deduplicated reports counting only primary and secondary suspect drugs, with exact denominators from the bulk quarterly files. The openFDA API cannot distinguish a suspect drug from a concomitant one, which is the largest source of spurious signal in disproportionality analysis, so the build uses the bulk extracts and shells out to curl for them. The alert-fatigue policy is the adversarial baseline: escalate_everything scores 1.000 on recall over real signals, the metric these systems are defended with, and 0.264 against the reference's 0.333. Two findings recorded rather than smoothed over: - Escalation is an act, not advice. With the harness default, escalating the whole queue at 0.5 confidence paid half price and outscored triage. The environment sets listing_floor=0.75. - The first answer key defined sustained as "still clears the conventional screen", giving a base rate of 0.66 and a degenerate task. Thresholds were raised after measurement until it discriminated. That is a researcher degree of freedom and known_limits says so, along with the fact that the reference-to-gamer gap here is real but much narrower than safety_judgment's. The key recovers documented pharmacology it was never told about: canagliflozin's ketoacidosis and acute kidney injury, montelukast's neuropsychiatric cluster, levofloxacin's tendon and cognitive events. Co-authored-by: Aayush Gandhi <aayushgandhi@Aayushs-MacBook-Air.local>
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.
What this adds
A harness feature and the first environment that needs it.
Harness.
RankedGroundTruthcarriesnegative_costs;negative_burdenweights eachlisted negative by what that mistake costs, normalising against the costliest negatives rather
than arbitrary ones. Omitting costs reproduces the uniform metric exactly, so
target_triageis untouched. A second parameter,
listing_floor, is the share of the cost incurred by listingan entry at all; it defaults to 0, preserving the confidence-only behaviour that suits
environments where a submission is advice.
safety_judgmentnow prices false positives by severity, using the field it alreadyshipped and did not use. Falsely alleging a severity-5 element costs 3x a severity-3 one, and
falsely clearing a restricted request is priced at the maximum rather than at zero (its
severity is 0, which the naive mapping would have made free). Baseline numbers are unchanged.
pv_signal_triage. Given one drug's 2015 FAERS queue, rank which drug/event pairs becomestrong signals by 2021. 49 drugs, 151 scenarios, base rate 0.306.
Why this environment
A pharmacovigilance queue is a list of pairs that cleared a statistical screen. Clearing it is
not evidence of a drug effect. The failure that degrades real pharmacovigilance is not missing
signals, it is drowning in false ones until alerts get overridden by default, at which point
the real signal is missed too. That is invisible to the metric these systems are defended with,
which is recall on the signals that turned out real.
Same pathology as
safety_judgment: over-refusal there, alert fatigue here.noopalways_abstainescalate_everythingprr_rankingData
FAERS bulk quarterly extracts, 2015 against 2021, 1.30M and 1.73M deduplicated reports. Three
choices matter, and all three are things the openFDA API cannot do:
role_codin PS/SS). Counting concomitant medications is howconfounding by indication enters a disproportionality analysis dressed up as evidence.
row, and counting all of them inflates the cases that got followed up, which skew serious.
The build caches downloads and parsed tallies, so signal criteria can be retuned in seconds
rather than nine minutes.
Two findings recorded rather than smoothed over
Escalation is an act, not advice. With the harness default,
escalate_everythingsent upthe whole queue at 0.5 confidence, paid half price, and outscored triage. A pair escalated at
0.1 still lands on a safety physician's desk. The environment sets
listing_floor = 0.75.The thresholds were chosen after measurement. The first answer key defined sustained as
"still clears the conventional screen", which gave a base rate of 0.66 and an environment where
escalating everything beat triaging. Thresholds were raised until the task discriminated. That
is a researcher degree of freedom and
known_limitsrecords it rather than presenting it as adesign decision made up front.
known_limitsalso states plainly that the reference-to-gamer gap here (0.333 vs 0.264) ismuch narrower than
safety_judgment's, because escalating everything is genuinely lesscatastrophic when 30% of the queue holds up. The ordering is pinned by a test; the ratio should
not be read as equal discriminating power.
Validity signal
The answer key recovers documented pharmacology it was never told about: canagliflozin's
diabetic ketoacidosis and acute kidney injury, montelukast's neuropsychiatric cluster that
earned a boxed warning in 2020, levofloxacin's tendon and cognitive events. None hand-entered.
Verification
ruff check/formatclean,aimpoint validateok for all three environmentsuv run python scripts/build_pv_snapshot.py