Skip to content

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 None to abstain;
  • a hard check failed and has no then entry for it;
  • it has no rule and no trained head.