soev_evals.core
Pure evaluation models, ports, loading and scoring.
A project file names the system under test and its suites. A suite file holds cases. A case holds the
turns of a conversation and the criteria that grade the reply. A run starts a conversation for each attempt of a
case through an arm, and collects the evidence. Then each criterion gives a verdict on the evidence.
soev_evals.core does no I/O of its own: it gets the YAML text and the services from its caller.
Cases and suites
A suite is a list of cases with the criteria that they share. Load it from YAML text.
Suite
modelSuiteCases and shared criteria from one logical suite.
A suite can span several YAML files: load_suites merges them. Validation fails when two cases have
the same id, when a case names another suite, or when a case does not match id_pattern.
attributenamestrThe name of the suite. The project names its suites by this name.
attributeid_patternstr | None= NoneA regular expression with one capture group, or None. Each case id must match it in full,
and the group must equal the case's rule.
attributedefaultslist[CriterionSpec]= list()The criteria of every case of the suite. They come before the criteria of each case.
attributecaseslist[Case]The cases. A suite has at least one case.
methodcriteria_for(case) -> list[CriterionSpec]Return suite defaults followed by case-specific criteria.
A run adds the project invariants before this list.
paramcaseCaseA case of this suite.
Returns
list[CriterionSpec]The criteria that grade each attempt of case, in order.
load_suite
functionload_suite(text, registry) -> SuiteLoad one suite from YAML text. The function reads no file.
The registry checks the kind and the parameters of each criterion, so an unknown kind or a wrong parameter fails here, before a run starts.
Example
from soev_evals.core import load_suite
from soev_evals.criteria import builtin_registry
text = '''
name: smoke
cases:
- id: greet
lineage: greet
category: smalltalk
turns:
- prompt: Hallo, wie ben jij?
criteria:
- kind: reply.language
language: nl
'''
suite = load_suite(text, builtin_registry())paramtextstrThe YAML text of one suite file.
paramregistryCriterionRegistryThe criterion kinds that the suite can use.
Returns
SuiteThe validated suite.
Raises:
SuiteError: The text is not valid YAML or not a valid suite, or a criterion has an unknown kind or invalid parameters.
load_suites
functionload_suites(documents, registry) -> SuiteMerge the files of one suite into one suite.
The merged suite has the cases of all documents, in the order of documents.
paramdocumentsSequence[str]The YAML text of each file of the suite.
paramregistryCriterionRegistryThe criterion kinds that the suite can use.
Returns
SuiteOne suite with the cases of all documents.
Raises:
SuiteError:documentsis empty, a document is not a valid suite, the documents differ inname,defaultsorid_pattern, or two documents have a case with the same id.
Case
modelCaseA conversation and its project-independent evaluation definition.
A case is one entry of a suite file. Each attempt of a case runs its turns on a new conversation, and each variant on a new conversation of its own. Then the criteria grade the evidence.
attributeidstrThe id of the case. It is unique in its suite and in the project.
attributesuitestrThe name of the suite. A suite file fills it in when the case leaves it out.
attributestatusLiteral['active', 'draft', 'retired']= 'active'Only "active" cases run. "draft" and "retired" cases stay in the file.
attributesplitLiteral['dev', 'test'] | None= NoneThe side of the dataset, "dev" or "test", or None before a split. The seal covers the test
cases.
attributelineagestrThe group of the case and the cases derived from it. A split puts a whole lineage on one side.
attributecategorystrA free label. The report gives scores for each category.
attributerulestr | None= NoneThe id of the rule that the case tests, or None. The report gives scores for each rule, and
Suite.id_pattern checks it against the case id.
attributederived_fromstr | None= NoneThe id of the case that this case derives from, or None for the root of a lineage.
attributeprovenanceProvenance= Provenance()The generation and review history.
attributeturnslist[Turn]The user prompts, in order. A case has at least one turn.
attributevariantsdict[str, list[Turn]]= dict()Other versions of the turns, by name. The compare.* criteria compare their evidence with the
evidence of turns.
attributeexpectExpect= Expect()What the system must do and say.
attributeanswerabilityAnswerability | None= NoneAn assessment of how well the sources cover the question, or None.
attributecriterialist[CriterionSpec]= list()The criteria of this case. They come after the suite defaults.
attributesetupdict[str, JsonValue]= dict()Free data for the project's CaseSetup, which receives the whole case.
Turn
modelTurnOne user prompt in a conversation.
attributepromptstrThe text that the arm sends as the user input. It is nonempty.
Expect
modelExpectThe expected behaviour, content and source roles for a case.
attributebehaviourLiteral['answer', 'refuse', 'abstain']= 'answer'What the system must do: "answer", "refuse" or "abstain". behaviour.expected asks the
judge for this label.
attributemessagestr | None= NoneThe key of a message in Project.messages. behaviour.message requires its text in the reply,
and refusal.code expects this code for a refusal or an abstention.
attributeanswerstr | None= NoneA reference answer, or None. rubric.judge gives it to the judge.
attributenuggetslist[Nugget]= list()The facts that the reply must cover.
attributesourcesSourceRoles= SourceRoles()The roles of the sources that the reply can cite.
Nugget
modelNuggetA reference fact and the ids of the sources that support it.
The nuggets.coverage criterion asks the judge whether the reply covers each nugget.
attributetextstrThe fact. It is nonempty.
attributeimportanceLiteral['vital', 'okay']= 'vital'"vital" or "okay". The coverage score counts only the vital nuggets.
attributesourceslist[str]= list()The ids of the sources that support the fact. The judge receives them with the fact.
SourceRoles
modelSourceRolesRequired alternative groups, supporting sources and forbidden sources.
Each entry is a source id, as CitationMapping resolves it from a citation. The citation criteria
compare these ids with the cited ids. With the default match "hierarchical", an id also matches the ids below
it in the / path: law/1 matches law/1/2, and law/1/2 matches law/1.
attributerequireddict[str, list[str]]= dict()Groups of alternative sources, by group name. A citation of one member covers its group.
citations.required scores the share of covered groups.
attributesupportinglist[str]= list()Sources that a reply can cite. citations.unseen does not list them.
attributeforbiddenlist[str]= list()Sources that a reply must not cite. citations.forbidden fails on each such citation.
Provenance
modelProvenanceGeneration and review history carried with a case.
This package stores the history with the case, but does not read it.
attributegeneratorstr | None= NoneWho or what wrote the case, or None when unknown.
attributereviewerstr | None= NoneWho reviewed the case, or None when nobody did.
attributeroundint | None= NoneThe number of the review round, from 0, or None.
attributenotesJsonValue= NoneFree JSON notes.
Answerability
modelAnswerabilitySource coverage assessment and non-authoritative hints for expert review.
This package stores and validates the assessment, but no built-in criterion reads it.
attributelabelAnswerabilityLabelHow well the sources cover the question.
attributelimitationslist[Limitation]= list()Why the coverage is limited. It is nonempty exactly when label is "limited".
attributesource_hintslist[str]= list()Ids of sources that can help a reviewer. Each id is nonempty.
attributedetailstr= ''A free explanation of the assessment.
attributeassessed_byLiteral['judge', 'expert']Who made the assessment: "judge" or "expert".
AnswerabilityLabel
type aliasAnswerabilityLabel = Literal['full', 'limited', 'not_regulated', 'unanswerable']The label of an Answerability assessment: how well the sources cover the question of a case.
Only the label "limited" has reasons, as a list of Limitation values.
Limitation
type aliasLimitation = Literal['lower_regulation', 'parliamentary_history', 'case_law_or_guidance', 'fact_dependent']A reason for the Answerability label "limited".
SuiteError
errorSuiteErrorSuite content is invalid or inconsistent.
load_suite and load_suites raise it.
Projects
A project holds the system under test, the judge settings, the suites and the criteria that every case shares.
Project
modelProjectProject-owned arm, judge, suites, hooks and invariant definitions.
A project is one YAML file. It names the system under test, the suites and the criteria that every
case shares. load of soev_evals.cli reads it with its suites, its hooks and its corpus lookup.
attributenamestrThe name of the project.
attributelanguagestrThe main language of the project, as a language code.
attributesystemSystemConfigThe system under test.
attributejudgeJudgeConfigThe judge settings.
attributerunsRunsConfig= RunsConfig()The number of attempts of each case.
attributeconcurrencyint= 1The number of attempts that run at the same time, at least 1.
attributeinvariantslist[CriterionSpec]= list()The criteria of every case of every suite. They come before the suite defaults.
attributemessagesdict[str, str]= dict()The fixed messages of the system, by key. Expect.message names a key.
attributecitationsCitationMappingHow the arm finds the source id of a cited element.
attributehooksstr | None= NoneThe name of a Python module to import, or None. Its attribute CRITERIA lists more criterion
kinds, and its attribute SETUP is the CaseSetup of the project.
attributesplitSplitConfig= SplitConfig()The settings of a dataset split.
attributesuitesdict[str, str]= dict()The glob pattern of the files of each suite, by suite name, relative to the folder of the project file.
attributeruntimestr | None= NoneThe name of the runtime provider in the entry point group soev.evals.runtimes, or None for the
HTTP arm. The --runtime option replaces it.
attributecorpusCorpusLookupConfig= CorpusLookupConfig()Where the corpus lookup file is.
attributeextensionsdict[str, JsonValue]= dict()Free JSON settings for other tools. This package does not read them.
SystemConfig
modelSystemConfigThe settings of the arm: the server, the agent and the names of the environment variables of its credentials.
The project file holds only the names of the environment variables, never their values. The arm reads the values when it opens its HTTP client.
attributearmLiteral['soev_thread']= 'soev_thread'The kind of arm. "soev_thread" is the only kind: the threads API of a soev server.
attributeurl_envstrThe environment variable with the base URL of the server.
attributecredential_envstrThe environment variable with the bearer token for the server.
attributesubject_envstrThe environment variable with the subject that the arm sends in the X-Soev-Subject header.
attributeagentstrThe name of the agent that each new thread runs.
attributemodelstr | None= NoneThe model that each input asks for, or None for the default model of the agent.
attributeknowledgelist[str]= list()The knowledge keys that each input sends.
attributetimeout_sfloat= 120.0The timeout of each HTTP request, in seconds.
JudgeConfig
modelJudgeConfigThe judge settings of a project.
soev_evals records endpoint in the manifest, but connects no judge to it. A RuntimeProvider reads
it to make its judge.
attributeendpointstrThe name of the judge endpoint. The run manifest records it.
attributecontextLiteral['units', 'corpus']= 'units'The source context of the judge: "units" or "corpus". This package does not read it.
RunsConfig
modelRunsConfigThe requested repetition count for each case.
attributekint= 1The number of attempts of each case in a run, at least 1. The --k option of run replaces it.
CitationMapping
modelCitationMappingA dotted element field path and optional canonical-id extraction regex.
The arm uses it to turn each element that a reply cites into the canonical source id of a Citation.
attributefieldstrThe dotted path of the field in the element that holds the id, for example "metadata.unit_id".
attributeregexstr | None= NoneA regular expression that finds the id in the field's value, or None to take the whole value. The
id is the first capture group, or the whole match without a group.
methodsource_id(element) -> str | NoneResolve a source id using the first capture group or the whole match.
paramelementMapping[str, object]An element of a tool output, as JSON.
Returns
str | NoneThe canonical source id, or None when the field is missing or empty, or when the regex does not
match.
CorpusLookupConfig
modelCorpusLookupConfigWhere the corpus criteria find the ids and the text of the corpus.
The project loader reads the file when it exists. Each line is a JSON object with an id and a text.
Without the file, the criteria that need the corpus give a verdict with the status "error".
attributepathstr= 'corpus/units.jsonl'The path of the JSONL file, relative to the folder of the project file.
attributelaw_namesdict[str, list[str]]= dict()Other names of each law, by canonical law id. citations.mentions_in_corpus resolves a
mention of such a name to that law.
SplitConfig
modelSplitConfigIncremental lineage split targets and suite-specific strata.
The settings of a dataset split. No command of soev_evals reads them.
attributetest_sharefloat= 0.2The share of the lineages of each stratum that goes to the test side, from 0 to 1.
attributeseedint= 0The seed that orders the lineages of a stratum before the split.
attributestratifydict[str, StratifyKey]= dict()The StratifyKey of each suite, by suite name. A suite without an entry uses "category".
attributemin_per_sideint= 2The number of lineages on each side of a stratum below which a split count warns.
StratifyKey
type aliasStratifyKey = Literal['category', 'suite', 'rule', 'rule_direction']The case field that groups the lineages of a suite into strata for a dataset split.
The split puts the same share of each stratum on the test side. The value comes from the root case of a lineage.
"rule_direction" combines the rule with the expected behaviour: "pass" for "answer", "fire" otherwise.
ProjectError
errorProjectErrorProject content is invalid or inconsistent.
The project loader of soev_evals.cli raises it, for example when two suites of a project have a case
with the same id.
Criteria
A criterion names a kind and its parameters. The registry finds the kind, and the kind gives the verdict.
CriterionSpec
modelCriterionSpecA named criterion with scoring policy and kind-specific parameters.
It is one entry of criteria, defaults or invariants in a YAML file. The parameters of the kind can
stand next to kind, or under params. A key next to kind replaces the same key under params:
- kind: reply.max_length
max: 2000
gate: trueattributekindstrThe name of the criterion kind in the registry, for example "reply.language".
attributeweightint= 1The weight of the criterion in the score of an attempt, at least 1.
attributegatebool= FalseIf true, a failed criterion makes the score of the attempt 0, and its weight does not count.
attributeparamsdict[str, JsonValue]= dict()The parameters of the kind. The registry validates them against the parameter model of the kind.
CriterionKind
protocolCriterionKindA criterion implementation with a validated parameter model.
A criterion in a suite names its kind in kind. Builtin of soev_evals.criteria makes a kind of a
typed async function. Register your own kinds in the CRITERIA list of the project's hooks module.
attributenamestrThe stable registry key.
It is the kind of a criterion in a suite, for example "reply.language".
attributeparams_modeltype[BaseModel]The schema accepted by this kind.
It is a pydantic model. The registry validates the parameters of each criterion against it.
methodevaluateasync (case, evidence, *, params, ctx) -> VerdictEvaluate one case against the supplied evidence.
Return a verdict with the status "error" when the criterion cannot grade. An exception stops the
run.
paramcaseCaseThe case that the attempt ran.
paramevidenceEvidenceThe evidence of the attempt.
paramparamsBaseModelThe parameters of the criterion, as an instance of params_model.
paramctxCriterionContextThe services and the lookup data of the project.
Returns
VerdictThe verdict. The registry fills in its kind, weight and gate.
CriterionRegistry
classCriterionRegistry(kinds=())Resolve and evaluate an explicitly supplied collection of kinds.
builtin_registry of soev_evals.criteria returns a registry with the built-in kinds.
Make a registry of kinds.
paramkindsIterable[CriterionKind]= ()The criterion kinds. Each name occurs once.
Raises:
DuplicateCriterionError: Two kinds have the same name.
attributenamestuple[str, ...]The registered names, in deterministic (sorted) order.
methodkind_named(name) -> CriterionKindReturn the kind with the name name.
paramnamestrThe name of the kind.
Returns
CriterionKindThe kind with this name.
Raises:
UnknownCriterionError: The registry has no kind with this name.
methodvalidate(spec) -> BaseModelValidate kind-specific arguments before evaluation begins.
paramspecCriterionSpecThe criterion to check.
Returns
BaseModelThe parameters of spec, as an instance of the parameter model of its kind.
Raises:
UnknownCriterionError: The registry has no kind with the namespec.kind.CriterionParamsError: The parameters do not fit the parameter model of the kind.
methodevaluateasync (spec, case, *, evidence, ctx) -> VerdictEvaluate a criterion and attach its declared weight and gate.
paramspecCriterionSpecThe criterion.
paramcaseCaseThe case that the attempt ran.
paramevidenceEvidenceThe evidence of the attempt.
paramctxCriterionContextThe services and the lookup data of the project.
Returns
VerdictThe verdict of the kind, with the kind, weight and gate of spec.
Raises:
UnknownCriterionError: The registry has no kind with the namespec.kind.CriterionParamsError: The parameters do not fit the parameter model of the kind.
CriterionContext
dataclassCriterionContext(judge=None, language_detector=None, messages=dict(), corpus_ids=None, corpus_law_names=dict(), corpus_text=None, rubrics=dict())The services and the project lookup data that each criterion gets.
Each criterion gets the same context. A criterion does no I/O of its own: what it needs from outside
comes from here. A service or lookup that the project did not configure is None or empty, and a criterion that
needs it gives a verdict with the status "error".
paramjudgeJudge | None= NoneThe judge for the judge criteria, or None.
paramlanguage_detectorLanguageDetector | None= NoneThe language detector for reply.language, or None.
parammessagesMapping[str, str]= dict()The fixed messages of the system, by key, from Project.messages.
paramcorpus_idsfrozenset[str] | None= NoneThe ids of all corpus units, or None without a corpus lookup.
paramcorpus_law_namesMapping[str, list[str]]= dict()Other names of each law, by canonical law id, from CorpusLookupConfig.law_names.
paramcorpus_textMapping[str, str] | None= NoneThe text of each corpus unit, by id, or None without a corpus lookup.
paramrubricsMapping[str, str]= dict()The text of each rubric, by the path that a rubric.judge criterion gives.
Verdict
modelVerdictOne criterion outcome with the scoring policy used for the attempt.
attributestatusLiteral['pass', 'fail', 'not_applicable', 'error']"pass" or "fail". "not_applicable" when the case gives the criterion nothing to check.
"error" when the criterion cannot grade, for example without a judge. An error makes the attempt
fail, but does not count in its score.
attributedetailstr= ''A short explanation of the outcome.
attributedatadict[str, JsonValue] | None= NoneStructured data of the outcome for the report, or None.
attributekindstr= ''The kind of the criterion. The registry fills it in.
attributeweightint= 1The weight of the criterion. The registry fills it in.
attributegatebool= FalseWhether the criterion is a gate. The registry fills it in.
UnknownCriterionError
errorUnknownCriterionErrorA criterion name is absent from the registry.
CriterionRegistry raises it for a spec whose kind it does not hold. load_suite reports it as a
SuiteError.
DuplicateCriterionError
errorDuplicateCriterionErrorTwo implementations claim the same criterion name.
CriterionRegistry raises it when it is made with two kinds of the same name, for example a project
hook that reuses the name of a built-in kind.
CriterionParamsError
errorCriterionParamsErrorA criterion has invalid parameters.
CriterionRegistry.validate and CriterionRegistry.evaluate raise it when the parameters of a spec do
not fit the parameter model of its kind. load_suite reports it as a SuiteError.
Evidence and scores
Evidence is what the system under test returned in one attempt. The verdicts of an attempt give its score.
Evidence
modelEvidenceThe evidence of one attempt: its turns in order, its failure and the evidence of its variants.
The runner builds it for each attempt, and the criteria grade it. The archive stores it, so a rescore can grade it again without a new conversation.
attributeturnslist[TurnEvidence]= list()The evidence of each turn that ran, in order.
attributeartifactsdict[str, JsonValue]= dict()Free JSON data of the attempt. CaseSetup.collect adds its data here.
attributethread_idstr | None= NoneThe id of the conversation in the system under test, or None.
attributefailurestr | None= NoneWhat went wrong outside a turn, for example an ArmError or a SetupError, or None.
attributevariantsdict[str, Evidence]= dict()The evidence of each variant of the case, by variant name.
attributereplystr | NoneThe final turn's reply, or None when it was not captured.
attributecited_idsfrozenset[str]Canonical ids cited anywhere in the conversation.
attributefailurestuple[str, ...]All recorded attempt and turn failures.
TurnEvidence
modelTurnEvidenceThe reply, citations, tool calls and measurements from one turn.
A Conversation returns it for each turn that it sends. A turn with a failure ends the
conversation: the runner sends no more turns of the case.
attributereplystr | None= NoneThe text of the final reply, or None when the turn has none.
attributecitationslist[Citation]= list()The citations of the turn, in order.
attributetool_callslist[ToolCall]= list()The tool calls of the turn, in order.
attributeusageUsage | None= NoneThe measured usage, or None when it was not measured.
attributeartifactsdict[str, JsonValue]= dict()Free JSON data of the turn, which criteria can read.
attributethread_idstr | None= NoneThe id of the conversation in the system under test, or None.
attributefailurestr | None= NoneWhat went wrong in the turn, or None when nothing did.
Citation
modelCitationA cited source resolved to its canonical id.
attributesource_idstrThe canonical id of the source, which the citation criteria compare with SourceRoles.
attributerawJsonValue= NoneThe citation as the system under test returned it.
attributetitlestr | None= NoneThe title of the source, or None.
attributeurlstr | None= NoneThe URL of the source, or None.
ToolCall
modelToolCallA tool invocation and a compact result description.
attributenamestrThe name of the tool.
attributeargsdict[str, JsonValue]= dict()The arguments of the call.
attributeresult_summarystr | None= NoneA short text form of the result, or None when the call has no result.
Usage
modelUsageMeasured token and time consumption of a turn.
attributeprompt_tokensint= 0The prompt tokens of all model calls of the turn.
attributecompletion_tokensint= 0The completion tokens of all model calls of the turn.
attributesecondsfloat= 0.0The duration of the turn, in seconds.
attributeanswered_modelstr | None= NoneThe name of the model that wrote the reply, or None when unknown.
ScoredAttempt
modelScoredAttemptA case's verdicts from one attempt.
attributecaseCaseThe case of the attempt.
attributeverdictslist[Verdict]= list()One verdict for each criterion of the case, in the order of the criteria.
attributescorefloatThe weighted non-gate score, zeroed by a failed gate.
It is the weight of the passed criteria divided by the weight of the passed and failed criteria,
from 0 to 1. Verdicts with the status "error" or "not_applicable" do not count. A gate that fails makes
the score 0. Without a passed or failed criterion that is not a gate, the score is 1.
attributepassedboolWhether every applicable criterion passed without judging errors.
Each verdict must have the status "pass" or "not_applicable". A verdict with the status
"error" makes the attempt fail.
Ports
A port is a boundary that the caller implements: the system under test, the setup of a case, the judge, the language detector, the archive and the tracker.
Arm
protocolArmAn arm, which starts a new conversation with the system under test for each attempt.
The arm is the connection to the system under test. SoevThreadArm of soev_evals.arms is the built-in arm.
methodstartasync (case) -> ConversationCreate an isolated conversation for one attempt.
The runner calls it for each attempt of a case, and again for each variant.
paramcaseCaseThe case of the attempt. For a variant, its turns are the turns of the variant.
Returns
ConversationA new conversation that shares no state with other conversations.
Raises:
ArmError: The arm cannot start a conversation. The runner records it as the failure of the evidence.
Conversation
protocolConversationA single isolated multi-turn interaction with the system under test.
An Arm starts it. The runner sends the turns of the case in order, then closes the conversation.
methodsendasync (turn) -> TurnEvidenceSubmit a prompt and collect that turn's evidence.
Put a failure of the turn in TurnEvidence.failure. The runner then sends no more turns.
paramturnTurnThe next turn of the case.
Returns
TurnEvidenceThe evidence of the turn.
Raises:
ArmError: The conversation cannot continue. The runner records it as the failure of the evidence.
methodcloseasync () -> NoneRelease resources associated with the conversation.
The runner calls it once after the last turn, also when a turn failed.
Raises:
ArmError: The release failed. The runner records it as the failure of the evidence.
CaseSetup
protocolCaseSetupThe setup of a project, which manages project-specific fixtures and artifacts around an attempt.
The runner calls prepare before the conversation, collect after it, and cleanup at the end. It does this
for the turns of the case and again for each variant. Give a setup to the CLI as SETUP in the project's
hooks module.
methodprepareasync (case) -> Mapping[str, JsonValue]Prepare fixtures and return opaque cleanup state.
paramcaseCaseThe case of the attempt.
Returns
Mapping[str, JsonValue]The state that collect and cleanup receive.
Raises:
SetupError: The preparation failed. The conversation does not run, and the runner records the failure.
methodcollectasync (case, evidence, *, state) -> dict[str, JsonValue]Collect project artifacts after the attempt.
paramcaseCaseThe case of the attempt.
paramevidenceEvidenceThe evidence of the conversation.
paramstateMapping[str, JsonValue]The state that prepare returned.
Returns
dict[str, JsonValue]The artifacts. The runner adds them to Evidence.artifacts.
Raises:
SetupError: The collection failed. The runner records the failure in the evidence.
methodcleanupasync (case, state) -> NoneRelease the prepared fixtures.
The runner calls it after each successful prepare, also when the conversation or collect
failed.
paramcaseCaseThe case of the attempt.
paramstateMapping[str, JsonValue]The state that prepare returned.
Raises:
SetupError: The cleanup failed. The runner records the failure in the evidence.
Judge
protocolJudgeA judge, which gives a label for a grading request.
The judge owns the prompts. A criterion gets a judge from CriterionContext.judge. LLMJudge of
soev_evals.judges is the built-in judge.
methodjudgeasync (request) -> JudgeResultReturn an allowed label or raise JudgeError.
paramrequestJudgeRequestThe task, the inputs and the allowed labels.
Returns
JudgeResultThe chosen label, one of request.allowed_labels, and its explanation.
Raises:
JudgeError: The judge cannot give a usable result.
JudgeRequest
modelJudgeRequestThe task and the inputs that a criterion sends to a judge.
A criterion sends the task and the inputs. The judge adds the prompt of the task.
attributetaskstrThe name of the grading task. The built-in judge criteria use their own kind as the task, for example
"rubric.judge". LLMJudge picks its prompt by this name.
attributeinputsdict[str, JsonValue]The data to grade, for example the reply and the reference answer.
attributeallowed_labelslist[str]The labels that the judge can choose from. There is at least one.
attributecontext_prefixstr= ''Text that comes before the prompt, for example source text, or an empty string. With a
prefix, LLMJudge first checks that the request fits the model's context window.
JudgeResult
modelJudgeResultA judge's chosen label and explanation.
attributelabelstrThe chosen label, one of the request's allowed_labels.
attributedetailstr= ''The judge's explanation of the label.
attributelimitationslist[str]= list()The reasons for a limited answerability. Only a task with the name "filters.answerable"
fills them, and no built-in criterion uses that task.
attributesource_hintslist[str]= list()Ids of sources that can help a reviewer. Only a task with the name "filters.answerable"
fills them, and no built-in criterion uses that task.
LanguageDetector
protocolLanguageDetectorA language detector, which identifies the language of a single sentence.
The reply.language criterion calls it for each sentence of the reply. LangidDetector of soev_evals.judges
is the built-in detector.
methoddetect(text) -> strReturn a language code or raise LanguageDetectionError.
paramtextstrOne sentence.
Returns
strThe language code, for example "nl". The criterion compares it with its language parameter, without
case.
Raises:
LanguageDetectionError: The detector cannot identify the language.
RunArchive
protocolRunArchiveA run archive, which persists and retrieves complete runs for resume and rescore.
A run has a manifest, a journal of completed attempts, the evidence of each attempt and a report. The runner
calls these synchronous methods in a worker thread. FileRunArchive of soev_evals.run is the built-in archive.
methodcreate(run_id, manifest) -> NoneCreate a run with its manifest.
paramrun_idstrThe id of the new run.
parammanifestMapping[str, JsonValue]The manifest of the run, as JSON.
Raises:
ArchiveError: The run exists already, or the archive cannot write it.
methodappend(run_id, attempt) -> NoneAppend a completed attempt to the journal.
The runner saves the evidence of the attempt before it appends the attempt.
paramrun_idstrThe id of the run.
paramattemptMapping[str, JsonValue]The completed attempt, as JSON.
Raises:
ArchiveError: The archive cannot write the journal.
methodattempts(run_id) -> Sequence[Mapping[str, JsonValue]]Read the completed attempt journal.
paramrun_idstrThe id of the run.
Returns
Sequence[Mapping[str, JsonValue]]The completed attempts, in the order of the journal.
Raises:
ArchiveError: The archive cannot read the journal.
methodsave_evidence(run_id, case_id, *, attempt, evidence) -> NonePersist evidence for a numbered attempt.
paramrun_idstrThe id of the run.
paramcase_idstrThe id of the case.
paramattemptintThe number of the attempt, from 1.
paramevidenceEvidenceThe evidence of the attempt.
Raises:
ArchiveError: The archive cannot write the evidence.
methodload_evidence(run_id, case_id, *, attempt) -> EvidenceRead evidence for a numbered attempt.
paramrun_idstrThe id of the run.
paramcase_idstrThe id of the case.
paramattemptintThe number of the attempt, from 1.
Returns
EvidenceThe evidence that save_evidence saved.
Raises:
ArchiveError: The archive cannot read the evidence.
methodmanifest(run_id) -> Mapping[str, JsonValue]Read a run's manifest.
paramrun_idstrThe id of the run.
Returns
Mapping[str, JsonValue]The manifest that create saved.
Raises:
ArchiveError: The archive cannot read the manifest.
methodsave_report(run_id, report) -> NonePersist the aggregate report.
A rescore calls it again and replaces the report.
paramrun_idstrThe id of the run.
paramreportMapping[str, JsonValue]The report, as JSON.
Raises:
ArchiveError: The archive cannot write the report.
Tracker
protocolTrackerA tracker, which publishes run records to an optional tracking destination.
The runner logs a warning for each exception of a tracker and continues, so a tracker cannot make a run fail.
methodstartasync (run_id, manifest) -> NoneBegin tracking a run and its manifest.
paramrun_idstrThe id of the run.
parammanifestMapping[str, JsonValue]The manifest of the run, as JSON.
methodrecordasync (run_id, attempt) -> NonePublish one attempt and its evidence.
paramrun_idstrThe id of the run.
paramattemptMapping[str, JsonValue]The attempt as the journal records it, with its evidence under the key "evidence".
methodfinishasync (run_id, report) -> NonePublish the report and finish tracking.
paramrun_idstrThe id of the run.
paramreportMapping[str, JsonValue]The report of the run, as JSON.
ArmError
errorArmErrorThe system under test could not complete a conversation.
An Arm or a Conversation raises it. The runner records it as the failure of the attempt's evidence,
and the run continues.
SetupError
errorSetupErrorCase preparation, collection or cleanup failed.
A CaseSetup raises it. The runner records it as the failure of the attempt's evidence, and the run
continues.
JudgeError
errorJudgeErrorThe judge could not produce a usable result.
A Judge raises it. LLMJudge raises it when it has no prompt for the task, and when the model's
answer is not valid JSON or has a label that the request does not allow. It also raises it when a request with a
context prefix does not fit the model's context window. A built-in criterion records it as a verdict with the
status "error".
LanguageDetectionError
errorLanguageDetectionErrorThe detector could not identify a sentence's language.
A LanguageDetector raises it, for example for an empty sentence. The reply.language criterion
records it as a verdict with the status "error".
ArchiveError
errorArchiveErrorRun archive data could not be read or written.
A RunArchive raises it. The runner also raises it when a resumed run does not match its archive.
Base classes
The models of this package are frozen pydantic models, and its errors share one base class.
FrozenModel
modelFrozenModelA frozen value object that rejects unexpected fields.
It is the pydantic base of the public models of soev_evals. A field name that the model does not
declare fails validation, and so do the float values inf and nan. An instance cannot change after it is
made. Subclass it for the parameter model of your own CriterionKind, so that a typo in a suite file fails when
the suite loads.
EvalsError
errorEvalsErrorAn evaluation operation could not be completed.
It is the base class of the errors of soev_evals. Catch it to handle any of them.