Asking: System and Response¶
from solvi import System
system = System(cat, questions)
res = system.ask(init_state) # all questions
res = system.ask(init_state, ["ship"]) # a subset: questions=["ship"] (or "ship")
system.ask(init_state, questions=None, *, workers=None, order=None, store=True, early_exit=None); aask takes the same
questions and keyword-only order, store, timeout, speculate, early_exit. (names= is the 0.7 spelling of
questions=: deprecated, removed in 0.9.)
System(catalog, questions, *, workers=1, order="default", producers="declared", learn=None, input_model=None,
strategist=None, storage=None, timeout=None, cost_policy="declared", lang="en", early_exit=True); learn: after every ask,
update the parts' measured costs and the learned order / producer policies from what happened (default: on when
order or producers is "learned"); the others are described where they matter. storage (a TraceStorage or a path) saves every
response with its whole trace, hash-chained across responses (see Storing decisions).
Every option after questions is keyword-only. With a JSON-lines store every ask appends one line with the hash of
init_state, the answers, the flow and the hash of every trace record, plus the whole response and the chain fields
(journal="file.jsonl", the older spelling of storage="file.jsonl", is deprecated and goes in 0.9). ask(..., store=False) skips saving one response. inputs: a pydantic model of
init_state (see Types); ask also takes a BaseModel instance.
Response¶
| Field | Content |
|---|---|
res["q"] |
the Result for question q |
res.results |
dict of all results |
res.flow |
the planned flow; print(res.flow) lists the steps and why each was taken |
res.flow.per_question |
question -> names of the parts in its flow |
res.flow.skipped |
catalog part -> why it was not executed (inputs unavailable, or not needed) |
res.flow.unresolved |
question -> facts that nothing can compute from this init_state |
res.state_text() |
a printable listing (computed_state in 0.7): each computed fact, its value, quote offsets, extraction confidence, errors |
res.values |
dict of all fact values (inputs and computed) |
res.trace |
the hash-chained trace (see The trace) |
res.audit(q=None) |
what each answer rests on and which safeguards fired (see Grounded decisions) |
res.safeguards |
the safeguard events of this response |
res.ms |
decision time in milliseconds |
res.confidence |
overall confidence: the probability that every answered question is right (product of the answers' confidences, errors taken as independent — conservative when constraints tie answers together); abstained questions are left out |
res.complete, res.weakest |
did every question get an answer; (question, confidence) of the least confident answer |
res.overall |
all of it as data: {confidence, weakest, answered, abstained, complete, feasible, not_stated, by_kind} (by_kind: per answer kind the answered count and the product of their confidences); also in to_json() and the first line of print(res.audit()) |
res.not_stated |
the questions answered "not stated" (solvi.Unknown) |
res.model_dump(), res.to_json() |
the response as data / JSON; Response.from_json(text, catalog=...) loads it back (see Types) |
Result¶
| Field | Content |
|---|---|
.answer |
one of the options (a tuple for multi-label and rank, a number for an estimate, the coerced text for a span, solvi.Unknown for "not stated"), or None when abstaining |
.confidence |
float in [0, 1] |
.why |
the reason: rule inputs and their values, or the top feature contributions of a learned head, or why it abstained or was forced |
.status |
"ok", "forced" (a hard check decided) or "abstain" |
.probs |
class probabilities for answers from a learned head or a model decision (empty for plain rules) |
.provenance, .source |
where the answer came from: computed (a rule, a hard check), learned (a head, a learned rule), decided (a model-backed rule); and which rule / check / head |
.guard, .repaired |
the safeguard that settled it (hard_check, outside_options, low_confidence, grounding, type_rejected, evidence_missing, ...), and (previous answer, constraints) if joint decoding changed it |
.kind |
the answer type's kind (yes_no, choice, ordinal, multi, span, rank, estimate) |
.evidence, .span |
the supporting quotes [Quote(text, start, end, source)]; a span answer's Quote |
.not_stated, .interval, .scores, .extra |
the answer is solvi.Unknown; an estimate's interval; a ranking's scores; the details as data |
A question abstains when:
- a fact it needs cannot be computed from
init_state(nothing in the catalog produces it); - a part it depends on raised an exception (the error is kept in the trace);
- its rule returned a value outside the options, or returned
Noneto abstain; - a hard check failed and has no
thenentry for it; - it has no rule and no trained head.