inspect_ai.scorer
Scorers
match
Scorer which matches text or a number.
@scorer(metrics=[accuracy(), stderr()])
def match(
location: Literal["begin", "end", "any", "exact"] = "end",
*,
ignore_case: bool = True,
numeric: bool = False,
) -> ScorerlocationLiteral['begin', 'end', 'any', 'exact']-
Location to match at. “any” matches anywhere in the output; “exact” requires the output be exactly equal to the target (module whitespace, etc.)
ignore_casebool-
Do case insensitive comparison.
numericbool-
Is this a numeric match? When True, currency symbols (
$,€,£), thousands separators (,), and formatting markers (*,_) are stripped before numbers are normalized and compared. The percent sign is not stripped:60%is ambiguous (it could mean60or0.6), so an answer of60%will not match a numeric target of60. To accept a percentage-formatted answer, pass both forms as targets, e.g.Target(["60", "60%"]), where the non-numeric"60%"is matched as a string.
includes
Check whether the specified text is included in the model output.
@scorer(metrics=[accuracy(), stderr()])
def includes(ignore_case: bool = True) -> Scorerignore_casebool-
Use a case insensitive comparison.
pattern
Scorer which extracts the model answer using a regex.
Note that at least one regex group is required to match against the target.
The regex can have a single capture group or multiple groups. In the case of multiple groups, the scorer can be configured to match either one or all of the extracted groups
@scorer(metrics=[accuracy(), stderr()])
def pattern(pattern: str, ignore_case: bool = True, match_all: bool = False) -> Scorerpatternstr-
Regular expression for extracting the answer from model output.
ignore_casebool-
Ignore case when comparing the extract answer to the targets. (Default: True)
match_allbool-
With multiple captures, do all captured values need to match the target? (Default: False)
answer
Scorer for model output that preceded answers with ANSWER:.
Some solvers including multiple_choice solicit answers from the model prefaced with “ANSWER:”. This scorer extracts answers of this form for comparison with the target.
Note that you must specify a type for the answer scorer.
@scorer(metrics=[accuracy(), stderr()])
def answer(pattern: Literal["letter", "word", "line"]) -> ScorerpatternLiteral['letter', 'word', 'line']-
Type of answer to extract. “letter” is used with multiple choice and extracts a single letter; “word” will extract the next word (often used for yes/no answers); “line” will take the rest of the line (used for more more complex answers that may have embedded spaces). Note that when using “line” your prompt should instruct the model to answer with a separate line at the end.
choice
Scorer for multiple choice answers, required by the multiple_choice solver.
This assumes that the model was called using a template ordered with letters corresponding to the answers, so something like:
What is the capital of France?
A) Paris
B) Berlin
C) London
The target for the dataset will then have a letter corresponding to the correct answer, e.g. the Target would be "A" for the above question. If multiple choices are correct, the Target can be an array of these letters.
@scorer(metrics=[accuracy(), stderr()])
def choice() -> Scorermath
Create a mathematical expression scorer.
Extracts a bounded final answer from model output, parses it without evaluating Python, and compares it to each target under bounded symbolic work.
@scorer(metrics=[accuracy(), stderr()])
def math(*, timeout: float = _DEFAULT_TIMEOUT_SECONDS) -> Scorertimeoutfloat-
Active-work budget in seconds for each parsing phase (target and answer). This is wall-clock time in the host process and so is sensitive to concurrent load; parsing that exceeds it is treated as an incorrect answer (or an unscored target). The first call gets a larger cold-start allowance to absorb one-time imports.
f1
Scorer which produces an F1 score
Computes the F1 score for the answer (which balances recall precision by taking the harmonic mean between recall and precision).
@scorer(metrics=[mean(), stderr()])
def f1(
answer_fn: Callable[[str], str] | None = None, stop_words: list[str] | None = None
) -> Scoreranswer_fnCallable[[str], str] | None-
Custom function to extract the answer from the completion (defaults to using the completion).
stop_wordslist[str] | None-
Stop words to include in answer tokenization.
exact
Scorer which produces an exact match score
Normalizes the text of the answer and target(s) and performs an exact matching comparison of the text. This scorer will return CORRECT when the answer is an exact match to one or more targets.
@scorer(metrics=[mean(), stderr()])
def exact() -> Scorermodel_graded_qa
Score a question/answer task using a model.
@scorer(metrics=[accuracy(), stderr()])
def model_graded_qa(
template: str | None = None,
instructions: str | None = None,
grade_pattern: str | None = None,
include_history: bool | Callable[[TaskState], str] = False,
partial_credit: bool = False,
model: list[str | Model] | str | Model | None = None,
model_role: str | ModelRole | None = "grader",
) -> Scorertemplatestr | None-
Template for grading prompt. This template has four variables: -
question,criterion,answer, andinstructions(which is fed from theinstructionsparameter). Variables from samplemetadataare also available in the template. instructionsstr | None-
Grading instructions. This should include a prompt for the model to answer (e.g. with with chain of thought reasoning) in a way that matches the specified
grade_pattern, for example, the defaultgrade_patternlooks for one of GRADE: C, GRADE: P, or GRADE: I. grade_patternstr | None-
Regex to extract the grade from the model response. Defaults to looking for e.g. GRADE: C The regex should have a single capture group that extracts exactly the letter C, P, I.
include_historybool | Callable[[TaskState], str]-
Whether to include the full chat history in the presented question. Defaults to
False, which presents only the original sample input. Optionally provide a function to customise how the chat history is presented. partial_creditbool-
Whether to allow for “partial” credit for answers (by default assigned a score of 0.5). Defaults to
False. Only used with the defaultinstructions(as custom instructions provide their own prompts for grades). Under those defaults the grader is offered C/I, or C/P/I when this isTrue, and its finalGRADE:verdict is validated against that set: a verdict outside it (aPthat was never offered, or any other letter) is a grade-parse failure and leaves the sample unscored rather than being scored or silently falling back to an earlier grade mentioned in the reasoning. Custominstructionsor an explicitgrade_patternare authoritative and keep every grade they match. modellist[str | Model] | str | Model | None-
Model or models to use for grading. If a list is provided, each model grades independently and the final grade is computed by majority vote. When this parameter is provided, it takes precedence over
model_role. model_rolestr | ModelRole | None-
Named model role to use for grading (default: “grader”). Pass
ModelRole(name, required=True)to require a model to be bound to the role. Ignored ifmodelis provided. If specified and a model is bound to this role (e.g. via themodel_rolesargument to eval()), that model is used. If no role-bound model is available and the role is not required, the model being evaluated (the default model) is used.
model_graded_fact
Score a question/answer task with a fact response using a model.
@scorer(metrics=[accuracy(), stderr()])
def model_graded_fact(
template: str | None = None,
instructions: str | None = None,
grade_pattern: str | None = None,
include_history: bool | Callable[[TaskState], str] = False,
partial_credit: bool = False,
model: list[str | Model] | str | Model | None = None,
model_role: str | ModelRole | None = "grader",
) -> Scorertemplatestr | None-
Template for grading prompt. This template uses four variables:
question,criterion,answer, andinstructions(which is fed from theinstructionsparameter). Variables from samplemetadataare also available in the template. instructionsstr | None-
Grading instructions. This should include a prompt for the model to answer (e.g. with with chain of thought reasoning) in a way that matches the specified
grade_pattern, for example, the defaultgrade_patternlooks for one of GRADE: C, GRADE: P, or GRADE: I). grade_patternstr | None-
Regex to extract the grade from the model response. Defaults to looking for e.g. GRADE: C The regex should have a single capture group that extracts exactly the letter C, P, or I.
include_historybool | Callable[[TaskState], str]-
Whether to include the full chat history in the presented question. Defaults to
False, which presents only the original sample input. Optionally provide a function to customise how the chat history is presented. partial_creditbool-
Whether to allow for “partial” credit for answers (by default assigned a score of 0.5). Defaults to
False. Only used with the defaultinstructions(as custom instructions provide their own prompts for grades). Under those defaults the grader is offered C/I, or C/P/I when this isTrue, and its finalGRADE:verdict is validated against that set: a verdict outside it (aPthat was never offered, or any other letter) is a grade-parse failure and leaves the sample unscored rather than being scored or silently falling back to an earlier grade mentioned in the reasoning. Custominstructionsor an explicitgrade_patternare authoritative and keep every grade they match. modellist[str | Model] | str | Model | None-
Model or models to use for grading. If a list is provided, each model grades independently and the final grade is computed by majority vote. When this parameter is provided, it takes precedence over
model_role. model_rolestr | ModelRole | None-
Named model role to use for grading (default: “grader”). Pass
ModelRole(name, required=True)to require a model to be bound to the role. Ignored ifmodelis provided. If specified and a model is bound to this role (e.g. via themodel_rolesargument to eval()), that model is used. If no role-bound model is available and the role is not required, the model being evaluated (the default model) is used.
perplexity
Score samples by computing per-token negative log-likelihood from prompt logprobs.
Requires prompt_logprobs to be set in GenerateConfig so that the model provider returns log probabilities for each prompt token.
The score value is the per-sample negative log-likelihood (NLL). Per-sample perplexity is exp(value). The companion :func:perplexity_per_token metric computes corpus-level perplexity weighted by token count.
@scorer(metrics=[perplexity_per_token(), perplexity_per_seq()])
def perplexity() -> Scorertarget_perplexity
Score samples by computing NLL of target-completion tokens.
N (number of target tokens) is resolved in order:
- The
num_target_tokensargument (uniform for all samples). state.metadata["num_target_tokens"](per-sample).- Auto-tokenize
state.metadata[target_text_key]via the model provider’s :meth:~ModelAPI.tokenizemethod. - Raises an error if
target_textis present but tokenization fails (no silent fallback to incorrect results).
If neither num_target_tokens nor target_text is available, defaults to 1 (single-token targets like " A").
@scorer(metrics=[perplexity_per_token(), perplexity_per_seq()])
def target_perplexity(
num_target_tokens: int | None = None,
target_text_key: str = "target_text",
) -> Scorernum_target_tokensint | None-
Fixed number of trailing prompt tokens. When
None, resolved per-sample from metadata or auto-tokenization. target_text_keystr-
Metadata key holding the target text for auto-tokenization. Defaults to
"target_text".
multi_scorer
Returns a Scorer that runs multiple Scorers in parallel and aggregates their results into a single Score using the provided reducer function.
def multi_scorer(scorers: list[Scorer], reducer: str | ScoreReducer) -> Scorerscorerslist[Scorer]-
a list of Scorers.
reducerstr | ScoreReducer-
a function which takes in a list of Scores and returns a single Score.
precomputed_scores
Scorer that applies scores computed outside of Inspect.
Reads scores from a file and applies them to samples by id, for example to attach human ratings to an existing log using the score() function or the inspect score command. Samples with no matching record are left unscored, or fail the eval if on_missing is “error”. Records matching no sample are always ignored.
The file must contain a list of records with an id field matching a sample id, a value field with the score value, and optionally epoch, answer, explanation, and metadata fields (other fields are ignored). Records without an epoch apply to every epoch of the sample, and a record with a matching epoch takes precedence over one without.
Supported formats are JSON (an array of objects) and JSON Lines (.jsonl, one object per line).
To also name the score, wrap this scorer in your own @scorer-decorated factory (the score takes the factory’s name):
@scorer(metrics={"helpful": [mean()], "harmless": [mean()]})
def human_rubric() -> Scorer:
return precomputed_scores("ratings.json")def precomputed_scores(
scores: str,
on_missing: Literal["unscored", "error"] = "unscored",
metrics: list[Metric | dict[str, list[Metric]]]
| dict[str, list[Metric]]
| None = None,
) -> Scorerscoresstr-
Path to the scores file. Can be a local filesystem path or a path to an S3 bucket (e.g. “s3://my-bucket/scores.json”).
on_missingLiteral['unscored', 'error']-
What to do with a sample that has no matching record. “unscored” (the default) leaves it unscored, so metrics are computed over the matched samples only. “error” raises, for a scores file intended to cover every sample.
metricslist[Metric | dict[str, list[Metric]]] | dict[str, list[Metric]] | None-
Metrics to aggregate the scores with, defaulting to accuracy and stderr. Use a dict mapping subscore keys to metrics for dict-valued scores. Recorded in the log’s scorer entry, so rescoring the log reuses them.
Metrics
accuracy
Compute proportion of total answers which are correct.
@metric
def accuracy(to_float: ValueToFloat = value_to_float()) -> Metricto_floatValueToFloat-
Function for mapping Value to float for computing metrics. The default
value_to_float()maps CORRECT (“C”) to 1.0, INCORRECT (“I”) to 0, PARTIAL (“P”) to 0.5, and NOANSWER (“N”) to 0, casts numeric values to float directly, and prints a warning and returns 0 if the Value is a complex object (list or dict).
categorical
Default metrics for a categorical scorer.
Convenience helper that returns [frequency(categories)] for use as the metrics= argument of :func:~inspect_ai.scorer.scorer. Pass a StrEnum to declare the full category set::
class Verdict(StrEnum):
YES = "yes"
NO = "no"
UNSURE = "unsure"
@scorer(metrics=categorical(Verdict))
def my_grader() -> Scorer: ...
For dict-valued scores, use the per-key form::
@scorer(metrics={"*": categorical(Verdict)})
def my_grader() -> Scorer: ...
frequency() declares @metric(scores="unreduced"): when epochs are used, each epoch’s score is treated as an independent observation even when a reducer is configured for metrics that use reduced scores.
def categorical(categories: Categories = None) -> list[Metric]categoriesCategories-
The full set of possible categories (typically a StrEnum). Resolved to its member values so the category list is recorded in the metric params and survives recompute_metrics(). If
None, only observed categories are reported.
frequency
Frequency of each distinct categorical score value.
Returns a mapping from category label to its proportion (or count) among scored samples. Intended for scorers that emit string-valued (categorical) scores, e.g. Score(value="sandbagging").
For dict-valued scores, use the per-key metrics form so that each key gets its own scorer block in the results::
@scorer(metrics={"*": [frequency()]})
def my_scorer() -> Scorer: ...
def frequency(
categories: Categories = None,
normalize: bool = True,
) -> MetriccategoriesCategories-
The full set of possible categories, as a StrEnum type or a sequence of labels. Declare this so that categories with zero observations are still reported as
0.0and the metric round-trips identically through recompute_metrics(). IfNone, only observed categories are reported. normalizebool-
If
True(default) report proportions in[0, 1]; ifFalsereport raw counts.
grouped
Creates a grouped metric that applies the given metric to subgroups of samples.
@metric
def grouped(
metric: Metric,
group_key: str,
*,
all: Literal["samples", "groups"] | Literal[False] = "samples",
all_label: str = "all",
value_to_float: ValueToFloat = value_to_float(),
name_template: str = "{group_name}",
) -> MetricmetricMetric-
The metric to apply to each group of samples.
group_keystr-
The metadata key used to group samples. Each sample must have this key in its metadata.
allLiteral['samples', 'groups'] | Literal[False]-
How to compute the “all” aggregate score: - “samples”: Apply the metric to all samples regardless of groups - “groups”: Calculate the mean of all group scores - False: Don’t calculate an aggregate score
all_labelstr-
The label for the “all” key in the returned dictionary.
value_to_floatValueToFloat-
Function to convert metric values to floats, used when all=“groups”.
name_templatestr-
Template for the name of each group. The default is “{group_name}”.
aggregate
Apply agg to a single key extracted from each dict-valued Score.value.
Many scorers emit dict-valued scores (multiple numeric fields per sample). aggregate selects one field by key and feeds the resulting scalar SampleScores into agg, so any standard metric (mean, stderr, std, accuracy, …) can be applied per key.
A missing key (either key not in value or value[key] is None) is routed through on_missing. This matches the convention used by inspect_evals.utils.metrics.mean_of, so a mean_of → aggregate swap preserves behaviour.
on_missing="skip" reduces the number of samples seen by agg, which changes the result of any aggregator that depends on sample count (e.g. stderr, mean, std, var). Two evals run with the same scorer can therefore report different stderrs purely because the rate of missing keys differed, not because of any difference in the underlying variance. Prefer "zero" if you want a constant denominator.
If every sample is filtered out by on_missing="skip", the aggregator returns NaN rather than calling agg([]) (which most built-in metrics would raise on). This matches the Score.unscored() / NaN sentinel used elsewhere in the framework.
@metric
def aggregate(
key: str,
agg: Metric,
*,
to_float: ValueToFloat | None = None,
on_missing: Literal["error", "skip", "zero"] = "error",
) -> Metrickeystr-
Field to extract from each sample’s dict-valued
Score.value. aggMetric-
Metric to apply to the extracted values.
to_floatValueToFloat | None-
Optional function for mapping the extracted Value to a float before it reaches
agg. The default (None) passes the raw extracted value straight through, soagg’s own conversion applies (e.g. accuracy()’sto_float, or mean()’sas_float()). Set this only whenaggcannot convert the value itself — e.g. to feed string grades (“C”/“I”) into mean(), which expects numerics. When set, passvalue_to_float()(or a customised variant) to get the standard CORRECT/INCORRECT/PARTIAL/NOANSWER mapping. on_missingLiteral['error', 'skip', 'zero']-
How to handle samples whose
score.valuedoes not containkey, or containskeywith aNonevalue:"error"(default): raiseValueError."skip": exclude the sample fromagg. ReturnsNaNif every sample is skipped."zero": include the sample with value0.0.
mean
Compute mean of all scores.
@metric
def mean(to_float: ValueToFloat = value_to_float()) -> Metricto_floatValueToFloat-
Function for mapping Value to float for computing metrics. The default
value_to_float()maps CORRECT (“C”) to 1.0, INCORRECT (“I”) to 0, PARTIAL (“P”) to 0.5, and NOANSWER (“N”) to 0, casts numeric values to float directly, and prints a warning and returns 0 if the Value is a complex object (list or dict).
std
Calculates the sample standard deviation of a list of scores.
@metric
def std(to_float: ValueToFloat = value_to_float()) -> Metricto_floatValueToFloat-
Function for mapping Value to float for computing metrics. The default
value_to_float()maps CORRECT (“C”) to 1.0, INCORRECT (“I”) to 0, PARTIAL (“P”) to 0.5, and NOANSWER (“N”) to 0, casts numeric values to float directly, and prints a warning and returns 0 if the Value is a complex object (list or dict).
stderr
Standard error of the mean using Central Limit Theorem.
@metric
def stderr(
to_float: ValueToFloat = value_to_float(), cluster: str | None = None
) -> Metricto_floatValueToFloat-
Function for mapping Value to float for computing metrics. The default
value_to_float()maps CORRECT (“C”) to 1.0, INCORRECT (“I”) to 0, PARTIAL (“P”) to 0.5, and NOANSWER (“N”) to 0, casts numeric values to float directly, and prints a warning and returns 0 if the Value is a complex object (list or dict). clusterstr | None-
The key from the Sample metadata corresponding to a cluster identifier for computing clustered standard errors.
bootstrap_stderr
Standard error of the mean using bootstrap.
@metric
def bootstrap_stderr(
num_samples: int = 1000, to_float: ValueToFloat = value_to_float()
) -> Metricnum_samplesint-
Number of bootstrap samples to take.
to_floatValueToFloat-
Function for mapping Value to float for computing metrics. The default
value_to_float()maps CORRECT (“C”) to 1.0, INCORRECT (“I”) to 0, PARTIAL (“P”) to 0.5, and NOANSWER (“N”) to 0, casts numeric values to float directly, and prints a warning and returns 0 if the Value is a complex object (list or dict).
perplexity_per_token
Corpus-level perplexity weighted by token count.
Longer samples contribute proportionally more. Computed as exp(-total_sum_log_probs / total_num_tokens).
This is the standard definition of corpus perplexity used in the HuggingFace Transformers documentation and the EleutherAI lm-evaluation-harness (weighted_perplexity).
@metric
def perplexity_per_token() -> Metricperplexity_per_seq
Corpus-level perplexity with equal weight per sample.
Each sample’s per-token NLL is averaged, then exponentiated. Computed as exp(mean_over_samples(-sum_log_probs_i / num_tokens_i)) – the geometric mean of per-sample perplexities.
Unlike perplexity_per_token, this gives equal weight to each sample regardless of length, preventing long samples from dominating the metric. The EleutherAI lm-evaluation-harness perplexity aggregation is a different metric, exp(-mean(loglikelihood_i)) over raw per-document log-likelihoods with no per-token normalization.
@metric
def perplexity_per_seq() -> Metrickrippendorff_alpha
Krippendorff’s α coefficient of inter-rater agreement.
Computes Krippendorff’s α across multiple judges/raters for each sample. Each SampleScore passed to the metric must have a sequence-valued Score.value, where each element is one judge’s rating of that sample; produce these per-judge lists by pairing multi_scorer() with the collect reducer. Samples whose Score.value is not a sequence (or contains fewer than two ratings) are skipped.
α = 1 indicates perfect agreement; α = 0 indicates agreement equal to chance; α < 0 indicates systematic disagreement.
For the 2-judge nominal case, α coincides with Scott’s π (its many-judge analogue is Fleiss’ κ); the two converge only as the number of units grows, since α applies a small-sample correction.
@metric
def krippendorff_alpha(
level: KrippendorffLevel = "nominal",
to_float: ValueToFloat | None = None,
) -> MetriclevelKrippendorffLevel-
Measurement scale.
"nominal"(default) treats ratings as unordered categories (any difference is a full disagreement). Use for correct/incorrect labels and unordered category IDs."ordinal"treats ratings as ordered categories whose gaps are not assumed equal; δ² is weighted by the marginal frequency of intermediate ranks (Krippendorff 2007). Use for Likert-style ratings."interval"treats ratings as numbers on an equal-interval scale; δ² is the squared numeric difference. Use for continuous scores. to_floatValueToFloat | None-
Optional
ValueToFloatused to coerce non-numeric ratings to floats for"ordinal"and"interval"(e.g.,value_to_float()to map CORRECT/INCORRECT/PARTIAL/NOANSWER to 1/0/0.5/0). Numeric ratings need no coercion. Raises if"ordinal"or"interval"is selected with non-numeric ratings and noto_float. Ignored for"nominal".
Reducers
at_least
Score correct if there are at least k score values greater than or equal to the value.
@score_reducer
def at_least(
k: int, value: float = 1.0, value_to_float: ValueToFloat = value_to_float()
) -> ScoreReducerkint-
Number of score values that must exceed
value. valuefloat-
Score value threshold.
value_to_floatValueToFloat-
Function to convert score values to float.
pass_at
Probability of at least 1 correct sample given k epochs (https://arxiv.org/pdf/2107.03374).
@score_reducer
def pass_at(
k: int, value: float = 1.0, value_to_float: ValueToFloat = value_to_float()
) -> ScoreReducerkint-
Epochs to compute probability for.
valuefloat-
Score value threshold.
value_to_floatValueToFloat-
Function to convert score values to float.
pass_k
Probability that all k epoch attempts succeed (https://arxiv.org/pdf/2406.12045).
Computed as the draw-without-replacement estimator C(correct, k) / C(total, k), dual to pass_at’s Chen 2021 estimator.
@score_reducer
def pass_k(
k: int, value: float = 1.0, value_to_float: ValueToFloat = value_to_float()
) -> ScoreReducerkint-
Epochs to compute probability for.
valuefloat-
Score value threshold.
value_to_floatValueToFloat-
Function to convert score values to float.
max_score
Take the maximum value from a list of scores.
@score_reducer(name="max")
def max_score(value_to_float: ValueToFloat = value_to_float()) -> ScoreReducervalue_to_floatValueToFloat-
Function to convert the value to a float
mean_score
Take the mean of a list of scores.
@score_reducer(name="mean")
def mean_score(value_to_float: ValueToFloat = value_to_float()) -> ScoreReducervalue_to_floatValueToFloat-
Function to convert the value to a float
median_score
Take the median value from a list of scores.
@score_reducer(name="median")
def median_score(value_to_float: ValueToFloat = value_to_float()) -> ScoreReducervalue_to_floatValueToFloat-
Function to convert the value to a float
mode_score
Take the mode from a list of scores.
@score_reducer(name="mode")
def mode_score() -> ScoreReducercollect_score
Collect each score’s value into a list, preserving every value.
Keeps the individual values intact instead of aggregating them into one. Score values must be scalar; unscored (NaN) scores are dropped.
@score_reducer(name="collect")
def collect_score() -> ScoreReducerTypes
Scorer
Score model outputs.
Evaluate the passed outputs and targets and return a dictionary with scoring outcomes and context.
class Scorer(Protocol):
async def __call__(
self,
state: TaskState,
target: Target,
) -> Score | NoneExamples
@scorer
def custom_scorer() -> Scorer:
async def score(state: TaskState, target: Target) -> Score:
# Compare state / model output with target
# to yield a score
return Score(value=...)
return scoreTarget
Target for scoring against the current TaskState.
Target is a sequence of one or more strings. Use the text property to access the value as a single string.
class Target(Sequence[str])Score
Score generated by a scorer.
class Score(BaseModel)Attributes
valueValue-
Score value.
answerstr | None-
Answer extracted from model output (optional)
explanationstr | None-
Explanation of score (optional).
metadatadict[str, Any] | None-
Additional metadata related to the score
historylist[ScoreEdit]-
Edit history - users can access intermediate states.
textstr-
Read the score as text.
Methods
- unscored
-
Construct a Score that is preserved but excluded from metrics and reducers.
Use this when a scorer cannot produce a value for a sample but you still want to record context (answer, explanation, metadata). Sets
valueto NaN, which is the canonical sentinel that aggregate metrics and reducers skip.@classmethod def unscored( cls, *, answer: str | None = None, explanation: str | None = None, metadata: dict[str, Any] | None = None, ) -> "Score"answerstr | Noneexplanationstr | Nonemetadatadict[str, Any] | None
- as_str
-
Read the score as a string.
def as_str(self) -> str - as_int
-
Read the score as an integer.
def as_int(self) -> int - as_float
-
Read the score as a float.
def as_float(self) -> float - as_bool
-
Read the score as a boolean.
def as_bool(self) -> bool - as_list
-
Read the score as a list.
def as_list(self) -> list[str | int | float | bool] - as_dict
-
Read the score as a dictionary.
def as_dict(self) -> dict[str, str | int | float | bool | None]
Value
Value provided by a score.
Use the methods of Score to easily treat the Value as a simple scalar of various types.
Value = Union[
str | int | float | bool,
Sequence[str | int | float | bool],
Mapping[str, str | int | float | bool | None],
]ScoreReducer
Reduce a set of scores to a single score.
class ScoreReducer(Protocol):
def __call__(self, scores: list[Score]) -> Scorescoreslist[Score]-
List of scores.
Metric
Metric protocol.
The Metric signature changed in release v0.3.64. Both the previous and new signatures are supported – you should use MetricProtocol for new code as the depreacated signature will eventually be removed.
Metric = MetricProtocol | MetricDeprecatedMetricProtocol
Compute a metric on a list of scores.
class MetricProtocol(Protocol):
def __call__(self, scores: list[SampleScore]) -> Valuescoreslist[SampleScore]-
List of scores.
Examples
@metric
def mean() -> Metric:
def metric(scores: list[SampleScore]) -> Value:
return np.mean([score.score.as_float() for score in scores]).item()
return metricSampleScore
Score for a Sample.
class SampleScore(BaseModel)Attributes
scoreScore-
A score
sample_idstr | int | None-
A sample id
sample_metadatadict[str, Any] | None-
Metadata from the sample
scorerstr | None-
Registry name of scorer that created this score.
Methods
- sample_metadata_as
-
Pydantic model interface to sample metadata.
def sample_metadata_as(self, metadata_cls: Type[MT]) -> MT | Nonemetadata_clsType[MT]-
Pydantic model type
Decorators
scorer
Decorator for registering scorers.
def scorer(
metrics: Sequence[Metric | Mapping[str, Sequence[Metric]]]
| Mapping[str, Sequence[Metric]],
name: str | None = None,
**metadata: Any,
) -> Callable[[Callable[P, Scorer]], Callable[P, Scorer]]metricsSequence[Metric | Mapping[str, Sequence[Metric]]] | Mapping[str, Sequence[Metric]]-
One or more metrics to calculate over the scores.
namestr | None-
Optional name for scorer. If the decorator has no name argument then the name of the underlying ScorerType object will be used to automatically assign a name.
**metadataAny-
Additional values to serialize in metadata.
Examples
@scorer
def custom_scorer() -> Scorer:
async def score(state: TaskState, target: Target) -> Score:
# Compare state / model output with target
# to yield a score
return Score(value=...)
return scoremetric
Decorator for registering metrics.
def metric(
name: str | Callable[P, Metric] | None = None,
*,
scores: MetricScores = "auto",
) -> Callable[[Callable[P, Metric]], Callable[P, Metric]] | Callable[P, Metric]namestr | Callable[P, Metric] | None-
Optional name for metric. If the decorator has no name argument then the name of the underlying MetricType will be used to automatically assign a name.
scoresMetricScores-
Epoch-reduction contract for the metric’s
scoresinput."auto"(default) preserves legacy behavior, receiving reduced scores unless reducers are explicitly disabled."reduced"requires one score per sample after the configured ScoreReducer runs."unreduced"receives one score per sample per epoch — use this for metrics that treat each epoch as an independent observation (e.g. frequency()).
Examples
```python @metric def mean() -> Metric: def metric(scores: list[SampleScore]) -> Value: return np.mean([score.score.as_float() for score in scores]).item() return metric
score_reducer
Decorator for registering Score Reducers.
def score_reducer(
func: ScoreReducerType | None = None, *, name: str | None = None
) -> Callable[[ScoreReducerType], ScoreReducerType] | ScoreReducerTypefuncScoreReducerType | None-
Function returning ScoreReducer targeted by plain task decorator without attributes (e.g.
@score_reducer) namestr | None-
Optional name for reducer. If the decorator has no name argument then the name of the function will be used to automatically assign a name.
Intermediate Scoring
score
Score a model conversation.
Score a model conversation (you may pass TaskState or AgentState as the value for conversation)
async def score(conversation: ModelConversation) -> list[Score]conversationModelConversation-
Conversation to submit for scoring. Note that both TaskState and AgentState can be passed as the
conversationparameter.