{"data":{"kind":"file","path":"README.md","version_id":"x86by8eaucv0g86linbc7xyg","entry":{"name":"README.md","path":"README.md","is_directory":false,"size":8311,"modified_at":"2026-08-29T14:57:04.812000","content_hash":"907e02a9341dc60c01e3f787327ad48b0927cd15fd008aa6ccc64bc07a7f20f3"},"entries":[],"content":"# selective-verification-v1\n\n**An environment that rewards calibrated abstention, not just correctness.**\n\nAlmost every environment scores whether the model got the answer right. This one\nscores whether the model *knew* how likely it was to be right — using a strictly\nproper scoring rule, so honest confidence is the reward-maximising strategy and\nconfidence inflation is strictly dominated rather than merely discouraged.\n\n```bash\nprime env install kunaltilaganji/selective-verification-v1\n```\n\nThis is a **native `verifiers` v1 taskset**, not a v0 environment. It is loaded\nfrom config (`[env.taskset] id = \"selective-verification-v1\"`), which is what the\n`eval` entrypoint and `prime-rl` both do. The generic\n`verifiers.load_environment('...')` snippet the Hub prints on every listing is the\n**v0 legacy loader** and does not apply here — it looks for a module-level\n`load_environment` function, which a v1 taskset deliberately does not define.\n\n---\n\n## The task\n\nGiven an image and a claim about it, return a verdict and a confidence:\n\n```json\n{\"verdict\": \"SUPPORTED\" | \"REFUTED\" | \"ABSTAIN\", \"confidence\": 0.0}\n```\n\n* `SUPPORTED` — the claim is true of the image\n* `REFUTED` — the claim is false of the image\n* `ABSTAIN` — too uncertain to call it\n* `confidence` — the model's probability that **its own verdict** is correct.\n  Ignored when abstaining.\n\nThe system prompt states the scoring rule, the abstention payoff, and the\nimplied decision threshold explicitly. This is a calibration experiment, not a\ndeception experiment: the model is told exactly how it is being scored.\n\n## The reward\n\n| outcome | reward |\n|---|---|\n| answered | proper score on the reported confidence (see below) |\n| `ABSTAIN` | flat `abstain_reward` (default **0.80**) |\n| unparseable | `0.00` |\n\n**Brier** (default): `r = 1 - (p - y)²`, where `y = 1` if the verdict is correct.\n\n**Log** (optional): `r = 1 - ln(clip(p_correct, ε, 1)) / ln(ε)`, normalised to\n`[0, 1]`. Clipping keeps it bounded — an unclipped log score is unbounded below,\nand one confident error would swamp the advantage estimate for a whole RL batch.\n\n### Why the rule is proper\n\nLet `q` be the model's true belief that its verdict is correct and `p` what it\nreports. Under Brier:\n\n```\nE[r | q] = 1 - q(1-p)² - (1-q)p²\ndE/dp    = 2(q - p)     ->  unique maximum at p = q\n```\n\nThe log score maximises at `p = q` by the standard argument. Both are therefore\n**strictly proper**: expected reward is uniquely maximised by reporting your true\nposterior. Overstating confidence loses reward; so does understating it. The\npackage verifies this numerically rather than trusting the algebra — see\n`tests/test_scoring.py`, which searches a grid of reported confidences and\nasserts the argmax lands on the true belief.\n\n### Why `abstain_reward` defaults to 0.80\n\nThis constant *is* the decision threshold, and it is the most important knob in\nthe environment.\n\nAnswering honestly under Brier has expected value `1 - q(1-q)`, which is\n**minimised at 0.75** (at `q = 0.5`). So any abstention payoff at or below 0.75\nmakes abstaining **strictly dominated** — the optimal policy answers every single\ntime and the environment never rewards the behaviour it exists to study. This is\na real trap: an earlier draft of this environment used 0.55 and would have\nsilently measured nothing.\n\nFor `abstain_reward = a` in (0.75, 1), abstaining is optimal exactly when\n\n```\n1 - q(1-q) < a    <=>    q < q* = (1 + sqrt(4a - 3)) / 2\n```\n\nAt the default `a = 0.80` that gives **`q* = 0.7236`**: abstain when less than\nabout 72% sure. The environment refuses a dominated payoff at load time rather\nthan letting a run burn GPU hours on a reward that could never fire.\n\nThe two rules have different answer floors (0.75 for Brier, ≈0.9247 for the log\nscore at `ε = 1e-4`), so one numeric default cannot serve both. Leaving\n`abstain_reward` unset selects a per-rule default that places `q*` in the same\nplace under either.\n\n## Configuration\n\n| key | default | meaning |\n|---|---|---|\n| `split` | `adversarial` | `random` / `popular` / `adversarial` / `all` |\n| `partition` | `eval` | `train` / `eval` / `all` — see the leakage note below |\n| `num_tasks` | `100` | tasks to build (lazily) |\n| `seed` | `0` | shuffle seed |\n| `task.scoring_rule` | `brier` | `brier` or `log` |\n| `task.abstain_reward` | *(per-rule)* | flat payoff for `ABSTAIN` |\n\n```bash\nprime eval run <owner>/selective-verification-v1 \\\n  --env.taskset.split adversarial \\\n  --env.taskset.task.abstain-reward 0.85\n```\n\n## Metrics\n\nReported as per-trace indicators so aggregates are unambiguous: `correct` /\n`answered` is accuracy among answered items, `confidence_sum` / `answered` is\nmean confidence among them.\n\n`answered` · `abstained` · `malformed` · `correct` · `confidence_sum` ·\n`brier_sum` · `needed_repair`\n\n`malformed` is tracked apart from reward on purpose. RL learns the output format\nbefore it learns anything about calibration, and format-learning must not be\nread as calibration improving.\n\n## Data\n\n[POPE](https://github.com/RUCAIBox/POPE) (Li et al., 2023,\n[arXiv:2305.10355](https://arxiv.org/abs/2305.10355)), via the\n[`lmms-lab-encoder/POPE`](https://huggingface.co/datasets/lmms-lab-encoder/POPE)\nformatting. Object-presence probes over COCO `val2014` images, in three regimes\nthat differ only in how the *absent* object in a negative claim is chosen:\n`random` (uniform), `popular` (frequent objects), `adversarial` (objects that\nco-occur with what is actually present).\n\nStreamed from the Hub at runtime. **No images or annotations are redistributed\nin this package.** The HF dataset card declares no explicit license; the\nunderlying images are COCO `val2014`. Check both upstream sources before using\nthis in a context with licensing requirements.\n\n### The partition is by image, and that matters\n\nMeasured on the data: all three splits draw on the **same 500 COCO images**, and\n**97% of positive claims are shared across splits** (1457/1500 between `random`\nand `adversarial`). Only the negatives differ. `question_id` is also not globally\nunique — it collides 3000/3000 across splits.\n\nSo a row-level or `question_id`-level holdout leaks nearly every positive claim\ninto the eval set. This environment partitions on `image_source` with a sha256\nhash (not Python's `hash()`, which is salted per process and would silently\nreshuffle the \"held-out\" set between runs). Result: **train 7164 rows / 398\nimages, eval 1836 rows / 102 images**, zero overlap at image, (image, question),\nand task-id level, with both partitions staying exactly 50/50 class-balanced.\n\n**Train on `partition = \"train\"`. The `eval` partition is the held-out set.**\n\n## Baseline\n\n`Qwen/Qwen3.5-4B`, bf16, 200 tasks per split from the held-out `eval` partition.\nSampling is Qwen3.5's published instruct/non-thinking profile (`temperature 0.7,\ntop_p 0.8, presence_penalty 1.5`), thinking disabled.\n\n| split | accuracy | coverage | abstain | ECE | Brier | AURC | reward |\n|---|---:|---:|---:|---:|---:|---:|---:|\n| random | 0.949 | 0.980 | 0.005 | 0.015 | 0.048 | 0.041 | 0.937 |\n| popular | 0.938 | 0.975 | 0.005 | 0.017 | 0.057 | 0.053 | 0.923 |\n| adversarial | 0.906 | 0.960 | 0.010 | 0.052 | 0.086 | 0.071 | 0.886 |\n\nECE is 15-bin, equal-mass, and tie-aware. Miscalibration concentrates on the\nadversarial split — exactly where abstention should earn its keep.\n\nTwo things this baseline shows about the headroom, stated plainly because they\nbound what any post-training claim can mean:\n\n1. The model is only **mildly** overconfident (mean confidence ≈0.956 against\n   0.906–0.949 accuracy). This is not a broken model.\n2. Its sharpest weakness is **expressive, not directional**. Across 200\n   adversarial items it emits three distinct confidences — 0.946 (n=140,\n   accuracy 0.886), 0.980 (n=35, 0.943), 0.990 (n=17, 1.000). The ranking is\n   right; 70% of items simply receive the same number. And abstention, though\n   explained in the prompt with its payoff and threshold, is used on ~1% of items.\n\n## Citation\n\n```bibtex\n@misc{tilaganji2026selectiveverification,\n  title  = {selective-verification-v1: rewarding calibrated abstention with a proper scoring rule},\n  author = {Tilaganji, Kunal},\n  year   = {2026},\n  note   = {Prime Intellect Environments Hub}\n}\n```\n\nApache-2.0.\n","encoding":"utf-8","truncated":false,"total_bytes":8311},"status":null}