Skip to content

Mark grader content-filter refusals as unscored #10

Merged
iphan merged 2 commits into
mainfrom
scorer_refusal
Jun 8, 2026
Merged

Mark grader content-filter refusals as unscored #10
iphan merged 2 commits into
mainfrom
scorer_refusal

Conversation

@iphan

@iphan iphan commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

This PR contains

Description

  • Mark grader content-filter refusals as unscored instead of INCORRECT
  • Lazy load the EdisonScientific/labbench2 dependencies

Validation

Automated checks

make check
make test

Manual checks

  • Run eval with a tag using the semantic scorer with Sonnet as the judge
  • Check that some sample without scorer output are correctly marked as unscored
image

iphan added 2 commits June 5, 2026 17:49
Anthropic's content filter can non-deterministically block the LLM judge,
returning stop_reason=content_filter with an empty completion. That response
previously fell through to a silent INCORRECT, turning a transient grader
failure into a false negative.

Detect refusals (content_filter or empty completion), retry up to
MAX_GRADER_ATTEMPTS, and on persistent failure return Score.unscored so the
sample is excluded from accuracy/stderr and recorded as unscored rather than
counted wrong. Applies to all judge-graded tags via _judge_score.
@iphan iphan changed the title Scorer refusal Mark grader content-filter refusals as unscored Jun 6, 2026
A ``content_filter`` stop reason or an empty completion means moderation
blocked the grader (or it returned nothing), not that the answer is wrong.
"""
if result.stop_reason == "content_filter":

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ItsTania I was able to repro the issue that you described here with Sonnet as the grader. It turned out this was due to content filtering.
I chose to exclude the sample from the results in this case where the grader model refuses to answer.

thanks again for pointing out this issue

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats so interesting that the content filter blocked the grading stage but not the actual question answering stage ahah

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the different provider have different content filters: the model under test is gpt 5.2, whereas the judge is Sonnet 4.5

@iphan
iphan requested a review from ItsTania June 6, 2026 01:00
@iphan
iphan marked this pull request as ready for review June 6, 2026 01:00

@ItsTania ItsTania left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - the comments below are just a record of my thoughts (esp as I'm thinking about the question of 'what is the best way to deal with errors not to do with the solver" which is relevant to a few evals rn)

import textwrap


def test_package_imports_without_optional_labbench2_dependency() -> None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not relevant to this PR - but I wonder if this optional dependency is a weakness of the template... it seems like it added more confusion than necessary for most people who would only implement one eval per repo...

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is only a single eval in the repo, users can make the deps required. Just add them in the main dependencies list here.
I put LB2's deps as optional to test the template setup for the multi-eval per repo case

calls = _patch_grader(
monkeypatch,
[
("", "content_filter"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also try and handle other refusal patterns (maybe in a future PR?)

https://developers.openai.com/api/docs/guides/structured-outputs

Suggested change
("", "content_filter"),
("", "content_filter"), # the anthropic API does model refusal by ...

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thing that could be added to Inspect AI as to support LLM grader
(handling refusals)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created this issue to track it: #11

name="evaluation_result", json_schema=json_schema(EvaluationResult)
)

async def call_grader_with_retry(prompt: str) -> ModelOutput | None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the first time I've seen the Score.unscored option - v cool
I like that it enables future scoring and really highlights that the issue is with the scoring (and make re-scoring easier https://inspect.aisi.org.uk/scoring-workflow.html)

The pattern I previously knew of is to raise an error and rely on --retry-on-error (https://inspect.aisi.org.uk/options.html#errors-and-limits). The benefit is the retry is built in, but the ^ re-scoring options aren't (get logged as errors after x retries))

I wonder if there is a neat fix combining the two in inspect ai! Esp as LLM judges are getting more popular as scoring options.

@iphan
iphan merged commit 51ebf59 into main Jun 8, 2026
18 checks passed
@iphan
iphan deleted the scorer_refusal branch June 8, 2026 17:59
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.

2 participants