feat: judge failure handling - #2384
Conversation
719f8ce to
66bb6a5
Compare
|
/ok to test 66bb6a5 |
|
/claude review |
|
SHIP — clean, well-scoped, well-tested. This PR decomposes proof_judge's zero-rewards into a named Reward math is unchanged. The refactor Request contract — Response schema — Tests — good coverage: parametrized cases assert reward + One NOTE inline re: the "422 if empty" comment being slightly inaccurate ( |
|
|
||
| class ProofWithJudgeVerifyRequest(BaseVerifyRequest): | ||
| problem: str = "" | ||
| # Force a 422 error if the problem is empty. |
There was a problem hiding this comment.
NOTE: The comment says "Force a 422 error if the problem is empty," but problem: str only rejects a missing field — an empty string "" still validates. If you actually want to reject empty problems, use problem: str = Field(min_length=1). Otherwise reword the comment to "if the problem is missing." Not a correctness issue given all in-repo datasets supply a non-empty problem.
|
/ok to test 7307b03 |
|
/claude review |
|
SHIP — no reliability concerns. Reviewed
No async/HTTP-client, public-API, dependency, or config-convention issues. Reward aggregation math is untouched. |
There was a problem hiding this comment.
I think this is not needed anymore, now that we set problem: str = Field(min_length=1)
There was a problem hiding this comment.
Oops. I knee-jerk addressed the claude review without thinking. Fixed!
|
This PR looks correct in a sense that it will do its job without breaking anything else. However, the previous PR #2113 introduced a unification on how we handle judge failures, so making changes just to one harness does not seem right. As for now, the unified approach assumes that unparsable responses are not judge failures. This means that the judge had a fair chance of giving a verdict (i.e. we received a response from the API) and it just happened to be not what we expected. It was not considered a judge failure because judge failures currently mean the call itself failed (eg. due to rate limiting, auth issues, timeouts, HTTP errors) so we never got a verdict at all. We could change this approach to include unparsable responses as judge failures but this change should be applied uniformly, to other benchmarks as well. |
I agree in bulk, and I think we're on the same page.
I don't consider this PR changing that contract. The point of this PR is just to surface The idea is that the training backend can continue to receive 200 responses in the same cases from Gym, but has an extra field they can use to make judgment calls. In this case, my team is treating repeated
I 100% agree; I wasn't familiar enough with the codebase to realize this should/could be done. I've put a draft PR at #2552; do you think this is sufficient? I actually have this exact Also, the reason I ended up doing things this way is because |
ee1a983 to
6899c52
Compare
6899c52 to
4c2677d
Compare
Signed-off-by: Teodor-Dumitru Ene <teodord.ene@gmail.com>
Signed-off-by: Teodor-Dumitru Ene <teodord.ene@gmail.com>
Signed-off-by: Teodor-Dumitru Ene <teodord.ene@gmail.com>
4c2677d to
569a6cf
Compare
Done in #2552; merged. |
| # A format reason means the policy failed to follow the format and received an automatic 0. | ||
| # "judge_unparseable" means that the judge itself failed to produce a parseable score. | ||
| # Distinguishing between these cases is needed for judge error-proofing. | ||
| failure_reason: Optional[str] = None |
A zero reward from a judge model has three distinct causes that are currently indistinguishable:
The middle case leads to severe training run degradation, should the judge model become corrupted - which is not uncommon.
This PR merely surfaces the failure reason, emitting
judge_unparseableif the problem is with the judge, allowing upstream training infrastructure to decide how to best handle such judge degradation.