Repository navigation
feat(eval): add eval redteam to probe grading checks with planted answers #281
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
54 commits
Select commit
Hold shift + click to select a range
87e4ea4
feat(eval): red-team grading blocks against wrong, empty, hedged and …
napetrov 424afa6
fix(eval): redteam skips the attacks a grading block passes by design
napetrov 583ee2c
fix(redteam): inconclusive status, single-literal stuffing, hedge col…
napetrov 8c2ba2b
fix(redteam): negated checks no longer silence wrong, empty and hedge
napetrov c0e182c
fix(redteam): clear wrong answer of check values, stuff negated checks
napetrov 267a648
fix(redteam): skip the stuffed probe for a negated mode all match
napetrov 006a777
Merge branch 'main' of https://github.com/intel/dokimi into pr281-work
napetrov 0d731b0
fix(redteam): choose the planted wrong answer and the hedge probe by …
napetrov ec22242
fix(redteam): grade wrong, empty and hedge against the whole block, t…
napetrov 54c8893
fix(redteam): a set with a question that was not measured is inconclu…
napetrov 07d39a1
fix(redteam): bury aliases between decoys instead of listing them for…
napetrov 4624d63
fix(redteam): grade each question with its own block when an id repeats
napetrov 76a252c
feat(redteam): record the judge model and provider in the redteam.v1 …
napetrov 735c64c
refactor(redteam): read check values and build the judge ask through …
napetrov 6a09774
fix(redteam): name -o in the cut-violations line when no artifact is …
napetrov 27558b5
test(redteam): pin the canary of a whole-answer match and of a string…
napetrov 72d04ab
docs(redteam): list the negated mode all exclusion and say where nega…
napetrov 2359e74
test(redteam): run judge checks through run(ask=) and through the --j…
napetrov 90a4f4c
test(redteam): run an ungradable block through the command and pin th…
napetrov 7627b00
test(redteam): check the artifact of a blocked and an inconclusive co…
napetrov f667fd8
test(redteam): pin the bare stuffed answer of a whole-answer check wi…
napetrov d9093cd
docs(redteam): changelog fragment says what an inconclusive run is
napetrov 354041d
Address review: answer the review summaries and bot comments in their…
napetrov 24ea369
docs(redteam): refresh two stale comments on the wrong and stuffed at…
napetrov 180a81d
fix(redteam): a question set nested too deep to parse exits 2, not wi…
napetrov f76e543
fix(redteam): a block with an unrun judge or regex is unprobed, not a…
napetrov 93fa1e5
Merge remote-tracking branch 'intel/main' into pr281-1029
napetrov ed0950f
test(redteam): a regex past its timeout leaves the probe unscored, wi…
napetrov 1c60d0d
docs: keep the comment blocks this PR adds to two lines
napetrov 442e80d
fix(redteam): a json contains check's stuffed answer goes after a decoy
napetrov ecc5377
fix(redteam): type the decoy candidates as a tuple of any length (mypy)
napetrov b12ecba
test(redteam): pin the decoy filter, the two-decoy fallback and the a…
napetrov 77345de
docs(redteam): name the unmeasured case in the exit-code docstring
napetrov a76a9f6
Merge intel/main into feat/verifier-redteam
napetrov 808c7fb
docs(reference): regenerate cli-interface.json for dokimi eval redteam
napetrov c2ab619
fix(redteam): a numeric canary, a stuffed list the grader accepts, a …
napetrov a95644a
Merge remote-tracking branch 'intel/main' into tidy281-redteam
napetrov 53d142f
feat(redteam): use the canonical CLI flags and the route table
napetrov 198244e
fix(redteam): a negated value the matcher reads as another number is …
napetrov 904a1fa
docs(changelog): eval redteam writes its artifact with --out FILE
napetrov 52d4c5d
Merge remote-tracking branch 'intel/main' into tidy281-redteam
napetrov 03d6683
chore(cli): regenerate the CLI snapshot after merging main
napetrov c3f2452
docs(redteam): name --out, not -o, in the answer-formats table
napetrov f39ebfc
fix(runs): list redteam.v1 in the runs kinds table
napetrov 297e47a
fix(redteam): probe the stuffed answer only for a negated check
napetrov 0ad171b
test(redteam): assert the stuffed self-check directly, not through run
napetrov 81fcc17
fix(redteam): drop the stuffed probe, keep stuffed_for as a self-check
napetrov 6cb7781
Merge remote-tracking branch 'intel/main' into pr281-land1031
napetrov 69e3449
fix(redteam): address review on the exact canary, zero-weight checks …
napetrov 7441aaf
test(redteam): fold the _LITERAL import into the redteam import line
napetrov 004d6fe
fix(redteam): zero-weight checks do not count, fuzzy canary is bare, …
napetrov 29a65fe
fix(redteam): unsupported checks do not enable the rejection probes
napetrov d29b7cd
docs(redteam): the table names up to 20 unmeasured questions; --out k…
napetrov 2262188
Merge remote-tracking branch 'intel/main' into feat/verifier-redteam
napetrov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
3 changes: 3 additions & 0 deletions
3
dokimi/changelog.d/20261028_120100_napetrov_feat-verifier-redteam.md
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| ### Added | ||
|
|
||
| - **`eval redteam` checks that grading blocks reject wrong answers** — grades a planted wrong, an empty and a hedged answer against each question's `grading` block, and a canary right answer built from its one literal check. A wrong answer the grader accepts, or a canary it rejects, is a violation: the command prints pass rates, exits 1 and, with `--out FILE`, writes a `redteam.v1` artifact (it records the judge model and provider). A run in which a graded question was not measured (judge checks without `--judge`, a block of only negated checks) is `inconclusive` and also exits 1. Judge checks are unscored unless `--judge` is given, so the default run makes no model call. |
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
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
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # Copyright (C) 2026 Intel Corporation | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| """``eval redteam``: check that a question set's grading rejects the answers it should. | ||
|
|
||
| Reads a questions set (with ``grading`` blocks), grades synthetic attacks against it and prints | ||
| the pass rates. Exits 1 when any attack is accepted, a canary is rejected, a graded question was not | ||
| measured, or nothing was graded (``inconclusive``); exits 2 on an unreadable input, a malformed | ||
| ``--judge`` or an unwritable ``--out``. Judge checks are not scored unless ``--judge PROVIDER/MODEL`` | ||
| is given, so the default run makes no model call. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import argparse | ||
| import sys | ||
|
|
||
|
|
||
| def _ask(args: argparse.Namespace): | ||
| if not args.judge: | ||
| return None | ||
| from dokimi.eval.judge import judge_ask | ||
|
|
||
| provider, model = args.judge | ||
| return judge_ask(model, provider) | ||
|
|
||
|
|
||
| def _judge_ref(value: str) -> tuple[str, str]: | ||
| from dokimi.eval.judge import JUDGE_PROVIDERS | ||
|
|
||
| provider, _, model = value.partition("/") | ||
| if provider not in JUDGE_PROVIDERS or not model.strip(): | ||
| raise argparse.ArgumentTypeError( | ||
| f"expected PROVIDER/MODEL with PROVIDER one of {', '.join(JUDGE_PROVIDERS)}, got {value!r}") | ||
| return provider, model.strip() | ||
|
|
||
|
|
||
| def cmd_eval_redteam(args: argparse.Namespace) -> None: | ||
| from dokimi.artifacts import save_artifact | ||
| from dokimi.eval.redteam import format_table, run | ||
| from dokimi.questions.artifact import load_questions | ||
|
|
||
| try: | ||
| questions = load_questions(args.questions).artifact.get("questions") or [] | ||
| result = run(questions, ask=_ask(args)) | ||
| except (OSError, ValueError, RecursionError) as e: # RecursionError: nested too deep | ||
| print(f"Error: {e}", file=sys.stderr) | ||
| sys.exit(2) | ||
| result["questions_path"] = str(args.questions) | ||
| result["judge_model"] = args.judge[1] if args.judge else None | ||
| result["judge_provider"] = args.judge[0] if args.judge else None | ||
| print(format_table(result, output=args.out)) | ||
| if args.out: | ||
| try: | ||
| save_artifact("redteam", result, args.out) | ||
| except (OSError, ValueError) as e: | ||
| print(f"Error: {e}", file=sys.stderr) | ||
| sys.exit(2) | ||
| print(f"Wrote redteam artifact to {args.out}") | ||
| if result["status"] != "pass": | ||
| sys.exit(1) | ||
|
|
||
|
|
||
| def register_eval(eval_sub) -> None: | ||
| r = eval_sub.add_parser( | ||
| "redteam", | ||
| help="Check grading blocks reject wrong, empty and hedged answers and accept a canary") | ||
| r.add_argument("questions", help="questions JSON with grading blocks (from `questions import`)") | ||
| r.add_argument("--judge", metavar="PROVIDER/MODEL", type=_judge_ref, default=None, | ||
| help="Grade judge checks with this judge model (model calls); default leaves them unscored") | ||
| r.add_argument("--out", metavar="FILE", default=None, help="redteam.v1 JSON to write") | ||
| r.set_defaults(func=cmd_eval_redteam) | ||
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
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Must-fix: the changelog advertises
-o, but this parser registers only--out, and shared CLI parsing does not add an alias.dokimi eval redteam questions.json -o redteam.jsontherefore exits 2 with an unrecognized-argument error instead of writing the artifact. Register-oas an alias (and test that invocation), or consistently document only--out. The same mismatch appears in the added answer-formats documentation.Suggestion:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not adding
-o. The parser registers--outonly, and the flag registry (dokimi/cli_flags.py) makes--outthe canonical output flag and bans-o, so an alias would fail the flag ratchet. The changelog already says--out FILE(b9f0980), and the docs match.