soev_evals.judges
An LLM judge with the prompts of the built-in judge criteria, and an offline language detector.
The judge criteria of soev_evals.criteria ask a Judge for a label, and reply.language asks a
LanguageDetector for the language of each sentence. This package holds the built-in implementations of both
ports. Give them in the CriterionContext of a run. For the CLI, a runtime provider gives the judge, and the CLI
uses LangidDetector when the provider gives no detector.
Judges
LLMJudge grades with the prompts of this package through a model that you connect with a JudgeLLM adapter.
LLMJudge
classLLMJudge(llm, prompts)A Judge that asks a model, through a JudgeLLM adapter, for a label.
For each request, the system message is the context prefix and then the prompt of the request's task. The user
message is the request's inputs as JSON. It asks the model for a JSON object with a label from the allowed labels
and a detail. Then it validates the answer.
Make a judge that uses llm with prompts.
paramllmJudgeLLMThe model that answers, through an adapter for your model provider.
parampromptsMapping[str, str]The prompt of each task, by task name, for example from load_prompts. The judge copies it.
methodjudgeasync (request) -> JudgeResultReturn the label of the model for request.
paramrequestJudgeRequestThe task, the inputs and the allowed labels.
Returns
JudgeResultThe label that the model chose, one of request.allowed_labels, and its explanation.
Raises:
JudgeError:promptshas no prompt for the task, or the model's answer is not valid JSON of the schema, or has a label that the request does not allow. Also when the request has a context prefix and the model's context window is unknown or too small.
JudgeLLM
protocolJudgeLLMThe model of an LLMJudge: an adapter that sends one chat request and returns the JSON answer.
Write an adapter for your model provider. complete must raise JudgeError for a failed call: a criterion
records it as a verdict with the status "error", but any other exception stops the run.
Example
from collections.abc import Mapping
import httpx
from pydantic import JsonValue
from soev_evals.core import JudgeError
from soev_evals.judges import LLMJudge, load_prompts
class ChatCompletionsLLM:
context_window = 128_000
def __init__(self, client: httpx.AsyncClient, model: str) -> None:
self._client = client
self._model = model
async def complete(self, *, system: str, user: str, schema: Mapping[str, JsonValue]) -> str:
schema_format = {"name": "verdict", "schema": dict(schema)}
body = {
"model": self._model,
"messages": [{"role": "system", "content": system}, {"role": "user", "content": user}],
"response_format": {"type": "json_schema", "json_schema": schema_format},
}
try:
response = await self._client.post("chat/completions", json=body)
response.raise_for_status()
return response.json()["choices"][0]["message"]["content"]
except (httpx.HTTPError, KeyError, IndexError, ValueError) as exc:
raise JudgeError(f"judge call failed: {type(exc).__name__}") from exc
client = httpx.AsyncClient(base_url="http://localhost:8000/v1/")
judge = LLMJudge(ChatCompletionsLLM(client, "my-judge-model"), load_prompts())attributecontext_windowint | NoneThe context window of the model, in tokens, or None when unknown.
LLMJudge reads it only for a request with a context prefix. It then refuses the request when the window is
unknown, or when the estimated tokens do not fit with a safety margin.
methodcompleteasync (*, system, user, schema) -> strSend one chat request and return the text of the answer.
paramsystemstrThe system message: the context prefix of the request, then the prompt of the task.
paramuserstrThe user message: the inputs of the request, as JSON.
paramschemaMapping[str, JsonValue]The JSON schema that the answer must satisfy. Give it to the model as a structured output format when the provider supports one.
Returns
strThe text of the answer. LLMJudge parses it as JSON and validates it.
Raises:
JudgeError: The call failed.
load_prompts
functionload_prompts() -> dict[str, str]Read the prompt of each built-in judge task.
The package ships one prompt file for each built-in judge kind: behaviour.expected,
compare.equivalent, nuggets.coverage, privacy.names and rubric.judge.
Returns
dict[str, str]The text of each prompt, by task name. Give it to LLMJudge, and its hashes to the run manifest.
prompt_shas
functionprompt_shas(prompts) -> dict[str, str]Hash the exact prompt and rubric content used by a run.
The run manifest records the hashes, so a resumed run fails when a prompt changed.
parampromptsMapping[str, str]The text of each prompt or rubric, by name.
Returns
dict[str, str]The SHA-256 hex digest of each text, by the same name. Give it as shas to build_manifest of
soev_evals.run.
Language detection
LangidDetector identifies the language offline, with a bundled model.
LangidDetector
classLangidDetector()A LanguageDetector with the bundled model of py3langid.
The model runs offline and gives the same answer for the same text. The CLI gives this detector to the
reply.language criterion when the runtime provider gives none.
Load the bundled model once, so that the first detect call is not slow.
methoddetect(text) -> strReturn an ISO language code for nonempty linguistic input.
paramtextstrOne sentence.
Returns
strThe ISO 639-1 code of the language, for example "nl".
Raises:
LanguageDetectionError:textis empty or blank, or the model finds no language in it.