Skip to content

feat(verifier): six check kinds for tasks that must be retrieved, computed or proved - #324

Open
Wings-Of-Disaster wants to merge 1 commit into
modelscope:mainfrom
Wings-Of-Disaster:pr2-check-kinds
Open

Wings-Of-Disaster wants to merge 1 commit into
modelscope:mainfrom
Wings-Of-Disaster:pr2-check-kinds

Conversation

@Wings-Of-Disaster

Copy link
Copy Markdown
Collaborator

PR type

  • Bug Fix
  • New Feature
  • Document Updates
  • More Models or Datasets Support

PR information

Add six check kinds to twinkle_agentic.verifier.result_check, expanding _KINDS from 10 to 16.

The new checks support held-out validation, exact and numeric answers, verifier-executed SQL, retrieval receipts, and compiler-checked Lean proofs.

Scope: 2 files, +639/−2 lines, 51 new tests. The implementation introduces no new imports and can be reviewed and merged independently of world or profile changes.

Why this is needed

The existing ten kinds grade a workspace and an answer string. Agentic tasks also need checks that can establish whether:

  • Validation was held out from the task proposer.
  • A claimed value agrees with a query executed by the verifier.
  • A cited source was actually retrieved during the episode.

They also need precise answer matching and a compiler verdict for proof tasks. The six additions cover these cases.

New check kinds

Kind What it checks Why it is useful
hidden_python Runs a Python check withheld from the proposer. Supports validation the proposer cannot tailor its task around.
answer_one_of Requires the answer to equal a member of an exact set. Avoids substring matches that accept both “the answer is 42” and “the answer is not 42.”
answer_number Requires one unambiguous finite number within a tolerance, with an optional required unit. Accepts equivalent numeric forms such as 3 and 3.0, while detecting incorrect units.
sql_query Executes the query in the verifier and compares the resulting rows. Checks the underlying data rather than accepting the model's stated result.
web_receipt Requires every cited URL to appear in retrieval receipts for the episode. Distinguishes a retrieved source from a plausible but unserved citation.
lean Compiles the submitted proof with lake env lean and rejects disallowed proof shortcuts. Uses the compiler to validate the proof rather than matching proof-like text.

Implementation and compatibility

Reuse the existing Python execution path

hidden_python shares the existing shell/Python execution path. The dispatch change selects the interpreter explicitly:

if kind in ('shell', 'python', 'hidden_python'):
    interpreter = 'shell' if kind == 'shell' else 'python'

For the existing shell and python kinds, interpreter == kind, preserving their behavior. These two lines are the only modification to existing code; the remaining implementation is additive.

Consume retrieval receipts without a world dependency

web_receipt receives receipts through CheckContext. It does not import or depend on a particular world implementation, and its tests supply fabricated receipts.

In production, this check relies on receipts recorded by the retrieval provider when it serves a result. Policy-authored claims are not evidence of retrieval. A failed fetch records no URL and therefore cannot satisfy a citation check.

This establishes that a cited URL was served during the episode; it does not, by itself, establish that the source supports the answer.

Compile Lean proofs and reject disallowed shortcuts

The lean kind runs lake env lean and also refuses sorry and native_decide. Compilation alone is insufficient under this check's rules: a submitted proof must pass both the compiler and the shortcut restrictions.

Actionable failure messages

Failures explain what needs to change rather than returning only “did not match.”

Kind Diagnostic detail
sql_query Row counts and the first three rows of both expected and actual results.
answer_number Distinguishes a non-number, a non-finite value, an incorrect unit, and a value outside tolerance.
web_receipt Identifies cited URLs that were not served.

These messages help a proposer respond to rejected checks and make evaluation logs easier to diagnose.

Verification

The following results are reported for the PR and the clean upstream baseline. No training results are included; this change is evaluated through verifier tests.

pre-commit run --all-files

pytest tests/twinkle_agentic tests/processor tests/utils tests/docs \
       tests/server/static tests/cli tests/advantage tests/metric
Check Result
Pre-commit All hooks passed
Clean main, same test selection 391 passed, 9 skipped
PR, same test selection 442 passed, 9 skipped, 0 failed
Test delta 51 additional passing tests; no additional skips

Five files matching test_async_rl_* or named test_vllm_sampler_tq_generation.py were deselected. They fail collection identically on clean main with ModuleNotFoundError: No module named 'transfer_queue'. The reported results cover the stated selection, not the entire repository test suite.

Scope and dependencies

result_check.py introduces no new imports. Tests use upstream's LocalEnv and fabricated receipts, so neither the implementation nor its tests require the world or profile additions.

The PR can be reviewed and merged on its own. Deployment still needs to supply the resources used by a selected check, including retrieval receipts for web_receipt and the Lean toolchain for lean.

The ten existing kinds grade a workspace and an answer string. That is enough for
a task whose artefact is a file, and not enough for the three things an agentic run
most needs to be able to ask of a task: was the check written by someone other than
its author, was the value actually queried rather than asserted, and was the source
actually read.

hidden_python -- a python check the proposer never saw. A proposer that writes its
own check script writes the task around it, which is an open-book exam. Grading
against a script held back restores the distinction between a task that was solved
and one that was authored to be solvable. Shares the shell/python execution path:
the two existing kinds pass `kind` straight through as the interpreter, so this
adds one name to the tuple and derives the interpreter, leaving both unchanged.

answer_one_of -- the answer must equal one of an exact set. answer_contains is too
loose for a multiple-valued question: "the answer is 42" and "the answer is not 42"
both contain 42.

answer_number -- the answer is one unambiguous finite number within a tolerance,
with an optional required unit. Comparing numbers as strings fails 3.0 against 3,
and a number with the wrong unit is a wrong answer that reads as a right one. The
regex rejects "about 5", "5 or 6" and "5m" unless the unit was asked for.

sql_query -- the verifier runs the query itself and compares rows. A task that asks
for a count and accepts the model's stated count is a task about handwriting.
Ordered and unordered comparison are both supported, and the failure message shows
the row counts and the first three rows of each side, because "did not match" is
not actionable.

web_receipt -- every url the answer cites must appear in what the search tools
actually served to this episode. This is the check that makes a citation mean
something, and it only works because the receipts are written by the world when it
answers, not by the policy when it claims. A policy that invents a url has nothing
to match against. Receipts arrive on CheckContext, so the kind is testable with
fabricated ones and needs no world.

lean -- compile the submitted proof with `lake env lean` and let the compiler be
the verdict. Lean decides what is true, and the same file that proves a theorem
here proves it for anyone; a regex over `:= by ring` would be a guess. The check
also refuses the escape hatches, since a proof that compiles by `sorry` or by
`native_decide` proves nothing.

Two existing lines changed, both to generalise one branch. For the kinds that
already existed the derived interpreter equals the kind, so behaviour is unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant