feat: deterministic assertions (is_json, json_schema, contains, regex) that skip the LLM judge on failure - #49
Open
brainsparker wants to merge 1 commit into
Open
Conversation
Adds an assert block to golden-set test cases with six zero-token checks: is_json, json_schema, contains, not_contains, regex, starts_with. A failed assertion marks the case failed and skips the LLM judge call. Assertion outcomes flow into results, JUnit XML (AssertionFailed failures), and the --fail-under quality gate. Includes docs, an example golden set, and 20 new tests.
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 does
Adds deterministic assertions to golden-set test cases. Each case can now declare an
assertblock of zero-token checks that run locally before the LLM judge:is_jsonjson_schemacontains/not_containsregexre.searchfinds a matchstarts_withBehavior:
<failure type="AssertionFailed">, so CI fails the build.--fail-undergate now fails on any assertion failure regardless of judge scores, and an assertion-only golden set (no judge scores at all) passes the gate when every assertion passes.assertblock behave exactly as before. No breaking changes.New module:
promptlens/judges/assertions.py. New dependency:jsonschema(pure Python). Example golden set:examples/golden_sets/structured_output.yaml.Why now (market rationale)
json_schemais the production default). With grammar-constrained decoding, "is it valid JSON" is guaranteed at the token level, and the eval question shifts to "are the values right", which needs schema and value assertions, not an LLM judge. Sources: https://janeer.com/guides/openai-vs-anthropic-structured-outputs/ , https://devtoollab.com/blog/llm-structured-outputs-guide-2026is-jsonplus JSON Schema assertions are its headline CI feature, and its Jan 2026 release added per-test structured output config. Sources: https://www.promptfoo.dev/docs/guides/evaluate-json/ , https://www.promptfoo.dev/docs/releases/jsonandre, plus the pure-Pythonjsonschemapackage.Runner-up opportunities considered today and passed on: A2A
message/streamSSE support in youagent (strong, likely a future pick) and a GitHub Copilot export target in you.md.Implementation notes and test status
Assertionmodel validates types and value shapes at load time, so a bad golden set fails fast with a clear message.judge.evaluate.EvaluationResult.assertion_resultsserializes into JSON/CSV/HTML exports automatically; JUnit adds an explicit failure element and anassertions: N/M passedline in system-out.tests/test_assertions.py(model validation, every check type, YAMLassertkey parsing, runner judge-skip integration with mocks, JUnit mapping, gate behavior). Full suite: 113 passed locally on Python 3.9.