API Reference#
The public API is exposed at the top of the llm_verifier package:
from llm_verifier import (
select, compare, track, ProgressTracker,
VerifierResult, ProgressResult,
MissingAPIKeyError, GRANULARITY, DEFAULT_MODEL, load_dotenv,
)
select#
def select(
problem: str,
candidates: Sequence[str],
*,
criteria: CriteriaArg,
images: Optional[ImagesArg] = None,
ground_truth_note: Optional[str] = None,
n_evaluations: int = 8,
pivots: int = 2,
seed: int = 0,
max_workers: int = 50,
model: str = DEFAULT_MODEL,
cache: Optional[str] = None,
progress: Optional[bool] = None,
on_error: str = "tie",
client: Any = None,
) -> VerifierResult
Select the best of N agent trajectories for a single task.
Scores directed pairs of trajectories with the fine-grained reward and aggregates them with a Probabilistic Pivot Tournament (PPT), so the cost is O(Nk) verifier comparisons rather than the O(N²) of a full round-robin.
Identical inputs with the same seed run the identical tournament.
Arguments
problem: the task description shown to the verifier.candidates: list of N agent trajectories (strings) to rank.criteria: a bundled benchmark name (e.g."swe_bench"), a path to a*.mdcriteria file, a{name: description}dict, or a list of strings /{"id", "name", "description"}dicts.images: task-context image(s) the verifier sees with every comparison — a single image or a list (ImagesArg); requires a multimodal verifier model.ground_truth_note: optional note the verifier always sees; defaults to the note parsed from the prompt file (or empty).n_evaluations: repeated verifications K per criterion.pivots: number of pivots k in the tournament. Keep k small relative tolen(candidates)— cost grows as O(Nk), and k ≥ N degenerates to a full round-robin (k is clamped to N).seed: seed for the random ring pass.max_workers: concurrency for verifier calls.model: verifier model name (defaultgemini-2.5-flash).cache: optional path to a JSON score cache. Re-running with the same cache re-scores only the comparisons not seen before.progress: show a progress bar / log lines. Default (None) shows progress only when stderr is a TTY.on_error:"tie"scores a failed verifier call 0.5/0.5 for this run (never persisted to the cache);"raise"re-raises it.client: a pre-builtopenaiorgoogle-genaiclient (optional); by default the backend is picked from the environment (OPENAI_BASE_URL, elseVERTEX_API_KEY) and must expose token-level logprobs.
Returns a VerifierResult whose .index / .best is the chosen trajectory and .ranking orders all trajectories best-first.
Raises MissingAPIKeyError if there are no credentials and no client given (only when uncached comparisons actually need scoring); ValueError on an empty trajectory list.
compare#
def compare(
problem: str,
trace_a: str,
trace_b: str,
*,
criteria: CriteriaArg,
images: Optional[ImagesArg] = None,
ground_truth_note: Optional[str] = None,
n_evaluations: int = 1,
max_workers: int = 8,
model: str = DEFAULT_MODEL,
client: Any = None,
) -> Tuple[float, float]
Fine-grained rewards (R_A, R_B) in [0, 1] for one directed comparison.
The verifier sees trace_a in slot A and trace_b in slot B; rewards are averaged over all criteria and n_evaluations repeats.
images accepts the same forms as select’s (one image or a list — paths, URLs, or bytes) and is attached as task context.
This is the raw pairwise reward select is built on — note the single directed call does not cancel slot bias the way select’s ring pass does.
A failed verifier call raises (there is no tie fallback here).
track#
def track(
problem: str,
steps: Sequence[str],
*,
images: Optional[ImagesArg] = None,
checkpoint_steps: Optional[Sequence[int]] = None,
n_evaluations: int = 1,
max_workers: int = 8,
model: str = DEFAULT_MODEL,
client: Any = None,
) -> ProgressResult
Score an agent trajectory’s progress after each step.
One verifier call scores every checkpoint (repeated n_evaluations times and averaged), so cost is O(K) calls regardless of trajectory length.
Arguments
problem: the task instruction shown to the verifier.steps: the agent’s steps, one string per step (action + observed output). Truncate very long observations yourself if needed.images: task-context image(s) attached to every scoring call (ImagesArg); for per-step frames, useProgressTrackerand pass images to eachupdate.checkpoint_steps: 1-indexed step numbers to score. Defaults to the interior steps2 .. T-1(the first and last step anchor the scale), or every step for trajectories with fewer than 3 steps.n_evaluations: independent repeats K; the returned curve is their mean.max_workers: concurrency for the K repeats.
Returns a ProgressResult — .steps, .scores (the progress curve in [0, 1]), .per_rep_scores, .final.
ProgressTracker#
class ProgressTracker:
def __init__(
self,
problem: str,
*,
images: Optional[ImagesArg] = None,
n_evaluations: int = 1,
max_workers: int = 8,
model: str = DEFAULT_MODEL,
client: Any = None,
) -> None
Online progress tracking for a still-running agent.
Feed steps as the agent produces them; each update scores the trajectory prefix accumulated so far, so the verifier structurally cannot be influenced by future steps.
Cost: one verifier call per repeat per update — a T-step run costs T × n_evaluations calls, versus n_evaluations for offline track.
Raises MissingAPIKeyError at construction if no credentials are found and no client is given.
Pass images at construction for task-context image(s) — e.g. a goal image or reference screenshot.
Methods and attributes
update(step: str, images=None) -> float: append the agent’s latest step and return the progress score of the trajectory so far (mean overn_evaluationsrepeats).images(one image or a list — e.g. a camera frame after this step) is attached to this step: the step text gets an[Image i attached]marker and the image stays part of the trajectory for all later updates.result() -> ProgressResult: the curve so far, same shape astrack()’s.steps/scores: the checkpoint indices and scores accumulated so far.
VerifierResult#
@dataclass
class VerifierResult:
index: int # index of the winning trajectory in the input list
best: str # the winning trajectory itself
scores: list[float] # per-trajectory mean preference (w_i / c_i)
n_comparisons: int # number of directed verifier comparisons run
criteria: list[str] # the criterion ids used for scoring
@property
def ranking(self) -> list[int]:
"""Trajectory indices sorted best-first by tournament score."""
ProgressResult#
@dataclass
class ProgressResult:
steps: list[int] # checkpoint step numbers
scores: list[float] # mean progress per checkpoint, in [0, 1]
per_rep_scores: list[list[float|None]] # rows are repeats, columns are steps
@property
def final(self) -> float:
"""Progress score at the last checkpoint."""
Constants and helpers#
ImagesArg— the type of everyimagesargument: one image or a sequence, each a local file path, an http(s) URL, or raw image bytes; attached after the text prompt, in order. See Multi-Modal Supports.DEFAULT_MODEL = "gemini-2.5-flash"— the default verifier model.GRANULARITY = 20— the number of score tokens G (the letter scale A–T).load_dotenv(root_dir=None)— loadVERTEX_API_KEY/OPENAI_BASE_URL(and friends) from a.envfile.MissingAPIKeyError— raised when a verifier call needs a backend and neitherOPENAI_BASE_URLnorVERTEX_API_KEYis configured.
Command line#
python -m llm_verifier <criteria.md | benchmark_name> # preview criteria (no API key needed)
python run.py [benchmark] [--pivots K] [--n-evaluations K] [--seed S] [--max-workers W]