Skip to content

Answers

ask returns a SystemOneOutput:

response.model      # the model that answered
response.usage      # input_tokens, output_tokens, cost (when reported)
response.id         # provider request id, when there is one
response.answers    # {question name: answer}, one entry per question asked

answers is heterogeneous — a noul question yields a NoulAnswer, a choice question a ChoiceAnswer, and so on. Three cached views narrow it by type so you get a precise type without an isinstance dance:

response.nouls["urgent"].noul
response.choices["topic"].choice
response.scores["severity"].score

NoulAnswer

answer = response.nouls["urgent"]
answer.noul         # 0.0–1.0: the probability the statement holds
answer.confidence   # |2p - 1| — 0 for a coin flip, 1 when certain either way

noul is a probability, not a boolean. Threshold it where your application wants the cut, and use confidence to route the uncertain middle to a human:

if answer.confidence < 0.7:
    escalate()
elif answer.noul > 0.5:
    page_someone()

ChoiceAnswer

answer = response.choices["topic"]
answer.choice          # the selected label
answer.probabilities   # {label: probability}, when the provider reports them
answer.confidence

ScoreAnswer

answer = response.scores["severity"]
answer.score           # probability-weighted expectation, not an argmax
answer.legend          # {index: criterion}, when reported
answer.probabilities   # {index: probability}, when reported
answer.confidence

The score is an expectation

With criteria ["minor", "normal", "major", "critical"], a score of 1.7 means the mass sits between normal (1) and major (2) and leans toward major. It is not the index of the most likely criterion — a model torn between minor and critical returns roughly 1.5, which no single criterion claims. Check confidence before treating a mid-range score as a verdict.

Confidence

confidence is whatever the provider reports; the hosted API always sends one for choice and score. When an answer arrives with probabilities but no confidence, it is derived from them, and every answer type puts it on the same scale: how certain is the value this answer reports?

Answer Derived as 1.0 0.0
noul \|2p - 1\| certain either way a coin flip
choice (pmax - 1/k) / (1 - 1/k) the label is certain uniform over the labels
score 1 - E\|i - mode\| / D, D that of a uniform all mass on one level as spread as a uniform, or worse

These match the confidence the hosted API sends. score cannot use the choice rule, because the score is an expectation rather than a level. It measures how far the mass sits from the most likely level instead, so a distribution split between the end levels — whose expectation lands in a valley no level claims — scores 0.0, while one split between neighbours scores 0.25.

Unusable probabilities leave confidence unset

Probabilities that are not a distribution — logits, a truncated top-k, a vector that does not sum to 1 — leave confidence as None rather than producing a number. Treat None as "unknown", never as confident.

Serialization

Every schema is a frozen pydantic model, so the usual methods apply. Pass exclude_none=True to keep unset optional fields off the wire:

response.model_dump(exclude_none=True)
response.model_dump_json(exclude_none=True)