solvi.core.knowledge.failures¶
Do not repeat an action or a plan that failed recently: a hard check with an expiry and a bound.
Failure memory: do not repeat an action or a plan that failed in the last N steps (or episodes) — a built-in hard check, with an expiry and a bound.
from solvi.core.knowledge import FailureMemory
fm = FailureMemory(window=20, unit="steps", max_blocked=8, min_open=1)
fm.install(cat, plan="plan", then={"plan": "ask_person"}) # a hard check over the given fact "recent_failures"
for step in ...:
res = system.ask({"situation": s, **fm.given(options=plans_on_offer)}) # the memory as a given fact: replays
ok = run(res["plan"].answer)
fm.failed(res["plan"].answer, why="the door stayed shut") if not ok else fm.succeeded(res["plan"].answer)
fm.step()
Every agent that proposes plans with a model needs this, and writes it by hand (a field report on solvi: "the model
proposed the plan that had just failed"). In benchmarks/knowledge/toy_crafting.py a proposer without memory repeated a
failure in the same situation 29.3 times per 100 steps, 0.53 behind this check. Here it is data plus a pure check: given() puts the blocked plans into the
decision's input, the check reads them, the trace records them, and the decision replays.
Bounded on purpose. A memory that only tightens can block everything (a learned gate fed by its own failures lowers
itself episode after episode: benchmarks/knowledge/risk_dungeon.py, arm protect_unbounded). So:
- expiry: a failure blocks its plan for window steps (or episodes), then the plan may be tried again;
- max_blocked: at most this many plans are blocked at once (the most recent failures);
- min_open: given the plans on offer (options), at least this many stay open — the oldest failures among them are
let through first;
- evidence reopens: succeeded(plan) removes its block at once.
Plans are compared by their JSON form (a string, a tuple of actions, a dict).
FailureMemory ¶
See the module docstring. window: how long a failure blocks its plan, in unit ("steps" or "episodes");
max_blocked: plans blocked at once at most; min_open: plans on offer that always stay open; store: a
KnowledgeStore every failure and success is journaled into.
blocked ¶
The plans blocked now → {key: {"failed_at", "expires_at", "why", "n"}}: failures within the window, at most
max_blocked (the most recent), and — when options (the plans on offer) are given — at least min_open of them
left open (the oldest failures among them are let through).
given ¶
The memory as a given fact for a decision: {"recent_failures": {"unit", "at", "blocked"}}.
check ¶
A Prediction for trying plan now: "refuse" (hard) when it is blocked, else "accept".
check_function
staticmethod
¶
The hard check as a catalog function of the facts plan and given (names as you choose them).
install ¶
Declare the hard check in a catalog: when plan is a recent failure it is False with the reason, and the
questions in then get their answers (a constant or a function of facts) — see Catalog.check. → the function.
plan_key ¶
A plan as the memory compares it: a string as it is, anything else as its JSON form (sorted keys).