judgevet.domain
Status: draft.
judgevet.domain
Domain layer - pure types and business logic.
Examples:
from judgevet.domain import Noul, Choice, Score
from judgevet.domain.answers import NoulAnswer, ChoiceAnswer, ScoreAnswer
# Create a yes/no question
noul = Noul(
instructions="Is this a valid question?",
criteria={"true": "It is valid", "false": "It is not valid"},
)
# Create a choice question
choice = Choice(
criteria={"a": "Option A", "b": "Option B"},
instructions="Choose one:",
)
# Create a score question
score = Score(
criteria=["Poor", "Fair", "Good", "Excellent"],
instructions="Rate the response:",
)
# Answer a question
answer = NoulAnswer(noul=0.75)
assert 0.0 <= answer.noul <= 1.0
See Also
- judgevet.domain.answers: Answer types
- judgevet.domain.errors: Error types
- judgevet.domain.questions: Question types
- judgevet.domain.response: Response container
- judgevet.domain.usage: Usage tracking
Attributes:
| Name | Type | Description |
|---|---|---|
Answer |
type
|
Union type of all answer types. |
Choice |
type
|
Question type for multiple choice. |
ChoiceAnswer |
type
|
Answer type for multiple choice. |
JevAuthError |
type
|
401/403 authentication errors. |
JevError |
type
|
Base exception for all Jev errors. |
JevRateLimitError |
type
|
429 rate limit errors. |
JevRequestError |
type
|
4xx client request errors. |
JevResponseError |
type
|
2xx with unparseable body. |
JevServiceError |
type
|
5xx or transport errors. |
Noul |
type
|
Question type for yes/no. |
NoulAnswer |
type
|
Answer type for yes/no. |
Question |
type
|
Base question type. |
Score |
type
|
Question type for numeric rating. |
ScoreAnswer |
type
|
Answer type for numeric rating. |
SystemOneResponse |
type
|
API response container. |
Usage |
type
|
API usage tracking. |
Answer = NoulAnswer | ChoiceAnswer | ScoreAnswer
module-attribute
Union type for all possible answers.
Question = Noul | Choice | Score
module-attribute
A question object.
Choice
A question that selects between named alternatives.
See: https://docs.typesafe.ai/primitives/choice
Attributes:
| Name | Type | Description |
|---|---|---|
criteria |
Mapping[str, str | dict | Sequence | None]
|
Labels mapped to descriptions. |
instructions |
str | dict | Sequence | None
|
The question to ask. |
Examples:
question = Choice(
criteria={"a": "Option A", "b": "Option B"},
instructions="Choose one:",
)
assert len(question.criteria) == 2
See Also
- judgevet.domain.questions.Question: Union type for all questions
- judgevet.domain.answers.ChoiceAnswer: Answer type for this question
__init__(criteria, instructions=None)
Initialize a Choice question.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
criteria
|
Mapping[str, str | dict[str, Any] | Sequence[Any] | None]
|
Labels mapped to descriptions, or None for undescribed labels. |
required |
instructions
|
str | dict[str, Any] | Sequence[Any] | None
|
The question to ask. |
None
|
__repr__()
Return a string representation of the Choice.
ChoiceAnswer
dataclass
A selected choice with probabilities and confidence.
See: https://docs.typesafe.ai/primitives/choice
This frozen dataclass validates values in __post_init__. Confidence and
probabilities must be finite, numeric and within [0.0, 1.0], excluding booleans.
Probabilities must sum to 1.0 and contain the selected choice.
Attributes:
| Name | Type | Description |
|---|---|---|
choice |
str
|
The name of the choice with highest probability. |
confidence |
float
|
Confidence in the selected choice, from 0 to 1. |
probabilities |
dict[str, float]
|
Probability of each choice, keyed by choice name. |
Examples:
answer = ChoiceAnswer(
choice="yes",
confidence=0.8,
probabilities={"yes": 0.8, "no": 0.2},
)
assert answer.choice in answer.probabilities
See Also
- judgevet.domain.answers.Answer: Union type for all answers
- judgevet.domain.response.SystemOneResponse: Response container
__post_init__()
Validate choice, confidence, and probabilities.
Ensures confidence is finite in [0.0, 1.0], all probability values are finite in [0.0, 1.0], probabilities sum to 1.0, and choice is a key.
Raises:
| Type | Description |
|---|---|
TypeError
|
If confidence or any probability is nonnumeric or a boolean. |
ValueError
|
If a numeric value is nonfinite or outside [0.0, 1.0]. Also raised if probabilities do not sum to 1.0 or choice is missing from probabilities. |
JevAuthError
Bases: JevError
Authentication error - 401 or 403.
Raised when the API key is missing, invalid, or lacks the necessary permissions to access the requested resource.
Attributes:
| Name | Type | Description |
|---|---|---|
args |
tuple
|
Standard exception arguments containing the message. |
status_code |
int
|
Always 401 or 403. |
Examples:
error = JevAuthError("Unauthorized", 401)
assert error.retryable is False
retryable
property
Return True if the error is retryable.
Returns:
| Type | Description |
|---|---|
bool
|
False for auth errors (401, 403). |
__init__(message, status_code)
Initialize the auth error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
The error message. |
required |
status_code
|
int
|
The HTTP status code (401 or 403). |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If status_code is not 401 or 403. |
JevError
Bases: Exception
Base exception for all Jev-related errors.
This is the parent of the service-error hierarchy, not local policy errors or every HTTPX exception. Redirects can propagate raw HTTPX status errors. The base class always reports retryable=False; subclasses override it.
Attributes:
| Name | Type | Description |
|---|---|---|
args |
tuple
|
Standard exception arguments containing the message. |
status_code |
int | None
|
The HTTP status code if available, None otherwise. |
retryable |
bool
|
Advisory retry classification; False on this base class. |
Examples:
error = JevError("Something went wrong", 500)
assert error.retryable is False
retryable
property
Return True if the error is retryable.
Returns:
| Type | Description |
|---|---|
bool
|
False on this base class, independent of status_code. |
__init__(message, status_code=None)
Initialize the error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
The error message. |
required |
status_code
|
int | None
|
The HTTP status code if available. |
None
|
Examples:
error = JevError("Something went wrong", 500)
assert error.retryable is False
__str__()
Return string representation.
JevRateLimitError
Bases: JevError
Rate limit exceeded - 429.
Raised when the API returns a 429 status code indicating the client has exceeded the rate limit. The caller chooses retry limits; the adapter defaults to one attempt.
See: https://docs.typesafe.ai/api.md
Attributes:
| Name | Type | Description |
|---|---|---|
args |
tuple
|
Standard exception arguments containing the message. |
status_code |
int
|
Always 429. |
Examples:
error = JevRateLimitError("Rate limit exceeded", 429)
assert error.retryable is True
retryable
property
Return True if the error is retryable.
Returns:
| Type | Description |
|---|---|
bool
|
True for rate limit errors (429). |
__init__(message, status_code)
Initialize the rate limit error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
The error message. |
required |
status_code
|
int
|
The HTTP status code (must be 429). |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If status_code is not 429. |
JevRequestError
Bases: JevError
Client request error - 4xx (except 401/403).
Raised when the API rejects the request due to invalid parameters, malformed input, or other client-side issues.
Attributes:
| Name | Type | Description |
|---|---|---|
args |
tuple
|
Standard exception arguments containing the message. |
status_code |
int
|
The HTTP status code (4xx). |
Examples:
error = JevRequestError("Bad Request", 400)
assert error.retryable is False
retryable
property
Return True if the error is retryable.
Returns:
| Type | Description |
|---|---|
bool
|
False for request errors (4xx). |
__init__(message, status_code)
Initialize the request error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
The error message. |
required |
status_code
|
int
|
The HTTP status code (4xx). |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If status_code is not a 4xx code or is 401/403. |
JevResponseError
Bases: JevError
Response parsing error - 2xx with invalid body.
Raised when the API returns a 2xx status code but the response body cannot be parsed into the expected domain types. This is a local parsing failure. Live calls verify only the fields they exercised; other fields remain inferred from documentation.
Attributes:
| Name | Type | Description |
|---|---|---|
args |
tuple
|
Standard exception arguments containing the message. |
status_code |
int
|
Always 2xx. |
Examples:
error = JevResponseError("Parse error", 200)
assert error.retryable is False
retryable
property
Return True if the error is retryable.
Returns:
| Type | Description |
|---|---|
bool
|
False for response errors (2xx with invalid body). |
__init__(message, status_code)
Initialize the response error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
The error message. |
required |
status_code
|
int
|
The HTTP status code (2xx). |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If status_code is not a 2xx code. |
JevServiceError
Bases: JevError
Server service error - 5xx or transport failures.
Raised when the API returns a 5xx status code or when a transport error occurs (network issues, timeouts, etc.).
Attributes:
| Name | Type | Description |
|---|---|---|
args |
tuple
|
Standard exception arguments containing the message. |
status_code |
int | None
|
The HTTP status code (5xx) or None for transport errors. |
Examples:
error = JevServiceError("Internal Server Error", 500)
assert error.retryable is True
retryable
property
Return True if the error is retryable.
Returns:
| Type | Description |
|---|---|
bool
|
True for service errors (5xx) and transport failures (status None). |
__init__(message, status_code=None)
Initialize the service error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
The error message. |
required |
status_code
|
int | None
|
The HTTP status code (5xx) or None for transport errors. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If status_code is not a 5xx code when provided. |
Noul
A yes/no question with optional descriptions for either outcome.
See: https://docs.typesafe.ai/primitives/noul
Attributes:
| Name | Type | Description |
|---|---|---|
instructions |
str | dict | Sequence | None
|
Question or statement to evaluate. |
criteria |
dict | None
|
Optional. An object with |
Examples:
question = Noul(
instructions="Is this a valid question?",
criteria={"true": "It is valid", "false": "It is not valid"},
)
assert question.instructions is not None
See Also
- judgevet.domain.questions.Question: Union type for all questions
- judgevet.domain.answers.NoulAnswer: Answer type for this question
__init__(instructions=None, criteria=None)
Initialize a Noul question.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
instructions
|
str | dict[str, Any] | Sequence[Any] | None
|
The yes/no question or statement to evaluate. |
None
|
criteria
|
dict[str, Any] | None
|
Optional descriptions of the yes and no outcomes. |
None
|
__repr__()
Return a string representation of the Noul.
NoulAnswer
dataclass
A yes/no answer with probability of true.
See: https://docs.typesafe.ai/primitives/noul
This is a frozen dataclass with validation in __post_init__ to ensure
noul is finite and numeric (not bool) and in [0.0, 1.0].
Attributes:
| Name | Type | Description |
|---|---|---|
noul |
float
|
Probability of a yes answer or true statement, from 0 to 1. |
Examples:
answer = NoulAnswer(noul=0.75)
assert 0.0 <= answer.noul <= 1.0
See Also
- judgevet.domain.answers.Answer: Union type for all answers
- judgevet.domain.response.SystemOneResponse: Response container
__post_init__()
Validate noul is finite, numeric and in [0.0, 1.0], excluding bool.
Raises:
| Type | Description |
|---|---|
TypeError
|
If noul is not a numeric type or is a bool. |
ValueError
|
If noul is nonfinite or outside [0.0, 1.0]. |
Score
A question that assigns a score using an ordered rubric.
See: https://docs.typesafe.ai/primitives/score
Attributes:
| Name | Type | Description |
|---|---|---|
criteria |
Sequence[str | dict | Sequence]
|
Ordered list of descriptions. |
instructions |
str | dict | Sequence | None
|
What the model should rate. |
Examples:
question = Score(
criteria=["Poor", "Fair", "Good", "Excellent"],
instructions="Rate the response:",
)
assert len(question.criteria) >= 2
See Also
- judgevet.domain.questions.Question: Union type for all questions
- judgevet.domain.answers.ScoreAnswer: Answer type for this question
__init__(criteria, instructions=None)
Initialize a Score question.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
criteria
|
Sequence[str | dict[str, Any] | Sequence[Any]]
|
Ordered list of descriptions, one per score from zero. |
required |
instructions
|
str | dict[str, Any] | Sequence[Any] | None
|
What the model should rate. |
None
|
__repr__()
Return a string representation of the Score.
ScoreAnswer
dataclass
A scored response with rubric and probabilities.
See: https://docs.typesafe.ai/primitives/score
This frozen dataclass validates values in __post_init__. Score must lie in
legend range and be finite and numeric, excluding booleans. Confidence and
probabilities must also be finite and numeric, excluding booleans, and within
[0.0, 1.0]. Probabilities must sum to 1.0, and legend/probability keys must match.
Attributes:
| Name | Type | Description |
|---|---|---|
score |
float
|
Expected score (probability-weighted average of rubric levels). |
confidence |
float
|
Confidence in the score, from 0 to 1. |
legend |
dict[int, str]
|
Rubric descriptions keyed by integer score. |
probabilities |
dict[int, float]
|
Probability of each score level, keyed by integer score. |
Examples:
answer = ScoreAnswer(
score=2.5,
confidence=0.9,
legend={1: "poor", 2: "fair", 3: "good"},
probabilities={1: 0.1, 2: 0.2, 3: 0.7},
)
assert 1 <= len(answer.legend) == len(answer.probabilities)
See Also
- judgevet.domain.answers.Answer: Union type for all answers
- judgevet.domain.response.SystemOneResponse: Response container
__post_init__()
Validate score, confidence, legend, and probabilities.
Checks finite score against legend range and finite confidence against [0.0, 1.0]. Checks finite numeric probabilities against [0.0, 1.0] and their sum against 1.0. Checks that legend/probability keys match.
Raises:
| Type | Description |
|---|---|
TypeError
|
If any numeric key or value is not the expected type or is a boolean. |
ValueError
|
If any numeric value is nonfinite, score is outside legend range, or confidence or any probability is outside [0.0, 1.0]. Also raised if probabilities do not sum to 1.0 or legend/probability keys do not match. |
SystemOneResponse
dataclass
Answers grouped by question type with model and usage metadata.
See: https://docs.typesafe.ai/concepts/system-one
Frozen instances prevent attribute reassignment. The original answers dictionary remains mutable. Each typed property filters its current contents into a fresh dictionary. Editing that returned mapping leaves answers unchanged; the answer objects and their nested dictionaries remain shared. Missing or wrong-variant keys raise normal KeyError when indexed.
Attributes:
| Name | Type | Description |
|---|---|---|
model |
str
|
The model used to answer the request. |
usage |
Usage
|
Token usage for the request. |
answers |
dict[str, Answer]
|
All answer objects keyed by question name. |
nouls |
dict[str, NoulAnswer]
|
Current Noul answers in a fresh dictionary. |
choices |
dict[str, ChoiceAnswer]
|
Current Choice answers in a fresh dictionary. |
scores |
dict[str, ScoreAnswer]
|
Current Score answers in a fresh dictionary. |
Examples:
from judgevet.domain.answers import NoulAnswer
from judgevet.domain.usage import Usage
response = SystemOneResponse(
model="jev-latest",
usage=Usage(input_tokens=100, output_tokens=50),
answers={"q1": NoulAnswer(noul=0.75)},
)
assert response.model == "jev-latest"
See Also
- judgevet.domain.answers: Answer types
- judgevet.domain.usage: Usage metadata
answers = field(default_factory=dict)
class-attribute
instance-attribute
All answer objects keyed by question name.
The field is always a dict (empty if no answers were provided).
choices
property
Return a fresh plain dict of ChoiceAnswer entries from self.answers.
Returns:
| Type | Description |
|---|---|
dict[str, ChoiceAnswer]
|
A new dict preserving insertion order with exact ChoiceAnswer object references. |
dict[str, ChoiceAnswer]
|
Empty if no matching entries; KeyError on wrong-variant indexing. |
nouls
property
Return a fresh plain dict of NoulAnswer entries from self.answers.
Returns:
| Type | Description |
|---|---|
dict[str, NoulAnswer]
|
A new dict preserving insertion order with exact NoulAnswer object references. |
dict[str, NoulAnswer]
|
Empty if no matching entries; KeyError on wrong-variant indexing. |
scores
property
Return a fresh plain dict of ScoreAnswer entries from self.answers.
Returns:
| Type | Description |
|---|---|
dict[str, ScoreAnswer]
|
A new dict preserving insertion order with exact ScoreAnswer object references. |
dict[str, ScoreAnswer]
|
Empty if no matching entries; KeyError on wrong-variant indexing. |
__repr__()
Return a string representation of the SystemOneResponse.
Returns:
| Type | Description |
|---|---|
str
|
A string representation including model, usage, and answers. |
Usage
dataclass
Token counts for a request.
See: https://docs.typesafe.ai/api.md
This is a frozen dataclass. Values must be non-negative if provided.
Attributes:
| Name | Type | Description |
|---|---|---|
input_tokens |
int | None
|
Number of input tokens used. |
output_tokens |
int | None
|
Number of output tokens used. |
Examples:
usage = Usage(input_tokens=100, output_tokens=50)
assert usage.input_tokens == 100
See Also
- judgevet.domain.response.SystemOneResponse: Response container
__post_init__()
Validate token counts.
Raises:
| Type | Description |
|---|---|
TypeError
|
If a token count is not int (bool rejected). |
ValueError
|
If a token count is negative. |