solvi.core.knowledge.actions¶
The action model: what an environment accepts, refuses and changes, learned conservatively from outcomes over an
explicit vocabulary (ActionModel, ConservativeActionModel, Vocabulary, Prediction).
The action model: what an environment accepts, refuses and changes — learned conservatively from outcomes, over an explicit vocabulary of conditions.
from solvi.core.knowledge import ConservativeActionModel, Vocabulary
vocab = Vocabulary({"status": lambda state, args: state["orders"][args["order_id"]]["status"],
"own_payment": lambda state, args: args["payment_id"] in state["user"]["payments"]})
am = ConservativeActionModel(vocab)
am.observe(state, "cancel_order", {"order_id": "A1"}, accepted=False) # the environment refused it
am.observe(state2, "cancel_order", {"order_id": "A2"}, accepted=True, effect={"status": "cancelled"})
p = am.predict(state3, "cancel_order", {"order_id": "A3"})
p.verdict, p.risk, p.support, p.reason, p.hard, p.effects # "accept" | "refuse" | "unknown", ...
The ActionModel protocol: observe(state, action, args, accepted, effect=None), predict(state, action, args) → Prediction, fingerprint(). Every prediction carries both a verdict and an estimate (the risk if the action is taken and the number of cases behind it); a RiskPolicy (solvi.core.knowledge.risk) turns them into take / avoid / ask System 2.
ConservativeActionModel: per action, the values each condition of the vocabulary took in accepted transitions are "allowed"; a refused transition is explained by the conditions whose value was never accepted, and the minimal such sets are its refusal signatures. predict says "accept" when every condition holds a value seen accepted, "refuse" when the violated conditions contain a signature, and "unknown" otherwise — and for an action never observed, or one with refusals the vocabulary cannot explain (then only exactly seen condition vectors are answered). "unknown" hands over to System 2 or a person. Effects: predicted when every accepted transition of the same condition vector (else of the action) had the same effect.
Scope, stated plainly — this is what "stable" covers and what it does not: - vocabulary-bound: the model can only learn checks the vocabulary can express. On τ-bench retail probes (benchmarks/knowledge/taubench_action_model.py), with a vocabulary written by someone who had read the tools' code, refusal precision and recall were 1.000 (7,602 of 7,602 answered held-out refusals) and it abstained on 0.26%; with pair features left out it abstained on 2.6%, with money comparisons left out on 10.7% and made 1 false refusal (a condition vector seen only refused, which a shorter vocabulary cannot tell from an accepted one); - it learns what the environment checks: a rule the environment does not enforce (confirm with the customer, authenticate first, policy-only rules) is never refused by it — those must come from a written policy (agenda gates, hard checks); - necessary conditions transfer; sufficient conditions are not promised to: conditions that held at every success by accident (an item carried, a material nearby, a place's name) make rules learned in one world over-conservative in a new one — "unknown", not wrong (benchmarks/knowledge/toy_crafting.py, arm km_place); - learned from an agent's own traces behind a hand guard it sees few refusals and abstains often: sound where it answers, little coverage.
Vocabulary: {name: predicate(state, args) → a JSON scalar}. A predicate that cannot be read (a KeyError, an entity not
looked up) gives MISSING, which is never "allowed" until an accepted transition shows it — so the model says "unknown"
there instead of guessing. hard= names conditions whose violation is a hard rule (instant harm, a policy): a refusal
resting on one is a hard prediction that no risk policy trades. The vocabulary's fingerprint (each predicate's code) is
in the model's fingerprint and in every action item it commits to a KnowledgeStore.
Prediction
dataclass
¶
Prediction(verdict: str, risk: float = 0.0, support: int = 0, reason: str = '', hard: bool = False, effects: object = None, action: str | None = None)
What an action model (or any knowledge item) says about taking an action: the verdict, the estimated risk if the
action is taken (probability of refusal / harm × its severity), the number of cases behind the estimate (support;
-1: a rate from a written spec), the reason, whether a hard rule stands behind a refusal (never traded), and the
predicted effects (None: not predicted).
ActionModel ¶
Bases: Protocol
What an environment accepts, refuses and changes.
You implement: observe(state, action, args, accepted, effect=None) (what the environment did),
predict(state, action, args) → Prediction (verdict accept / refuse / unknown, risk, support, reason, hard,
effects) and fingerprint() (changes with what it learned).
You get for free: its refusals as hard checks, "unknown" handed to System 2 or a person, the prediction compared
with the outcome, a risk policy deciding on its estimate; solvi.testing.conformance.check_action_model checks it.
Stability: stable (ConservativeActionModel's scope: vocabulary-bound, learns what the environment checks, sufficient conditions not promised to transfer).
Vocabulary ¶
The conditions an action model may learn from: {name: predicate(state, args) → JSON scalar}. hard: names whose violation is a hard rule; only: {action: [names]} — the conditions read for that action (default: all).
features ¶
The condition values for one (state, action, args) → tuple (MISSING where a predicate cannot be read).
ConservativeActionModel ¶
See the module docstring. vocabulary: a Vocabulary; severity: the harm of a refused / failed action in your
unit (a number, {action: number}, default 1.0) — risk = P(refused) × severity; store: a KnowledgeStore that every
observation is journaled into (and from which replay rebuilds the model).
observe ¶
What the environment did with this call: accepted (with effect, any JSON value — the change it made) or
refused. → the prediction made before this observation (compare it with what happened: a surprise is counted
in surprises).
predict ¶
→ Prediction(verdict, risk, support, reason, hard, effects) for taking action with args in state.
summary ¶
What the model learned about one action: allowed values per condition, refusal signatures with their counts, unexplained refusals, transitions, the effect (when constant).
fingerprint ¶
The vocabulary's fingerprint and every transition the model learned from.
commit ¶
Write each action's learned model into a KnowledgeStore as an "action" item (source "outcome", by "environment"; the vocabulary's predicate fingerprints in the body): the newer version refutes the older one. → {action: item id}.
replay
classmethod
¶
The model rebuilt from the observations journaled in store with this vocabulary (same fingerprint).